Skip to content

Commit

Permalink
fix(shadowsocks): check IPv4-mapped-IPv6 compatiblity with UDP socket
Browse files Browse the repository at this point in the history
- ref #1543
  • Loading branch information
zonyitoo committed Jun 16, 2024
1 parent 5d965ab commit 5c59fba
Showing 1 changed file with 17 additions and 23 deletions.
40 changes: 17 additions & 23 deletions crates/shadowsocks/src/net/sys/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::{
io::{self, ErrorKind},
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
time::Duration,
};

use cfg_if::cfg_if;
Expand Down Expand Up @@ -177,39 +176,34 @@ static IP_STACK_CAPABILITIES: Lazy<IpStackCapabilities> = Lazy::new(|| {
});

fn check_ipv4_mapped_ipv6_capability() -> io::Result<()> {
// https://stackoverflow.com/questions/30184377/how-to-detect-if-dual-stack-socket-is-supported

let local_host = SockAddr::from(SocketAddr::new(Ipv4Addr::LOCALHOST.to_ipv6_mapped().into(), 0));
let local_host_53 = SockAddr::from(SocketAddr::new(Ipv4Addr::LOCALHOST.to_ipv6_mapped().into(), 53));

let socket1 = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP))?;
socket1.set_only_v6(false)?;
socket1.bind(&local_host)?;
socket1.listen(128)?;
let socket = Socket::new(Domain::IPV6, Type::DGRAM, Some(Protocol::UDP))?;
socket.set_only_v6(false)?;
socket.bind(&local_host)?;
socket.connect(&local_host_53)?;

let socket1_address = socket1.local_addr()?;
match socket1_address.as_socket() {
// getsockname()
let local_addr = socket.local_addr()?;
match local_addr.as_socket() {
None => return Err(io::Error::new(ErrorKind::Other, "invalid local_addr")),
Some(socket_addr) => match socket_addr {
SocketAddr::V4(..) => {
return Err(io::Error::new(
ErrorKind::Other,
"local_addr shouldn't be an IPv4 address",
));
}
SocketAddr::V6(ref v6) => {
if let None = v6.ip().to_ipv4_mapped() {
Some(addr) => match addr {
SocketAddr::V4(..) => return Err(io::Error::new(ErrorKind::Other, "local_addr returned an IPv4 address")),
SocketAddr::V6(v6) => match v6.ip().to_ipv4_mapped() {
Some(_) => {}
None => {
return Err(io::Error::new(
ErrorKind::Other,
"local_addr is not an IPv4-mapped-IPv6 address",
"local_addr returned an non IPv4-mapped-IPv6 address",
));
}
}
},
},
}

let socket2 = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP))?;
socket2.set_only_v6(false)?;
socket2.bind(&local_host)?;
socket2.connect_timeout(&socket1_address, Duration::from_secs(1))?;

Ok(())
}

Expand Down

0 comments on commit 5c59fba

Please sign in to comment.