summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2024-10-22 13:04:22 +0200
committerDavid Lönnhager <david.l@mullvad.net>2024-10-23 09:39:19 +0200
commit8e69580b83a1bed06fbdc57a6109662ecb872052 (patch)
tree38be862c49c6ab4aa4eb9e88009ba2d23b733143
parent26db6201e280deebae0a64dc8335acd0ee73bd3f (diff)
downloadmullvadvpn-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.rs32
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;