mirror of
https://github.com/rathole-org/rathole.git
synced 2026-05-06 21:41:20 +08:00
Implement prefer IPv6 option for the client (#376)
* implement prefer_ipv6 option * implement prefer_ipv6 option * remove unused prefer_ipv6 * add prefer_ipv6 to sample config * fix merge * remove unused prefer_ipv6 * move prefer_piv6 to correct position in full.toml * set prefer_ipv6 default value * run clippy
This commit is contained in:
@@ -227,7 +227,7 @@ async fn run_data_channel<T: Transport>(args: Arc<RunDataChannelArgs<T>>) -> Res
|
||||
if args.service.service_type != ServiceType::Udp {
|
||||
bail!("Expect UDP traffic. Please check the configuration.")
|
||||
}
|
||||
run_data_channel_for_udp::<T>(conn, &args.service.local_addr).await?;
|
||||
run_data_channel_for_udp::<T>(conn, &args.service.local_addr, args.service.prefer_ipv6).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -255,7 +255,7 @@ async fn run_data_channel_for_tcp<T: Transport>(
|
||||
type UdpPortMap = Arc<RwLock<HashMap<SocketAddr, mpsc::Sender<Bytes>>>>;
|
||||
|
||||
#[instrument(skip(conn))]
|
||||
async fn run_data_channel_for_udp<T: Transport>(conn: T::Stream, local_addr: &str) -> Result<()> {
|
||||
async fn run_data_channel_for_udp<T: Transport>(conn: T::Stream, local_addr: &str, prefer_ipv6: bool) -> Result<()> {
|
||||
debug!("New data channel starts forwarding");
|
||||
|
||||
let port_map: UdpPortMap = Arc::new(RwLock::new(HashMap::new()));
|
||||
@@ -305,7 +305,7 @@ async fn run_data_channel_for_udp<T: Transport>(conn: T::Stream, local_addr: &st
|
||||
// grabbing the writer lock
|
||||
let mut m = port_map.write().await;
|
||||
|
||||
match udp_connect(local_addr).await {
|
||||
match udp_connect(local_addr, prefer_ipv6).await {
|
||||
Ok(s) => {
|
||||
let (inbound_tx, inbound_rx) = mpsc::channel(UDP_SENDQ_SIZE);
|
||||
m.insert(packet.from, inbound_tx);
|
||||
|
||||
@@ -63,6 +63,8 @@ pub struct ClientServiceConfig {
|
||||
#[serde(skip)]
|
||||
pub name: String,
|
||||
pub local_addr: String,
|
||||
#[serde(default)] // Default to false
|
||||
pub prefer_ipv6: bool,
|
||||
pub token: Option<MaskedString>,
|
||||
pub nodelay: Option<bool>,
|
||||
pub retry_interval: Option<u64>,
|
||||
@@ -201,6 +203,7 @@ fn default_client_retry_interval() -> u64 {
|
||||
pub struct ClientConfig {
|
||||
pub remote_addr: String,
|
||||
pub default_token: Option<MaskedString>,
|
||||
pub prefer_ipv6: Option<bool>,
|
||||
pub services: HashMap<String, ClientServiceConfig>,
|
||||
#[serde(default)]
|
||||
pub transport: TransportConfig,
|
||||
|
||||
@@ -64,16 +64,45 @@ pub fn host_port_pair(s: &str) -> Result<(&str, u16)> {
|
||||
}
|
||||
|
||||
/// Create a UDP socket and connect to `addr`
|
||||
pub async fn udp_connect<A: ToSocketAddrs>(addr: A) -> Result<UdpSocket> {
|
||||
let addr = to_socket_addr(addr).await?;
|
||||
pub async fn udp_connect<A: ToSocketAddrs>(addr: A, prefer_ipv6: bool) -> Result<UdpSocket> {
|
||||
|
||||
let bind_addr = match addr {
|
||||
SocketAddr::V4(_) => "0.0.0.0:0",
|
||||
SocketAddr::V6(_) => ":::0",
|
||||
let (socket_addr, bind_addr);
|
||||
|
||||
match prefer_ipv6 {
|
||||
false => {
|
||||
socket_addr = to_socket_addr(addr).await?;
|
||||
|
||||
bind_addr = match socket_addr {
|
||||
SocketAddr::V4(_) => "0.0.0.0:0",
|
||||
SocketAddr::V6(_) => ":::0",
|
||||
};
|
||||
},
|
||||
true => {
|
||||
let all_host_addresses: Vec<SocketAddr> = lookup_host(addr).await?.collect();
|
||||
|
||||
// Try to find an IPv6 address
|
||||
match all_host_addresses.clone().iter().find(|x| x.is_ipv6()) {
|
||||
Some(socket_addr_ipv6) => {
|
||||
socket_addr = *socket_addr_ipv6;
|
||||
bind_addr = ":::0";
|
||||
},
|
||||
None => {
|
||||
let socket_addr_ipv4 = all_host_addresses.iter().find(|x| x.is_ipv4());
|
||||
match socket_addr_ipv4 {
|
||||
None => return Err(anyhow!("Failed to lookup the host")),
|
||||
// fallback to IPv4
|
||||
Some(socket_addr_ipv4) => {
|
||||
socket_addr = *socket_addr_ipv4;
|
||||
bind_addr = "0.0.0.0:0";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let s = UdpSocket::bind(bind_addr).await?;
|
||||
s.connect(addr).await?;
|
||||
s.connect(socket_addr).await?;
|
||||
s.connect(socket_addr).await?;
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ remote_public_key = "key_encoded_in_base64" # Optional
|
||||
[client.services.service1] # A service that needs forwarding. The name `service1` can change arbitrarily, as long as identical to the name in the server's configuration
|
||||
type = "tcp" # Optional. The protocol that needs forwarding. Possible values: ["tcp", "udp"]. Default: "tcp"
|
||||
token = "whatever" # Necessary if `client.default_token` not set
|
||||
prefer_ipv6 = false # Optional. If the client prefers to use IPv6 when connecting to the server (e.g.: When the client is behind an ISP's NAT). Default: false
|
||||
local_addr = "127.0.0.1:1081" # Necessary. The address of the service that needs to be forwarded
|
||||
|
||||
[client.services.service2] # Multiple services can be defined
|
||||
|
||||
Reference in New Issue
Block a user