fix smoltcp tcp proxy (#157)

1. allow smoltcp proxy with dhcp ip
2. fix smoltcp not work without no tun.
This commit is contained in:
Sijie.Sun
2024-07-07 22:08:50 +08:00
committed by GitHub
parent 24143cbf1c
commit 537f6ecf78
3 changed files with 51 additions and 32 deletions

View File

@@ -212,7 +212,7 @@ and the vpn client is in network of 10.14.14.0/24"
#[arg( #[arg(
long, long,
help = "enable smoltcp stack for subnet proxy", help = "enable smoltcp stack for subnet proxy",
default_value = "true" default_value = "false"
)] )]
use_smoltcp: bool, use_smoltcp: bool,
} }

View File

@@ -154,9 +154,19 @@ pub struct TcpProxy {
impl PeerPacketFilter for TcpProxy { impl PeerPacketFilter for TcpProxy {
async fn try_process_packet_from_peer(&self, mut packet: ZCPacket) -> Option<ZCPacket> { async fn try_process_packet_from_peer(&self, mut packet: ZCPacket) -> Option<ZCPacket> {
if let Some(_) = self.try_handle_peer_packet(&mut packet).await { if let Some(_) = self.try_handle_peer_packet(&mut packet).await {
if self
.enable_smoltcp
.load(std::sync::atomic::Ordering::Relaxed)
{
let smoltcp_stack_sender = self.smoltcp_stack_sender.as_ref().unwrap();
if let Err(e) = smoltcp_stack_sender.try_send(packet) {
tracing::error!("send to smoltcp stack failed: {:?}", e);
}
} else {
if let Err(e) = self.peer_manager.get_nic_channel().send(packet).await { if let Err(e) = self.peer_manager.get_nic_channel().send(packet).await {
tracing::error!("send to nic failed: {:?}", e); tracing::error!("send to nic failed: {:?}", e);
} }
}
return None; return None;
} else { } else {
Some(packet) Some(packet)
@@ -167,7 +177,7 @@ impl PeerPacketFilter for TcpProxy {
#[async_trait::async_trait] #[async_trait::async_trait]
impl NicPacketFilter for TcpProxy { impl NicPacketFilter for TcpProxy {
async fn try_process_packet_from_nic(&self, zc_packet: &mut ZCPacket) { async fn try_process_packet_from_nic(&self, zc_packet: &mut ZCPacket) {
let Some(my_ipv4) = self.global_ctx.get_ipv4() else { let Some(my_ipv4) = self.get_local_ip() else {
return; return;
}; };
@@ -353,10 +363,10 @@ impl TcpProxy {
dev, dev,
NetConfig::new( NetConfig::new(
interface_config, interface_config,
format!("{}/24", self.global_ctx.get_ipv4().unwrap()) format!("{}/24", self.get_local_ip().unwrap())
.parse() .parse()
.unwrap(), .unwrap(),
vec![], vec![format!("{}", self.get_local_ip().unwrap()).parse().unwrap()],
), ),
); );
net.set_any_ip(true); net.set_any_ip(true);
@@ -524,6 +534,17 @@ impl TcpProxy {
self.local_port.load(std::sync::atomic::Ordering::Relaxed) self.local_port.load(std::sync::atomic::Ordering::Relaxed)
} }
pub fn get_local_ip(&self) -> Option<Ipv4Addr> {
if self
.enable_smoltcp
.load(std::sync::atomic::Ordering::Relaxed)
{
Some(Ipv4Addr::new(192, 88, 99, 254))
} else {
self.global_ctx.get_ipv4()
}
}
async fn try_handle_peer_packet(&self, packet: &mut ZCPacket) -> Option<()> { async fn try_handle_peer_packet(&self, packet: &mut ZCPacket) -> Option<()> {
if self.cidr_set.is_empty() if self.cidr_set.is_empty()
&& !self.global_ctx.enable_exit_node() && !self.global_ctx.enable_exit_node()
@@ -532,7 +553,7 @@ impl TcpProxy {
return None; return None;
} }
let ipv4_addr = self.global_ctx.get_ipv4()?; let ipv4_addr = self.get_local_ip()?;
let hdr = packet.peer_manager_header().unwrap(); let hdr = packet.peer_manager_header().unwrap();
let is_exit_node = hdr.is_exit_node(); let is_exit_node = hdr.is_exit_node();
@@ -589,17 +610,6 @@ impl TcpProxy {
tracing::trace!(?source, ?ipv4_addr, ?packet, "tcp packet after modified"); tracing::trace!(?source, ?ipv4_addr, ?packet, "tcp packet after modified");
if self
.enable_smoltcp
.load(std::sync::atomic::Ordering::Relaxed)
{
let smoltcp_stack_sender = self.smoltcp_stack_sender.as_ref().unwrap();
if let Err(e) = smoltcp_stack_sender.try_send(packet.clone()) {
tracing::error!("send to smoltcp stack failed: {:?}", e);
}
return None;
}
Some(()) Some(())
} }
} }

View File

@@ -232,7 +232,7 @@ impl Instance {
} }
let mut used_ipv4 = HashSet::new(); let mut used_ipv4 = HashSet::new();
for route in peer_manager_c.list_routes().await { for route in routes {
if route.ipv4_addr.is_empty() { if route.ipv4_addr.is_empty() {
continue; continue;
} }
@@ -277,6 +277,15 @@ impl Instance {
Self::clear_nic_ctx(nic_ctx.clone()).await; Self::clear_nic_ctx(nic_ctx.clone()).await;
if let Some(ip) = candidate_ipv4_addr { if let Some(ip) = candidate_ipv4_addr {
if global_ctx_c.no_tun() {
current_dhcp_ip = Some(ip);
global_ctx_c.set_ipv4(Some(ip.address()));
global_ctx_c.issue_event(GlobalCtxEvent::DhcpIpv4Changed(
last_ip,
Some(ip.address()),
));
continue;
}
let mut new_nic_ctx = NicCtx::new( let mut new_nic_ctx = NicCtx::new(
global_ctx_c.clone(), global_ctx_c.clone(),
&peer_manager_c, &peer_manager_c,
@@ -315,9 +324,8 @@ impl Instance {
self.listener_manager.lock().await.run().await?; self.listener_manager.lock().await.run().await?;
self.peer_manager.run().await?; self.peer_manager.run().await?;
if !self.global_ctx.config.get_flags().no_tun { if self.global_ctx.config.get_flags().no_tun {
if self.global_ctx.config.get_dhcp() { self.peer_packet_receiver.lock().await.close();
self.check_dhcp_ip_conflict();
} else if let Some(ipv4_addr) = self.global_ctx.get_ipv4() { } else if let Some(ipv4_addr) = self.global_ctx.get_ipv4() {
let mut new_nic_ctx = NicCtx::new( let mut new_nic_ctx = NicCtx::new(
self.global_ctx.clone(), self.global_ctx.clone(),
@@ -327,8 +335,9 @@ impl Instance {
new_nic_ctx.run(ipv4_addr).await?; new_nic_ctx.run(ipv4_addr).await?;
Self::use_new_nic_ctx(self.nic_ctx.clone(), new_nic_ctx).await; Self::use_new_nic_ctx(self.nic_ctx.clone(), new_nic_ctx).await;
} }
} else {
self.peer_packet_receiver.lock().await.close(); if self.global_ctx.config.get_dhcp() {
self.check_dhcp_ip_conflict();
} }
self.run_rpc_server()?; self.run_rpc_server()?;