From 0cb4c4cf0540a5510a215d3c0bf5a710a9a4f997 Mon Sep 17 00:00:00 2001 From: zonyitoo Date: Mon, 19 Feb 2024 10:46:42 +0800 Subject: [PATCH] feat: set default route for wintun interface - ref #1396 --- .../src/local/tun/sys/windows/mod.rs | 67 ++++++++++++++++++- .../src/dns_resolver/hickory_dns_resolver.rs | 3 +- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/crates/shadowsocks-service/src/local/tun/sys/windows/mod.rs b/crates/shadowsocks-service/src/local/tun/sys/windows/mod.rs index 9b50862005ab..2f5d136bc72c 100644 --- a/crates/shadowsocks-service/src/local/tun/sys/windows/mod.rs +++ b/crates/shadowsocks-service/src/local/tun/sys/windows/mod.rs @@ -1,7 +1,22 @@ -use std::{io, marker::Unpin}; +use std::{ + io::{self, ErrorKind}, + marker::Unpin, + mem, +}; +use log::{error, trace}; use tokio::io::{AsyncWrite, AsyncWriteExt}; -use tun::platform::Device as TunDevice; +use tun::{platform::Device as TunDevice, Device}; +use windows_sys::Win32::{ + Foundation::NO_ERROR, + NetworkManagement::IpHelper::{ + CreateIpForwardEntry, + GetBestInterface, + MIB_IPFORWARDROW, + MIB_IPROUTE_TYPE_INDIRECT, + }, + Networking::WinSock::MIB_IPPROTO_NETMGMT, +}; /// Packet Information length in bytes /// @@ -16,6 +31,52 @@ pub async fn write_packet_with_pi(writer: &mut W, packet: } /// Set platform specific route configuration -pub async fn set_route_configuration(_device: &TunDevice) -> io::Result<()> { +pub async fn set_route_configuration(device: &TunDevice) -> io::Result<()> { + let tun_address = match device.address() { + Ok(t) => t, + Err(err) => { + error!("tun device doesn't have address, error: {}", err); + return Err(io::Error::new(ErrorKind::Other, err)); + } + }; + + let tun_netmask = match device.netmask() { + Ok(m) => m, + Err(err) => { + error!("tun device doesn't have netmask, error: {}", err); + return Err(io::Error::new(ErrorKind::Other, err)); + } + }; + + unsafe { + // https://learn.microsoft.com/en-us/windows/win32/api/ipmib/ns-ipmib-mib_ipforwardrow + let mut ipfrow: MIB_IPFORWARDROW = mem::zeroed(); + + ipfrow.dwForwardDest = u32::from(tun_address); + ipfrow.dwForwardMask = u32::from(tun_netmask); + + // Get ifindex of this inteface + // https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getbestinterface + let mut if_index: u32 = 0; + let ret = GetBestInterface(ipfrow.dwForwardDest, &mut if_index); + if ret != NO_ERROR { + error!("GetBestInterface failed, ret: {}, destination: {}", ret, tun_address); + return Err(io::Error::new(ErrorKind::Other, format!("GetBestInterface {}", ret))); + } + ipfrow.dwForwardIfIndex = if_index; + + ipfrow.Anonymous1.dwForwardType = MIB_IPROUTE_TYPE_INDIRECT as u32; + ipfrow.Anonymous2.dwForwardProto = MIB_IPPROTO_NETMGMT as u32; + + let status = CreateIpForwardEntry(&ipfrow); + if status != NO_ERROR { + error!("CreateIpForwardEntry failed, status: {}", status); + return Err(io::Error::new( + ErrorKind::Other, + format!("CreateIpForwardEntry {}", status), + )); + } + } + Ok(()) } diff --git a/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs b/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs index 9e378bca4fbf..2d7e4fdab831 100644 --- a/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs +++ b/crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs @@ -20,7 +20,8 @@ use hickory_resolver::{ udp::{DnsUdpSocket, QuicLocalAddr}, TokioTime, }, - AsyncResolver, TokioHandle, + AsyncResolver, + TokioHandle, }; use log::trace; use tokio::{io::ReadBuf, net::UdpSocket};