diff options
| author | David Lönnhager <david.l@mullvad.net> | 2024-10-22 13:04:22 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2024-10-23 09:39:19 +0200 |
| commit | 8e69580b83a1bed06fbdc57a6109662ecb872052 (patch) | |
| tree | 38be862c49c6ab4aa4eb9e88009ba2d23b733143 | |
| parent | 26db6201e280deebae0a64dc8335acd0ee73bd3f (diff) | |
| download | mullvadvpn-8e69580b83a1bed06fbdc57a6109662ecb872052.tar.xz mullvadvpn-8e69580b83a1bed06fbdc57a6109662ecb872052.zip | |
Use sendto and recvfrom instead of connecting Shadowsocks socket
connect() seems to bind to a particular interface, which breaks the
connection when roaming
| -rw-r--r-- | tunnel-obfuscation/src/shadowsocks.rs | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/tunnel-obfuscation/src/shadowsocks.rs b/tunnel-obfuscation/src/shadowsocks.rs index 87622506f5..fc0f466029 100644 --- a/tunnel-obfuscation/src/shadowsocks.rs +++ b/tunnel-obfuscation/src/shadowsocks.rs @@ -122,7 +122,7 @@ async fn run_forwarding( .await .map_err(Error::WaitForUdpClient)?; - let shadowsocks = connect_shadowsocks(remote_socket, shadowsocks_endpoint).await?; + let shadowsocks = connect_shadowsocks(remote_socket, shadowsocks_endpoint)?; let shadowsocks = Arc::new(shadowsocks); let local_udp = Arc::new(local_udp_socket); @@ -132,9 +132,15 @@ async fn run_forwarding( let mut client = tokio::spawn(handle_outgoing( shadowsocks.clone(), local_udp.clone(), + shadowsocks_endpoint, wg_addr.clone(), )); - let mut server = tokio::spawn(handle_incoming(shadowsocks, local_udp, wg_addr)); + let mut server = tokio::spawn(handle_incoming( + shadowsocks, + local_udp, + shadowsocks_endpoint, + wg_addr, + )); tokio::select! { _ = shutdown_rx => { @@ -150,15 +156,10 @@ async fn run_forwarding( Ok(()) } -async fn connect_shadowsocks( +fn connect_shadowsocks( remote_socket: UdpSocket, shadowsocks_endpoint: SocketAddr, ) -> std::result::Result<ProxySocket, Error> { - remote_socket - .connect(shadowsocks_endpoint) - .await - .map_err(Error::ConnectShadowsocks)?; - let ss_context = Context::new_shared(ServerType::Local); let ss_config: ServerConfig = ServerConfig::new( shadowsocks_endpoint, @@ -216,6 +217,7 @@ async fn wait_for_local_udp_client(udp_listener: &UdpSocket) -> io::Result<()> { async fn handle_outgoing( ss_write: Arc<ProxySocket>, local_udp_read: Arc<UdpSocket>, + ss_addr: SocketAddr, wg_addr: Address, ) { let mut rx_buffer = vec![0u8; u16::MAX as usize]; @@ -229,7 +231,10 @@ async fn handle_outgoing( } }; - if let Err(error) = ss_write.send(&wg_addr, &rx_buffer[0..read_n]).await { + if let Err(error) = ss_write + .send_to(ss_addr, &wg_addr, &rx_buffer[0..read_n]) + .await + { if is_fatal_socket_error(&error) { log::error!("Failed to write to Shadowsocks client: {error}"); break; @@ -242,13 +247,18 @@ async fn handle_outgoing( async fn handle_incoming( ss_read: Arc<ProxySocket>, local_udp_write: Arc<UdpSocket>, + ss_addr: SocketAddr, wg_addr: Address, ) { let mut rx_buffer = vec![0u8; u16::MAX as usize]; loop { - let (read_n, addr, _ctrl) = match ss_read.recv(&mut rx_buffer).await { - Ok(read_n) => read_n, + let (read_n, _rx_addr, addr, _ctrl) = match ss_read.recv_from(&mut rx_buffer).await { + Ok((read_n, rx_addr, addr, _ctrl)) if rx_addr == ss_addr => { + (read_n, rx_addr, addr, _ctrl) + } + // Ignore incoming from unexpected source + Ok(_) => continue, Err(error) => { log::error!("Failed to read from Shadowsocks client: {error}"); break; |
