Skip to content

Commit

Permalink
feat: set default route for wintun interface
Browse files Browse the repository at this point in the history
- ref #1396
  • Loading branch information
zonyitoo committed Feb 19, 2024
1 parent c550cdf commit 0cb4c4c
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 4 deletions.
67 changes: 64 additions & 3 deletions crates/shadowsocks-service/src/local/tun/sys/windows/mod.rs
Original file line number Diff line number Diff line change
@@ -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
///
Expand All @@ -16,6 +31,52 @@ pub async fn write_packet_with_pi<W: AsyncWrite + Unpin>(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(())
}
3 changes: 2 additions & 1 deletion crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ use hickory_resolver::{
udp::{DnsUdpSocket, QuicLocalAddr},
TokioTime,
},
AsyncResolver, TokioHandle,
AsyncResolver,
TokioHandle,
};
use log::trace;
use tokio::{io::ReadBuf, net::UdpSocket};
Expand Down

0 comments on commit 0cb4c4c

Please sign in to comment.