Skip to content

Commit c99ed3a

Browse files
committed
UDP IPv6 outbound socket should disable IPV6_V6ONLY
1 parent 66dc357 commit c99ed3a

File tree

5 files changed

+52
-9
lines changed

5 files changed

+52
-9
lines changed

crates/shadowsocks/src/net/sys/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ fn socket_bind_dual_stack_inner(socket: &Socket, addr: &SocketAddr, ipv6_only: b
100100
socket.bind(&saddr)?;
101101
} else {
102102
if let Err(err) = socket.set_only_v6(false) {
103-
warn!("failed to set IPV6_V6ONLY: false for listener, error: {}", err);
103+
warn!("failed to set IPV6_V6ONLY: false for socket, error: {}", err);
104104

105105
// This is not a fatal error, just warn and skip
106106
}
@@ -115,7 +115,7 @@ fn socket_bind_dual_stack_inner(socket: &Socket, addr: &SocketAddr, ipv6_only: b
115115
);
116116

117117
if let Err(err) = socket.set_only_v6(true) {
118-
warn!("failed to set IPV6_V6ONLY: true for listener, error: {}", err);
118+
warn!("failed to set IPV6_V6ONLY: true for socket, error: {}", err);
119119

120120
// This is not a fatal error, just warn and skip
121121
}

crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ use std::{
99

1010
use log::{error, warn};
1111
use pin_project::pin_project;
12+
use socket2::{Domain, Protocol, Socket, Type};
1213
use tokio::{
1314
io::{AsyncRead, AsyncWrite, ReadBuf},
1415
net::{TcpSocket, TcpStream as TokioTcpStream, UdpSocket},
1516
};
1617
use tokio_tfo::TfoStream;
1718

1819
use crate::net::{
19-
sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect},
20+
sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect, socket_bind_dual_stack},
2021
AddrFamily,
2122
ConnectOpts,
2223
};
@@ -223,7 +224,17 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) ->
223224
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
224225
};
225226

226-
let socket = UdpSocket::bind(bind_addr).await?;
227+
let socket = if af != AddrFamily::Ipv6 {
228+
UdpSocket::bind(bind_addr).await?
229+
} else {
230+
let socket = Socket::new(Domain::for_address(bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
231+
socket_bind_dual_stack(&socket, &bind_addr, false)?;
232+
233+
// UdpSocket::from_std requires socket to be non-blocked
234+
socket.set_nonblocking(true)?;
235+
UdpSocket::from_std(socket.into())?
236+
};
237+
227238
if let Err(err) = set_disable_ip_fragmentation(af, &socket) {
228239
warn!("failed to disable IP fragmentation, error: {}", err);
229240
}

crates/shadowsocks/src/net/sys/unix/bsd/macos.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ use std::{
1010

1111
use log::{error, warn};
1212
use pin_project::pin_project;
13+
use socket2::{Domain, Protocol, Socket, Type};
1314
use tokio::{
1415
io::{AsyncRead, AsyncWrite, ReadBuf},
1516
net::{TcpSocket, TcpStream as TokioTcpStream, UdpSocket},
1617
};
1718
use tokio_tfo::TfoStream;
1819

1920
use crate::net::{
20-
sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect},
21+
sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect, socket_bind_dual_stack},
2122
AddrFamily,
2223
ConnectOpts,
2324
};
@@ -250,7 +251,17 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) ->
250251
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
251252
};
252253

253-
let socket = UdpSocket::bind(bind_addr).await?;
254+
let socket = if af != AddrFamily::Ipv6 {
255+
UdpSocket::bind(bind_addr).await?
256+
} else {
257+
let socket = Socket::new(Domain::for_address(bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
258+
socket_bind_dual_stack(&socket, &bind_addr, false)?;
259+
260+
// UdpSocket::from_std requires socket to be non-blocked
261+
socket.set_nonblocking(true)?;
262+
UdpSocket::from_std(socket.into())?
263+
};
264+
254265
if let Err(err) = set_disable_ip_fragmentation(af, &socket) {
255266
warn!("failed to disable IP fragmentation, error: {}", err);
256267
}

crates/shadowsocks/src/net/sys/unix/linux/mod.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ use std::{
1010
use cfg_if::cfg_if;
1111
use log::{error, warn};
1212
use pin_project::pin_project;
13+
use socket2::{Domain, Protocol, Socket, Type};
1314
use tokio::{
1415
io::{AsyncRead, AsyncWrite, ReadBuf},
1516
net::{TcpSocket, TcpStream as TokioTcpStream, UdpSocket},
1617
};
1718
use tokio_tfo::TfoStream;
1819

1920
use crate::net::{
20-
sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect},
21+
sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect, socket_bind_dual_stack},
2122
AddrFamily,
2223
ConnectOpts,
2324
};
@@ -245,7 +246,17 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) ->
245246
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
246247
};
247248

248-
let socket = UdpSocket::bind(bind_addr).await?;
249+
let socket = if af != AddrFamily::Ipv6 {
250+
UdpSocket::bind(bind_addr).await?
251+
} else {
252+
let socket = Socket::new(Domain::for_address(bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
253+
socket_bind_dual_stack(&socket, &bind_addr, false)?;
254+
255+
// UdpSocket::from_std requires socket to be non-blocked
256+
socket.set_nonblocking(true)?;
257+
UdpSocket::from_std(socket.into())?
258+
};
259+
249260
if let Err(err) = set_disable_ip_fragmentation(af, &socket) {
250261
warn!("failed to disable IP fragmentation, error: {}", err);
251262
}

crates/shadowsocks/src/net/sys/windows/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,17 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, opts: &ConnectOpts) -> i
368368
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
369369
};
370370

371-
let socket = UdpSocket::bind(bind_addr).await?;
371+
let socket = if af != AddrFamily::Ipv6 {
372+
UdpSocket::bind(bind_addr).await?
373+
} else {
374+
let socket = Socket::new(Domain::for_address(bind_addr), Type::DGRAM, Some(Protocol::UDP))?;
375+
socket_bind_dual_stack(&socket, &bind_addr, false)?;
376+
377+
// UdpSocket::from_std requires socket to be non-blocked
378+
socket.set_nonblocking(true)?;
379+
UdpSocket::from_std(socket.into())?
380+
};
381+
372382
if let Err(err) = set_disable_ip_fragmentation(af, &socket) {
373383
warn!("failed to disable IP fragmentation, error: {}", err);
374384
}

0 commit comments

Comments
 (0)