mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-01 21:13:09 +00:00
fix: correct hairpin NAT rules and bind hairpin check to gateway interface
The POSTROUTING MASQUERADE rules in forward-port failed to handle two hairpin scenarios: 1. Host-to-target hairpin (OUTPUT DNAT): when sip is a WAN IP (tunnel case), the old rule matched `-s sip` but the actual source of locally-originated packets is a local interface IP, not the WAN IP. Fix: use `-m addrtype --src-type LOCAL -m conntrack --ctorigdst sip` to match any local source while tying the rule to the specific sip. 2. Same-subnet self-hairpin (PREROUTING DNAT): when a WireGuard peer connects to itself via the tunnel's public IP, traffic is DNAT'd back to the peer. Without MASQUERADE the response takes a loopback shortcut, bypassing the tunnel server's conntrack and breaking NAT reversal. Fix: add `-s dip/dprefix -d dip` to masquerade same-subnet traffic, which also subsumes the old bridge_subnet rule. Also bind the hairpin detection socket to the gateway interface and local IP for consistency with the echoip client.
This commit is contained in:
@@ -290,10 +290,19 @@ pub async fn check_port(
|
||||
));
|
||||
};
|
||||
|
||||
let hairpinning = tokio::time::timeout(
|
||||
Duration::from_secs(5),
|
||||
tokio::net::TcpStream::connect(SocketAddr::new(ip.into(), port)),
|
||||
)
|
||||
let hairpinning = tokio::time::timeout(Duration::from_secs(5), async {
|
||||
let dest = SocketAddr::new(ip.into(), port);
|
||||
let socket = socket2::Socket::new(socket2::Domain::IPV4, socket2::Type::STREAM, None)?;
|
||||
socket.bind_device(Some(gateway.as_str().as_bytes()))?;
|
||||
socket.bind(&SocketAddr::new(IpAddr::V4(local_ipv4), 0).into())?;
|
||||
socket.set_nonblocking(true)?;
|
||||
#[cfg(unix)]
|
||||
let socket = unsafe {
|
||||
use std::os::fd::{FromRawFd, IntoRawFd};
|
||||
tokio::net::TcpSocket::from_raw_fd(socket.into_raw_fd())
|
||||
};
|
||||
socket.connect(dest).await.map(|_| ())
|
||||
})
|
||||
.await
|
||||
.map_or(false, |r| r.is_ok());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user