tor: bridge connection line, save changes on modal close
This commit is contained in:
parent
206c89520c
commit
e379a7bf86
6 changed files with 142 additions and 112 deletions
|
@ -134,6 +134,8 @@ transport:
|
||||||
tor_settings: Tor Settings
|
tor_settings: Tor Settings
|
||||||
bridges: Bridges
|
bridges: Bridges
|
||||||
bridges_desc: Setup bridges to bypass Tor network censorship if usual connection is not working.
|
bridges_desc: Setup bridges to bypass Tor network censorship if usual connection is not working.
|
||||||
|
bin_file: 'Binary file:'
|
||||||
|
conn_line: 'Connection line:'
|
||||||
network:
|
network:
|
||||||
self: Network
|
self: Network
|
||||||
type: 'Network type:'
|
type: 'Network type:'
|
||||||
|
|
|
@ -134,6 +134,8 @@ transport:
|
||||||
tor_settings: Настройки Tor
|
tor_settings: Настройки Tor
|
||||||
bridges: Мосты
|
bridges: Мосты
|
||||||
bridges_desc: Настройте мосты для обхода цензуры сети Tor, если обычное соединение не работает.
|
bridges_desc: Настройте мосты для обхода цензуры сети Tor, если обычное соединение не работает.
|
||||||
|
bin_file: 'Исполняемый файл:'
|
||||||
|
conn_line: 'Строка подключения:'
|
||||||
network:
|
network:
|
||||||
self: Сеть
|
self: Сеть
|
||||||
type: 'Тип сети:'
|
type: 'Тип сети:'
|
||||||
|
|
|
@ -54,8 +54,12 @@ pub struct WalletTransport {
|
||||||
/// QR code address image [`Modal`] content.
|
/// QR code address image [`Modal`] content.
|
||||||
qr_code_content: QrCodeContent,
|
qr_code_content: QrCodeContent,
|
||||||
|
|
||||||
|
/// Flag to check if Tor settings were changed.
|
||||||
|
tor_settings_changed: bool,
|
||||||
/// Tor bridge binary path edit text.
|
/// Tor bridge binary path edit text.
|
||||||
bridge_bin_path_edit: String,
|
bridge_bin_path_edit: String,
|
||||||
|
/// Tor bridge connection line edit text.
|
||||||
|
bridge_conn_line_edit: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WalletTab for WalletTransport {
|
impl WalletTab for WalletTransport {
|
||||||
|
@ -118,10 +122,10 @@ impl WalletTransport {
|
||||||
pub fn new(addr: String) -> Self {
|
pub fn new(addr: String) -> Self {
|
||||||
// Setup Tor bridge binary path edit text.
|
// Setup Tor bridge binary path edit text.
|
||||||
let bridge = TorConfig::get_bridge();
|
let bridge = TorConfig::get_bridge();
|
||||||
let bridge_bin_path_edit = if let Some(b) = bridge {
|
let (bin_path, conn_line) = if let Some(b) = bridge {
|
||||||
b.binary_path()
|
(b.binary_path(), b.connection_line())
|
||||||
} else {
|
} else {
|
||||||
"".to_string()
|
("".to_string(), "".to_string())
|
||||||
};
|
};
|
||||||
Self {
|
Self {
|
||||||
tor_sending: Arc::new(RwLock::new(false)),
|
tor_sending: Arc::new(RwLock::new(false)),
|
||||||
|
@ -132,7 +136,9 @@ impl WalletTransport {
|
||||||
address_error: false,
|
address_error: false,
|
||||||
modal_just_opened: false,
|
modal_just_opened: false,
|
||||||
qr_code_content: QrCodeContent::new(addr),
|
qr_code_content: QrCodeContent::new(addr),
|
||||||
bridge_bin_path_edit
|
tor_settings_changed: false,
|
||||||
|
bridge_bin_path_edit: bin_path,
|
||||||
|
bridge_conn_line_edit: conn_line,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +203,7 @@ impl WalletTransport {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw Tor transport header content.
|
/// Draw Tor transport header content.
|
||||||
fn tor_header_ui(&self, ui: &mut egui::Ui, wallet: &Wallet) {
|
fn tor_header_ui(&mut self, ui: &mut egui::Ui, wallet: &Wallet) {
|
||||||
// Setup layout size.
|
// Setup layout size.
|
||||||
let mut rect = ui.available_rect_before_wrap();
|
let mut rect = ui.available_rect_before_wrap();
|
||||||
rect.set_height(78.0);
|
rect.set_height(78.0);
|
||||||
|
@ -212,10 +218,12 @@ impl WalletTransport {
|
||||||
// Draw button to setup Tor transport.
|
// Draw button to setup Tor transport.
|
||||||
let button_rounding = View::item_rounding(0, 2, true);
|
let button_rounding = View::item_rounding(0, 2, true);
|
||||||
View::item_button(ui, button_rounding, GEAR_SIX, None, || {
|
View::item_button(ui, button_rounding, GEAR_SIX, None, || {
|
||||||
|
self.tor_settings_changed = false;
|
||||||
// Show Tor settings modal.
|
// Show Tor settings modal.
|
||||||
Modal::new(TOR_SETTINGS_MODAL)
|
Modal::new(TOR_SETTINGS_MODAL)
|
||||||
.position(ModalPosition::CenterTop)
|
.position(ModalPosition::CenterTop)
|
||||||
.title(t!("transport.tor_settings"))
|
.title(t!("transport.tor_settings"))
|
||||||
|
.closeable(false)
|
||||||
.show();
|
.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -285,19 +293,6 @@ impl WalletTransport {
|
||||||
let os = OperatingSystem::from_target_os();
|
let os = OperatingSystem::from_target_os();
|
||||||
let show_bridges = os != OperatingSystem::Android;
|
let show_bridges = os != OperatingSystem::Android;
|
||||||
|
|
||||||
// Restart running service or rebuild client.
|
|
||||||
let restart_or_rebuild = || {
|
|
||||||
let service_id = &wallet.identifier();
|
|
||||||
if Tor::is_service_running(service_id) {
|
|
||||||
if let Ok(key) = wallet.secret_key() {
|
|
||||||
let api_port = wallet.foreign_api_port().unwrap();
|
|
||||||
Tor::restart_service(api_port, key, service_id);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Tor::rebuild_client();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
if show_bridges {
|
if show_bridges {
|
||||||
let bridge = TorConfig::get_bridge();
|
let bridge = TorConfig::get_bridge();
|
||||||
|
@ -312,13 +307,13 @@ impl WalletTransport {
|
||||||
let value = if bridge.is_some() {
|
let value = if bridge.is_some() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let b = TorConfig::get_snowflake();
|
let default_bridge = TorConfig::get_obfs4();
|
||||||
self.bridge_bin_path_edit = b.binary_path();
|
self.bridge_bin_path_edit = default_bridge.binary_path();
|
||||||
Some(b)
|
self.bridge_conn_line_edit = default_bridge.connection_line();
|
||||||
|
Some(default_bridge)
|
||||||
};
|
};
|
||||||
TorConfig::save_bridge(value);
|
TorConfig::save_bridge(value);
|
||||||
// Restart running service or rebuild client.
|
self.tor_settings_changed = true;
|
||||||
restart_or_rebuild();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -330,50 +325,79 @@ impl WalletTransport {
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
ui.columns(2, |columns| {
|
ui.columns(2, |columns| {
|
||||||
columns[0].vertical_centered(|ui| {
|
columns[0].vertical_centered(|ui| {
|
||||||
// Draw Snowflake bridge selector.
|
|
||||||
let snowflake = TorConfig::get_snowflake();
|
|
||||||
let name = snowflake.protocol_name().to_uppercase();
|
|
||||||
View::radio_value(ui, &mut bridge, snowflake, name);
|
|
||||||
});
|
|
||||||
columns[1].vertical_centered(|ui| {
|
|
||||||
// Draw Obfs4 bridge selector.
|
// Draw Obfs4 bridge selector.
|
||||||
let obfs4 = TorConfig::get_obfs4();
|
let obfs4 = TorConfig::get_obfs4();
|
||||||
let name = obfs4.protocol_name().to_uppercase();
|
let name = obfs4.protocol_name().to_uppercase();
|
||||||
View::radio_value(ui, &mut bridge, obfs4, name);
|
View::radio_value(ui, &mut bridge, obfs4, name);
|
||||||
});
|
});
|
||||||
|
columns[1].vertical_centered(|ui| {
|
||||||
|
// Draw Snowflake bridge selector.
|
||||||
|
let snowflake = TorConfig::get_snowflake();
|
||||||
|
let name = snowflake.protocol_name().to_uppercase();
|
||||||
|
View::radio_value(ui, &mut bridge, snowflake, name);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
ui.add_space(12.0);
|
ui.add_space(12.0);
|
||||||
|
|
||||||
// Check if bridge type was changed to save.
|
// Check if bridge type was changed to save.
|
||||||
if current_bridge != bridge {
|
if current_bridge != bridge {
|
||||||
|
self.tor_settings_changed = true;
|
||||||
TorConfig::save_bridge(Some(bridge.clone()));
|
TorConfig::save_bridge(Some(bridge.clone()));
|
||||||
self.bridge_bin_path_edit = bridge.binary_path();
|
self.bridge_bin_path_edit = bridge.binary_path();
|
||||||
// Restart running service or rebuild client.
|
self.bridge_conn_line_edit = bridge.connection_line();
|
||||||
restart_or_rebuild();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw binary path text edit.
|
// Draw binary path text edit.
|
||||||
let bin_edit_id = Id::from(modal.id).with(wallet.get_config().id).with("_bin_edit");
|
let bin_edit_id = Id::from(modal.id)
|
||||||
let bin_edit_opts = TextEditOptions::new(bin_edit_id).paste();
|
.with(wallet.get_config().id)
|
||||||
|
.with("_bin_edit");
|
||||||
|
let bin_edit_opts = TextEditOptions::new(bin_edit_id)
|
||||||
|
.paste()
|
||||||
|
.no_focus();
|
||||||
let bin_edit_before = self.bridge_bin_path_edit.clone();
|
let bin_edit_before = self.bridge_bin_path_edit.clone();
|
||||||
ui.vertical_centered(|ui| {
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(RichText::new(t!("transport.bin_file"))
|
||||||
|
.size(17.0)
|
||||||
|
.color(Colors::INACTIVE_TEXT));
|
||||||
|
ui.add_space(6.0);
|
||||||
View::text_edit(ui, cb, &mut self.bridge_bin_path_edit, bin_edit_opts);
|
View::text_edit(ui, cb, &mut self.bridge_bin_path_edit, bin_edit_opts);
|
||||||
|
ui.add_space(6.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check if text was changed to save bin path.
|
// Draw connection line text edit.
|
||||||
if bin_edit_before != self.bridge_bin_path_edit {
|
let conn_edit_id = Id::from(modal.id)
|
||||||
|
.with(wallet.get_config().id)
|
||||||
|
.with("_conn_edit");
|
||||||
|
let conn_edit_opts = TextEditOptions::new(conn_edit_id)
|
||||||
|
.paste()
|
||||||
|
.scan_qr()
|
||||||
|
.no_focus();
|
||||||
|
let conn_edit_before = self.bridge_conn_line_edit.clone();
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(RichText::new(t!("transport.conn_line"))
|
||||||
|
.size(17.0)
|
||||||
|
.color(Colors::INACTIVE_TEXT));
|
||||||
|
ui.add_space(6.0);
|
||||||
|
View::text_edit(ui, cb, &mut self.bridge_conn_line_edit, conn_edit_opts);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if bin path or connection line text was changed to save bridge.
|
||||||
|
if conn_edit_before != self.bridge_conn_line_edit ||
|
||||||
|
bin_edit_before != self.bridge_bin_path_edit {
|
||||||
|
let bin_path = self.bridge_bin_path_edit.clone();
|
||||||
|
let conn_line = self.bridge_conn_line_edit.clone();
|
||||||
let b = match bridge {
|
let b = match bridge {
|
||||||
TorBridge::Snowflake(_) => {
|
TorBridge::Snowflake(_, _) => {
|
||||||
TorBridge::Snowflake(self.bridge_bin_path_edit.clone())
|
TorBridge::Snowflake(bin_path, conn_line)
|
||||||
},
|
},
|
||||||
TorBridge::Obfs4(_) => {
|
TorBridge::Obfs4(_, _) => {
|
||||||
TorBridge::Obfs4(self.bridge_bin_path_edit.clone())
|
TorBridge::Obfs4(bin_path, conn_line)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
TorConfig::save_bridge(Some(b));
|
TorConfig::save_bridge(Some(b));
|
||||||
// Restart running service or rebuild client.
|
self.tor_settings_changed = true;
|
||||||
restart_or_rebuild();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.add_space(2.0);
|
ui.add_space(2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,6 +420,19 @@ impl WalletTransport {
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
ui.vertical_centered_justified(|ui| {
|
ui.vertical_centered_justified(|ui| {
|
||||||
View::button(ui, t!("close"), Colors::WHITE, || {
|
View::button(ui, t!("close"), Colors::WHITE, || {
|
||||||
|
if self.tor_settings_changed {
|
||||||
|
self.tor_settings_changed = false;
|
||||||
|
// Restart running service or rebuild client.
|
||||||
|
let service_id = &wallet.identifier();
|
||||||
|
if Tor::is_service_running(service_id) {
|
||||||
|
if let Ok(key) = wallet.secret_key() {
|
||||||
|
let api_port = wallet.foreign_api_port().unwrap();
|
||||||
|
Tor::restart_service(api_port, key, service_id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Tor::rebuild_client();
|
||||||
|
}
|
||||||
|
}
|
||||||
modal.close();
|
modal.close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -33,8 +33,14 @@ impl Default for TorConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
bridge: None,
|
bridge: None,
|
||||||
obfs4: TorBridge::Obfs4(TorBridge::DEFAULT_OBFS4_BIN_PATH.to_string()),
|
obfs4: TorBridge::Obfs4(
|
||||||
snowflake: TorBridge::Snowflake(TorBridge::DEFAULT_SNOWFLAKE_BIN_PATH.to_string()),
|
TorBridge::DEFAULT_OBFS4_BIN_PATH.to_string(),
|
||||||
|
TorBridge::DEFAULT_OBFS4_CONN_LINE.to_string()
|
||||||
|
),
|
||||||
|
snowflake: TorBridge::Snowflake(
|
||||||
|
TorBridge::DEFAULT_SNOWFLAKE_BIN_PATH.to_string(),
|
||||||
|
TorBridge::DEFAULT_SNOWFLAKE_CONN_LINE.to_string()
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,10 +95,10 @@ impl TorConfig {
|
||||||
if bridge.is_some() {
|
if bridge.is_some() {
|
||||||
let bridge = bridge.unwrap();
|
let bridge = bridge.unwrap();
|
||||||
match &bridge {
|
match &bridge {
|
||||||
TorBridge::Snowflake(_) => {
|
TorBridge::Snowflake(_, _) => {
|
||||||
w_tor_config.snowflake = bridge
|
w_tor_config.snowflake = bridge
|
||||||
}
|
}
|
||||||
TorBridge::Obfs4(_) => {
|
TorBridge::Obfs4(_, _) => {
|
||||||
w_tor_config.obfs4 = bridge
|
w_tor_config.obfs4 = bridge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,8 +104,12 @@ impl Tor {
|
||||||
let bridge = TorConfig::get_bridge();
|
let bridge = TorConfig::get_bridge();
|
||||||
if let Some(b) = bridge {
|
if let Some(b) = bridge {
|
||||||
match b {
|
match b {
|
||||||
super::TorBridge::Snowflake(path) => Self::build_snowflake(&mut builder, path),
|
super::TorBridge::Snowflake(path, conn) => {
|
||||||
super::TorBridge::Obfs4(path) => Self::build_obfs4(&mut builder, path),
|
Self::build_snowflake(&mut builder, path, conn)
|
||||||
|
},
|
||||||
|
super::TorBridge::Obfs4(path, conn) => {
|
||||||
|
Self::build_obfs4(&mut builder, path, conn)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Setup address filter.
|
// Setup address filter.
|
||||||
|
@ -184,6 +188,7 @@ impl Tor {
|
||||||
|
|
||||||
// Restart Onion service.
|
// Restart Onion service.
|
||||||
pub fn restart_service(port: u16, key: SecretKey, id: &String) {
|
pub fn restart_service(port: u16, key: SecretKey, id: &String) {
|
||||||
|
println!("restart service");
|
||||||
Self::stop_service(id);
|
Self::stop_service(id);
|
||||||
Self::rebuild_client();
|
Self::rebuild_client();
|
||||||
Self::start_service(port, key, id)
|
Self::start_service(port, key, id)
|
||||||
|
@ -283,8 +288,10 @@ impl Tor {
|
||||||
.body(Body::from(data))
|
.body(Body::from(data))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Send request.
|
// Send request.
|
||||||
|
println!("Send request");
|
||||||
let duration = match http.request(req).await {
|
let duration = match http.request(req).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
println!("OK!");
|
||||||
// Remove service from starting.
|
// Remove service from starting.
|
||||||
let mut w_services = TOR_SERVER_STATE.starting_services.write();
|
let mut w_services = TOR_SERVER_STATE.starting_services.write();
|
||||||
w_services.remove(&service_id);
|
w_services.remove(&service_id);
|
||||||
|
@ -292,6 +299,7 @@ impl Tor {
|
||||||
Duration::from_millis(15000)
|
Duration::from_millis(15000)
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
println!("err: {}", e);
|
||||||
// Restart service on 3rd error.
|
// Restart service on 3rd error.
|
||||||
errors_count += 1;
|
errors_count += 1;
|
||||||
if errors_count == MAX_ERRORS {
|
if errors_count == MAX_ERRORS {
|
||||||
|
@ -350,6 +358,8 @@ impl Tor {
|
||||||
let mut w_services = TOR_SERVER_STATE.running_services.write();
|
let mut w_services = TOR_SERVER_STATE.running_services.write();
|
||||||
w_services.insert(id.clone(), (service.clone(), proxy.clone()));
|
w_services.insert(id.clone(), (service.clone(), proxy.clone()));
|
||||||
|
|
||||||
|
println!("run_service_proxy done");
|
||||||
|
|
||||||
// Start proxy for launched service.
|
// Start proxy for launched service.
|
||||||
client
|
client
|
||||||
.runtime()
|
.runtime()
|
||||||
|
@ -417,77 +427,35 @@ impl Tor {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_snowflake(builder: &mut TorClientConfigBuilder, bin_path: String) {
|
fn build_snowflake(builder: &mut TorClientConfigBuilder, bin_path: String, conn_line: String) {
|
||||||
// Add a single bridge to the list of bridges, from a bridge line.
|
let bridge_line = format!("Bridge {}", conn_line);
|
||||||
// This line comes from https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/blob/main/projects/common/bridges_list.snowflake.txt
|
if let Ok(bridge) = bridge_line.parse() {
|
||||||
// this is a real bridge line you can use as-is, after making sure it's still up to date with
|
builder.bridges().bridges().push(bridge);
|
||||||
// above link.
|
}
|
||||||
const BRIDGE1_LINE : &str = "Bridge snowflake 192.0.2.4:80 8838024498816A039FCBBAB14E6F40A0843051FA fingerprint=8838024498816A039FCBBAB14E6F40A0843051FA url=https://1098762253.rsc.cdn77.org/ fronts=www.cdn77.com,www.phpmyadmin.net ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.net:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn";
|
|
||||||
let bridge_1: BridgeConfigBuilder = BRIDGE1_LINE.parse().unwrap();
|
|
||||||
builder.bridges().bridges().push(bridge_1);
|
|
||||||
|
|
||||||
// Add a second bridge, built by hand. We use the 2nd bridge line from above, but modify some
|
|
||||||
// parameters to use AMP Cache instead of Fastly as a signaling channel. The difference in
|
|
||||||
// configuration is detailed in
|
|
||||||
// https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/tree/main/client#amp-cache
|
|
||||||
// let mut bridge2_builder = BridgeConfigBuilder::default();
|
|
||||||
// bridge2_builder
|
|
||||||
// .transport("snowflake")
|
|
||||||
// .push_setting(
|
|
||||||
// "fingerprint",
|
|
||||||
// "8838024498816A039FCBBAB14E6F40A0843051FA"
|
|
||||||
// )
|
|
||||||
// .push_setting("url", "https://snowflake-broker.torproject.net/")
|
|
||||||
// .push_setting("ampcache", "https://cdn.ampproject.org/")
|
|
||||||
// .push_setting("front", "www.google.com")
|
|
||||||
// .push_setting(
|
|
||||||
// "ice",
|
|
||||||
// "stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.net:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478",
|
|
||||||
// )
|
|
||||||
// .push_setting("utls-imitate", "hellorandomizedalpn");
|
|
||||||
// bridge2_builder.set_addrs(vec!["192.0.2.4:80".parse().unwrap()]);
|
|
||||||
// bridge2_builder.set_ids(vec!["8838024498816A039FCBBAB14E6F40A0843051FA".parse().unwrap()]);
|
|
||||||
// // Now insert the second bridge into our config builder.
|
|
||||||
// builder.bridges().bridges().push(bridge2_builder);
|
|
||||||
|
|
||||||
// Now configure an snowflake transport. (Requires the "pt-client" feature)
|
// Now configure an snowflake transport. (Requires the "pt-client" feature)
|
||||||
let mut transport = TransportConfigBuilder::default();
|
let mut transport = TransportConfigBuilder::default();
|
||||||
transport
|
transport
|
||||||
.protocols(vec!["snowflake".parse().unwrap()])
|
.protocols(vec!["snowflake".parse().unwrap()])
|
||||||
// this might be named differently on some systems, this should work on Debian, but Archlinux is known to use `snowflake-pt-client` instead for instance.
|
// this might be named differently on some systems, this should work on Debian,
|
||||||
|
// but Archlinux is known to use `snowflake-pt-client` instead for instance.
|
||||||
.path(CfgPath::new(bin_path.into()))
|
.path(CfgPath::new(bin_path.into()))
|
||||||
.run_on_startup(true);
|
.run_on_startup(true);
|
||||||
builder.bridges().set_transports(vec![transport]);
|
builder.bridges().set_transports(vec![transport]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_obfs4(builder: &mut TorClientConfigBuilder, bin_path: String) {
|
fn build_obfs4(builder: &mut TorClientConfigBuilder, bin_path: String, conn_line: String) {
|
||||||
// This bridge line is made up for demonstration, and won't work.
|
let bridge_line = format!("Bridge {}", conn_line);
|
||||||
const BRIDGE1_LINE : &str = "Bridge obfs4 82.64.231.149:9300 1B4382D598392D72F85F8D3D05CE1A6BB0EF0300 cert=+NYVc7iy+d6lj/NZZY2ZPFR6IHA/Mw5XSwFxvPFSespE+A/e5BOv2kgGbJbDzkkRfCsGGg iat-mode=0";
|
if let Ok(bridge) = bridge_line.parse() {
|
||||||
let bridge_1: BridgeConfigBuilder = BRIDGE1_LINE.parse().unwrap();
|
builder.bridges().bridges().push(bridge);
|
||||||
// This is where we pass `BRIDGE1_LINE` into the BridgeConfigBuilder.
|
}
|
||||||
builder.bridges().bridges().push(bridge_1);
|
|
||||||
|
|
||||||
// Add a second bridge, built by hand. This way is harder.
|
|
||||||
// This bridge is made up for demonstration, and won't work.
|
|
||||||
// let mut bridge2_builder = BridgeConfigBuilder::default();
|
|
||||||
// bridge2_builder
|
|
||||||
// .transport("obfs4")
|
|
||||||
// .push_setting("iat-mode", "1")
|
|
||||||
// .push_setting(
|
|
||||||
// "cert",
|
|
||||||
// "YnV0IHNvbWV0aW1lcyB0aGV5IGFyZSByYW5kb20u8x9aQG/0cIIcx0ItBcTqiSXotQne+Q"
|
|
||||||
// );
|
|
||||||
// bridge2_builder.set_addrs(vec!["198.51.100.25:443".parse().unwrap()]);
|
|
||||||
// bridge2_builder.set_ids(vec!["7DD62766BF2052432051D7B7E08A22F7E34A4543".parse().unwrap()]);
|
|
||||||
// // Now insert the second bridge into our config builder.
|
|
||||||
// builder.bridges().bridges().push(bridge2_builder);
|
|
||||||
|
|
||||||
// Now configure an obfs4 transport. (Requires the "pt-client" feature)
|
// Now configure an obfs4 transport. (Requires the "pt-client" feature)
|
||||||
let mut transport = TransportConfigBuilder::default();
|
let mut transport = TransportConfigBuilder::default();
|
||||||
transport
|
transport
|
||||||
.protocols(vec!["obfs4".parse().unwrap()])
|
.protocols(vec!["obfs4".parse().unwrap()])
|
||||||
// Specify either the name or the absolute path of pluggable transport client binary, this
|
// Specify either the name or the absolute path of pluggable transport client binary,
|
||||||
// may differ from system to system.
|
// this may differ from system to system.
|
||||||
.path(CfgPath::new(bin_path.into()))
|
.path(CfgPath::new(bin_path.into()))
|
||||||
.run_on_startup(true);
|
.run_on_startup(true);
|
||||||
builder.bridges().transports().push(transport);
|
builder.bridges().transports().push(transport);
|
||||||
|
|
|
@ -14,32 +14,47 @@
|
||||||
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Tor network bridge type with binary path.
|
/// Tor network bridge type.
|
||||||
#[derive(Serialize, Deserialize, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Clone, PartialEq)]
|
||||||
pub enum TorBridge {
|
pub enum TorBridge {
|
||||||
Snowflake(String),
|
/// Obfs4 bridge with connection line and binary path.
|
||||||
Obfs4(String)
|
Obfs4(String, String),
|
||||||
|
/// Snowflake bridge with connection line and binary path.
|
||||||
|
Snowflake(String, String)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TorBridge {
|
impl TorBridge {
|
||||||
/// Default Snowflake protocol client binary path.
|
|
||||||
pub const DEFAULT_SNOWFLAKE_BIN_PATH: &'static str = "/usr/bin/snowflake-client";
|
|
||||||
/// Default Obfs4 protocol proxy client binary path.
|
/// Default Obfs4 protocol proxy client binary path.
|
||||||
pub const DEFAULT_OBFS4_BIN_PATH: &'static str = "/usr/bin/obfs4proxy";
|
pub const DEFAULT_OBFS4_BIN_PATH: &'static str = "/usr/bin/obfs4proxy";
|
||||||
|
/// Default Snowflake protocol client binary path.
|
||||||
|
pub const DEFAULT_SNOWFLAKE_BIN_PATH: &'static str = "/usr/bin/snowflake-client";
|
||||||
|
|
||||||
|
/// Default Obfs4 protocol connection line.
|
||||||
|
pub const DEFAULT_OBFS4_CONN_LINE: &'static str = "obfs4 obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=0LDeJH4JzMDtkJJrFphJCiPqKx7loozKN7VNfuukMGfHO0Z8OGdzHVkhVAOfo1mUdv9cMg iat-mode=0";
|
||||||
|
/// Default Snowflake protocol connection line.
|
||||||
|
pub const DEFAULT_SNOWFLAKE_CONN_LINE: &'static str = "snowflake 192.0.2.4:80 8838024498816A039FCBBAB14E6F40A0843051FA fingerprint=8838024498816A039FCBBAB14E6F40A0843051FA url=https://1098762253.rsc.cdn77.org/ fronts=www.cdn77.com,www.phpmyadmin.net ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.net:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn";
|
||||||
|
|
||||||
/// Get bridge protocol name.
|
/// Get bridge protocol name.
|
||||||
pub fn protocol_name(&self) -> String {
|
pub fn protocol_name(&self) -> String {
|
||||||
match *self {
|
match *self {
|
||||||
TorBridge::Snowflake(_) => "snowflake".to_string(),
|
TorBridge::Obfs4(_, _) => "obfs4".to_string(),
|
||||||
TorBridge::Obfs4(_) => "obfs4".to_string()
|
TorBridge::Snowflake(_, _) => "snowflake".to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get bridge client binary path.
|
/// Get bridge client binary path.
|
||||||
pub fn binary_path(&self) -> String {
|
pub fn binary_path(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
TorBridge::Snowflake(path) => path.clone(),
|
TorBridge::Obfs4(path, _) => path.clone(),
|
||||||
TorBridge::Obfs4(path) => path.clone()
|
TorBridge::Snowflake(path, _) => path.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get bridge client connection line.
|
||||||
|
pub fn connection_line(&self) -> String {
|
||||||
|
match self {
|
||||||
|
TorBridge::Obfs4(_, line) => line.clone(),
|
||||||
|
TorBridge::Snowflake(_, line) => line.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue