Skip to content

Commit 0cb4c4c

Browse files
committed
feat: set default route for wintun interface
- ref #1396
1 parent c550cdf commit 0cb4c4c

File tree

2 files changed

+66
-4
lines changed

2 files changed

+66
-4
lines changed

crates/shadowsocks-service/src/local/tun/sys/windows/mod.rs

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1-
use std::{io, marker::Unpin};
1+
use std::{
2+
io::{self, ErrorKind},
3+
marker::Unpin,
4+
mem,
5+
};
26

7+
use log::{error, trace};
38
use tokio::io::{AsyncWrite, AsyncWriteExt};
4-
use tun::platform::Device as TunDevice;
9+
use tun::{platform::Device as TunDevice, Device};
10+
use windows_sys::Win32::{
11+
Foundation::NO_ERROR,
12+
NetworkManagement::IpHelper::{
13+
CreateIpForwardEntry,
14+
GetBestInterface,
15+
MIB_IPFORWARDROW,
16+
MIB_IPROUTE_TYPE_INDIRECT,
17+
},
18+
Networking::WinSock::MIB_IPPROTO_NETMGMT,
19+
};
520

621
/// Packet Information length in bytes
722
///
@@ -16,6 +31,52 @@ pub async fn write_packet_with_pi<W: AsyncWrite + Unpin>(writer: &mut W, packet:
1631
}
1732

1833
/// Set platform specific route configuration
19-
pub async fn set_route_configuration(_device: &TunDevice) -> io::Result<()> {
34+
pub async fn set_route_configuration(device: &TunDevice) -> io::Result<()> {
35+
let tun_address = match device.address() {
36+
Ok(t) => t,
37+
Err(err) => {
38+
error!("tun device doesn't have address, error: {}", err);
39+
return Err(io::Error::new(ErrorKind::Other, err));
40+
}
41+
};
42+
43+
let tun_netmask = match device.netmask() {
44+
Ok(m) => m,
45+
Err(err) => {
46+
error!("tun device doesn't have netmask, error: {}", err);
47+
return Err(io::Error::new(ErrorKind::Other, err));
48+
}
49+
};
50+
51+
unsafe {
52+
// https://learn.microsoft.com/en-us/windows/win32/api/ipmib/ns-ipmib-mib_ipforwardrow
53+
let mut ipfrow: MIB_IPFORWARDROW = mem::zeroed();
54+
55+
ipfrow.dwForwardDest = u32::from(tun_address);
56+
ipfrow.dwForwardMask = u32::from(tun_netmask);
57+
58+
// Get ifindex of this inteface
59+
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getbestinterface
60+
let mut if_index: u32 = 0;
61+
let ret = GetBestInterface(ipfrow.dwForwardDest, &mut if_index);
62+
if ret != NO_ERROR {
63+
error!("GetBestInterface failed, ret: {}, destination: {}", ret, tun_address);
64+
return Err(io::Error::new(ErrorKind::Other, format!("GetBestInterface {}", ret)));
65+
}
66+
ipfrow.dwForwardIfIndex = if_index;
67+
68+
ipfrow.Anonymous1.dwForwardType = MIB_IPROUTE_TYPE_INDIRECT as u32;
69+
ipfrow.Anonymous2.dwForwardProto = MIB_IPPROTO_NETMGMT as u32;
70+
71+
let status = CreateIpForwardEntry(&ipfrow);
72+
if status != NO_ERROR {
73+
error!("CreateIpForwardEntry failed, status: {}", status);
74+
return Err(io::Error::new(
75+
ErrorKind::Other,
76+
format!("CreateIpForwardEntry {}", status),
77+
));
78+
}
79+
}
80+
2081
Ok(())
2182
}

crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use hickory_resolver::{
2020
udp::{DnsUdpSocket, QuicLocalAddr},
2121
TokioTime,
2222
},
23-
AsyncResolver, TokioHandle,
23+
AsyncResolver,
24+
TokioHandle,
2425
};
2526
use log::trace;
2627
use tokio::{io::ReadBuf, net::UdpSocket};

0 commit comments

Comments
 (0)