Skip to content

Commit

Permalink
feat(shadowsocks): ConnectOpts::bind_local_addr supports binding to a…
Browse files Browse the repository at this point in the history
… specific port
  • Loading branch information
zonyitoo committed Nov 18, 2024
1 parent 55125df commit d3da10a
Show file tree
Hide file tree
Showing 12 changed files with 34 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use std::{
fmt::{self, Debug},
net::SocketAddr,
sync::{
atomic::{AtomicU32, Ordering},
Arc,
Expand Down Expand Up @@ -102,7 +103,7 @@ impl ServerIdent {
}

if let Some(bind_local_addr) = svr_cfg.outbound_bind_addr {
connect_opts.bind_local_addr = Some(bind_local_addr);
connect_opts.bind_local_addr = Some(SocketAddr::new(bind_local_addr, 0));
}

if let Some(ref bind_interface) = svr_cfg.outbound_bind_interface {
Expand Down
3 changes: 2 additions & 1 deletion crates/shadowsocks-service/src/local/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use std::{
io::{self, ErrorKind},
net::SocketAddr,
sync::Arc,
time::Duration,
};
Expand Down Expand Up @@ -130,7 +131,7 @@ impl Server {
vpn_protect_path: config.outbound_vpn_protect_path,

bind_interface: config.outbound_bind_interface,
bind_local_addr: config.outbound_bind_addr,
bind_local_addr: config.outbound_bind_addr.map(|ip| SocketAddr::new(ip, 0)),

..Default::default()
};
Expand Down
4 changes: 2 additions & 2 deletions crates/shadowsocks-service/src/manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! Service for managing multiple relay servers. [Manage Multiple Users](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users)
use std::{io, sync::Arc};
use std::{io, net::SocketAddr, sync::Arc};

use log::trace;
use shadowsocks::net::{AcceptOpts, ConnectOpts};
Expand Down Expand Up @@ -40,7 +40,7 @@ pub async fn run(config: Config) -> io::Result<()> {
#[cfg(target_os = "android")]
vpn_protect_path: config.outbound_vpn_protect_path,

bind_local_addr: config.outbound_bind_addr,
bind_local_addr: config.outbound_bind_addr.map(|ip| SocketAddr::new(ip, 0)),
bind_interface: config.outbound_bind_interface,

..Default::default()
Expand Down
6 changes: 3 additions & 3 deletions crates/shadowsocks-service/src/server/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Shadowsocks server
use std::{io, sync::Arc, time::Duration};
use std::{io, net::SocketAddr, sync::Arc, time::Duration};

use futures::future;
use log::trace;
Expand Down Expand Up @@ -64,7 +64,7 @@ pub async fn run(config: Config) -> io::Result<()> {
#[cfg(target_os = "android")]
vpn_protect_path: config.outbound_vpn_protect_path,

bind_local_addr: config.outbound_bind_addr,
bind_local_addr: config.outbound_bind_addr.map(|ip| SocketAddr::new(ip, 0)),
bind_interface: config.outbound_bind_interface,

..Default::default()
Expand Down Expand Up @@ -110,7 +110,7 @@ pub async fn run(config: Config) -> io::Result<()> {
}

if let Some(bind_local_addr) = inst.outbound_bind_addr {
connect_opts.bind_local_addr = Some(bind_local_addr);
connect_opts.bind_local_addr = Some(SocketAddr::new(bind_local_addr, 0));
}

if let Some(bind_interface) = inst.outbound_bind_interface {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl RuntimeProvider for ShadowDnsRuntimeProvider {
let mut connect_opts = self.connect_opts.clone();

if let Some(bind_addr) = bind_addr {
connect_opts.bind_local_addr = Some(bind_addr.ip());
connect_opts.bind_local_addr = Some(bind_addr);
}

let wait_for = wait_for.unwrap_or_else(|| Duration::from_secs(5));
Expand Down
4 changes: 2 additions & 2 deletions crates/shadowsocks/src/net/option.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Options for connecting to remote server
use std::{net::IpAddr, time::Duration};
use std::{net::SocketAddr, time::Duration};

/// Options for connecting to TCP remote server
#[derive(Debug, Clone, Default)]
Expand Down Expand Up @@ -60,7 +60,7 @@ pub struct ConnectOpts {
/// Outbound socket binds to this IP address, mostly for choosing network interfaces
///
/// It only affects sockets that trying to connect to addresses with the same family
pub bind_local_addr: Option<IpAddr>,
pub bind_local_addr: Option<SocketAddr>,

/// Outbound socket binds to interface
pub bind_interface: Option<String>,
Expand Down
14 changes: 7 additions & 7 deletions crates/shadowsocks/src/net/sys/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
io::{self, ErrorKind},
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
};

use cfg_if::cfg_if;
Expand All @@ -23,13 +23,13 @@ cfg_if! {

fn set_common_sockopt_for_connect(addr: SocketAddr, socket: &TcpSocket, opts: &ConnectOpts) -> io::Result<()> {
// Binds to IP address
if let Some(ip) = opts.bind_local_addr {
match (ip, addr.ip()) {
(IpAddr::V4(..), IpAddr::V4(..)) => {
socket.bind(SocketAddr::new(ip, 0))?;
if let Some(baddr) = opts.bind_local_addr {
match (baddr, addr) {
(SocketAddr::V4(..), SocketAddr::V4(..)) => {
socket.bind(baddr)?;
}
(IpAddr::V6(..), IpAddr::V6(..)) => {
socket.bind(SocketAddr::new(ip, 0))?;
(SocketAddr::V6(..), SocketAddr::V6(..)) => {
socket.bind(baddr)?;
}
_ => {}
}
Expand Down
6 changes: 3 additions & 3 deletions crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
io, mem,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
os::unix::io::{AsRawFd, RawFd},
pin::Pin,
ptr,
Expand Down Expand Up @@ -227,8 +227,8 @@ pub fn set_disable_ip_fragmentation<S: AsRawFd>(af: AddrFamily, socket: &S) -> i
#[inline]
pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result<UdpSocket> {
let bind_addr = match (af, config.bind_local_addr) {
(AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0),
(AddrFamily::Ipv6, Some(IpAddr::V6(ip))) => SocketAddr::new(ip.into(), 0),
(AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(),
(AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(),
(AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0),
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
};
Expand Down
6 changes: 3 additions & 3 deletions crates/shadowsocks/src/net/sys/unix/bsd/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
collections::HashMap,
io::{self, ErrorKind},
mem,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpStream as StdTcpStream},
net::{Ipv4Addr, Ipv6Addr, SocketAddr, TcpStream as StdTcpStream},
os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
pin::Pin,
ptr,
Expand Down Expand Up @@ -355,8 +355,8 @@ pub fn set_disable_ip_fragmentation<S: AsRawFd>(af: AddrFamily, socket: &S) -> i
#[inline]
pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result<UdpSocket> {
let bind_addr = match (af, config.bind_local_addr) {
(AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0),
(AddrFamily::Ipv6, Some(IpAddr::V6(ip))) => SocketAddr::new(ip.into(), 0),
(AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(),
(AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(),
(AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0),
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
};
Expand Down
6 changes: 3 additions & 3 deletions crates/shadowsocks/src/net/sys/unix/linux/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
io, mem,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
pin::Pin,
ptr,
Expand Down Expand Up @@ -286,8 +286,8 @@ pub fn set_disable_ip_fragmentation<S: AsRawFd>(af: AddrFamily, socket: &S) -> i
#[inline]
pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result<UdpSocket> {
let bind_addr = match (af, config.bind_local_addr) {
(AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0),
(AddrFamily::Ipv6, Some(IpAddr::V6(ip))) => SocketAddr::new(ip.into(), 0),
(AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(),
(AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(),
(AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0),
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
};
Expand Down
6 changes: 3 additions & 3 deletions crates/shadowsocks/src/net/sys/unix/others.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
io,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
ops::{Deref, DerefMut},
os::fd::AsRawFd,
pin::Pin,
Expand Down Expand Up @@ -81,8 +81,8 @@ pub fn set_disable_ip_fragmentation<S: AsRawFd>(_af: AddrFamily, _socket: &S) ->
#[inline]
pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result<UdpSocket> {
let bind_addr = match (af, config.bind_local_addr) {
(AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0),
(AddrFamily::Ipv6, Some(IpAddr::V6(ip))) => SocketAddr::new(ip.into(), 0),
(AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(),
(AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(),
(AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0),
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
};
Expand Down
6 changes: 3 additions & 3 deletions crates/shadowsocks/src/net/sys/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,9 +467,9 @@ pub async fn create_inbound_udp_socket(addr: &SocketAddr, ipv6_only: bool) -> io
/// Create a `UdpSocket` for connecting to `addr`
#[inline(always)]
pub async fn create_outbound_udp_socket(af: AddrFamily, opts: &ConnectOpts) -> io::Result<UdpSocket> {
let bind_addr = match (af, opts.bind_local_addr) {
(AddrFamily::Ipv4, Some(IpAddr::V4(ip))) => SocketAddr::new(ip.into(), 0),
(AddrFamily::Ipv6, Some(IpAddr::V6(ip))) => SocketAddr::new(ip.into(), 0),
let bind_addr = match (af, config.bind_local_addr) {
(AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(),
(AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(),
(AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0),
(AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
};
Expand Down

0 comments on commit d3da10a

Please sign in to comment.