Fix postrouting rules for vpns, port forwards
This commit is contained in:
parent
25e8b65394
commit
750b584b8a
|
@ -158,16 +158,16 @@ pub(crate) async fn forward_postrouting(
|
|||
proto: Proto,
|
||||
internal_ip: Ipv4Addr,
|
||||
internal_mask: u8,
|
||||
internal_port: u16,
|
||||
external_ip: Ipv4Addr,
|
||||
external_port: u16,
|
||||
destination_ip: Ipv4Addr,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
forward_postrouting_snat(
|
||||
proto,
|
||||
internal_ip,
|
||||
internal_mask,
|
||||
internal_port,
|
||||
external_ip,
|
||||
external_port,
|
||||
destination_ip,
|
||||
|cmd| cmd.arg("-I"),
|
||||
)
|
||||
|
@ -178,16 +178,16 @@ pub(crate) async fn delete_forward_postrouting(
|
|||
proto: Proto,
|
||||
internal_ip: Ipv4Addr,
|
||||
internal_mask: u8,
|
||||
internal_port: u16,
|
||||
external_ip: Ipv4Addr,
|
||||
external_port: u16,
|
||||
destination_ip: Ipv4Addr,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
forward_postrouting_snat(
|
||||
proto,
|
||||
internal_ip,
|
||||
internal_mask,
|
||||
internal_port,
|
||||
external_ip,
|
||||
external_port,
|
||||
destination_ip,
|
||||
|cmd| cmd.arg("-D"),
|
||||
)
|
||||
|
@ -198,8 +198,8 @@ async fn forward_postrouting_snat(
|
|||
proto: Proto,
|
||||
internal_ip: Ipv4Addr,
|
||||
internal_mask: u8,
|
||||
internal_port: u16,
|
||||
external_ip: Ipv4Addr,
|
||||
external_port: u16,
|
||||
destination_ip: Ipv4Addr,
|
||||
func: impl Fn(&mut Command) -> &mut Command,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
|
@ -215,7 +215,7 @@ async fn forward_postrouting_snat(
|
|||
"-m",
|
||||
proto.as_iptables_str(),
|
||||
"--dport",
|
||||
&external_port.to_string(),
|
||||
&internal_port.to_string(),
|
||||
"-m",
|
||||
"conntrack",
|
||||
"--ctstate",
|
||||
|
|
74
src/rules.rs
74
src/rules.rs
|
@ -109,34 +109,37 @@ pub(crate) async fn unset(interfaces: &Interfaces, rule: Rule) -> Result<(), any
|
|||
dest_port,
|
||||
)
|
||||
.await?;
|
||||
for iface in &interfaces.internal {
|
||||
iptables::delete_forward_postrouting(
|
||||
rule.proto,
|
||||
iface.ip,
|
||||
iface.mask,
|
||||
interfaces.external.ip,
|
||||
rule.port,
|
||||
dest_ip,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
for iface in &interfaces.tunnel {
|
||||
if interfaces
|
||||
for iface in interfaces.internal.iter().chain(interfaces.tunnel.iter()) {
|
||||
let is_nat_iface = interfaces
|
||||
.nats
|
||||
.iter()
|
||||
.any(|nat_iface| *nat_iface == iface.interface)
|
||||
{
|
||||
.any(|nat_iface| *nat_iface == iface.interface);
|
||||
|
||||
let has_nat_subnet = interfaces.nats.iter().any(|nat_iface| {
|
||||
*nat_iface != iface.interface
|
||||
&& interfaces
|
||||
.internal
|
||||
.iter()
|
||||
.chain(interfaces.tunnel.iter())
|
||||
.any(|other_iface| {
|
||||
*nat_iface == other_iface.interface
|
||||
&& other_iface.ip == iface.ip
|
||||
&& other_iface.mask == iface.mask
|
||||
})
|
||||
});
|
||||
|
||||
if is_nat_iface {
|
||||
iptables::delete_forward_prerouting(
|
||||
rule.proto, iface.ip, iface.mask, rule.port, dest_ip, dest_port,
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
} else if !has_nat_subnet {
|
||||
iptables::delete_forward_postrouting(
|
||||
rule.proto,
|
||||
iface.ip,
|
||||
iface.mask,
|
||||
dest_port,
|
||||
interfaces.external.ip,
|
||||
rule.port,
|
||||
dest_ip,
|
||||
)
|
||||
.await?;
|
||||
|
@ -192,34 +195,37 @@ pub(crate) async fn apply(interfaces: &Interfaces, rule: Rule) -> Result<(), any
|
|||
dest_port,
|
||||
)
|
||||
.await?;
|
||||
for iface in &interfaces.internal {
|
||||
iptables::forward_postrouting(
|
||||
rule.proto,
|
||||
iface.ip,
|
||||
iface.mask,
|
||||
interfaces.external.ip,
|
||||
rule.port,
|
||||
dest_ip,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
for iface in &interfaces.tunnel {
|
||||
if interfaces
|
||||
for iface in interfaces.internal.iter().chain(interfaces.tunnel.iter()) {
|
||||
let is_nat_iface = interfaces
|
||||
.nats
|
||||
.iter()
|
||||
.any(|nat_iface| *nat_iface == iface.interface)
|
||||
{
|
||||
.any(|nat_iface| *nat_iface == iface.interface);
|
||||
|
||||
let has_nat_subnet = interfaces.nats.iter().any(|nat_iface| {
|
||||
*nat_iface != iface.interface
|
||||
&& interfaces
|
||||
.internal
|
||||
.iter()
|
||||
.chain(interfaces.tunnel.iter())
|
||||
.any(|other_iface| {
|
||||
*nat_iface == other_iface.interface
|
||||
&& other_iface.ip == iface.ip
|
||||
&& other_iface.mask == iface.mask
|
||||
})
|
||||
});
|
||||
|
||||
if is_nat_iface {
|
||||
iptables::forward_prerouting(
|
||||
rule.proto, iface.ip, iface.mask, rule.port, dest_ip, dest_port,
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
} else if !has_nat_subnet {
|
||||
iptables::forward_postrouting(
|
||||
rule.proto,
|
||||
iface.ip,
|
||||
iface.mask,
|
||||
dest_port,
|
||||
interfaces.external.ip,
|
||||
rule.port,
|
||||
dest_ip,
|
||||
)
|
||||
.await?;
|
||||
|
|
|
@ -198,6 +198,52 @@ fn filter(interfaces: &Interfaces) -> String {
|
|||
|
||||
// FORWARD: Forwarding traffic across interfaces
|
||||
|
||||
for nat_iface in &interfaces.nats {
|
||||
if let Some(iface) = interfaces
|
||||
.internal
|
||||
.iter()
|
||||
.chain(interfaces.tunnel.iter())
|
||||
.find(|iface| iface.interface == *nat_iface)
|
||||
{
|
||||
filter += &format!(
|
||||
"-A FORWARD -i {natif} -d {natip}/{natmask} -j ACCEPT\n",
|
||||
natif = iface.interface,
|
||||
natip = iface.ip,
|
||||
natmask = iface.mask,
|
||||
);
|
||||
}
|
||||
|
||||
for iface in interfaces.internal.iter().chain(interfaces.tunnel.iter()) {
|
||||
let is_nat_iface = *nat_iface == iface.interface;
|
||||
|
||||
let has_nat_subnet = interfaces
|
||||
.internal
|
||||
.iter()
|
||||
.chain(interfaces.tunnel.iter())
|
||||
.any(|other_iface| {
|
||||
*nat_iface == other_iface.interface
|
||||
&& other_iface.ip == iface.ip
|
||||
&& other_iface.mask == iface.mask
|
||||
});
|
||||
|
||||
if !is_nat_iface && !has_nat_subnet {
|
||||
// Accept packets over NAT'd tunnel interfaces from pre-existing connections
|
||||
filter += &format!(
|
||||
"-A FORWARD -i {natif} -o {intif} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT\n",
|
||||
natif = nat_iface,
|
||||
intif = iface.interface,
|
||||
);
|
||||
|
||||
// Reject packets over NAT'd tunnel interfaces
|
||||
filter += &format!(
|
||||
"-A FORWARD -i {natif} -o {intif} -j REJECT --reject-with icmp-port-unreachable\n",
|
||||
natif = nat_iface,
|
||||
intif = iface.interface,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Accept packets over tunnel interfaces
|
||||
for iface in &interfaces.tunnel {
|
||||
filter += &format!(
|
||||
|
@ -273,13 +319,27 @@ fn nat(interfaces: &Interfaces) -> String {
|
|||
);
|
||||
|
||||
for nat_iface in &interfaces.nats {
|
||||
for internal in &interfaces.internal {
|
||||
nat += &format!(
|
||||
"-A POSTROUTING -s {intip}/{intmask} -o {natiface} -j MASQUERADE\n",
|
||||
intip = internal.ip,
|
||||
intmask = internal.mask,
|
||||
natiface = nat_iface,
|
||||
);
|
||||
for iface in interfaces.internal.iter().chain(interfaces.tunnel.iter()) {
|
||||
let is_nat_iface = *nat_iface == iface.interface;
|
||||
|
||||
let has_nat_subnet = interfaces
|
||||
.internal
|
||||
.iter()
|
||||
.chain(interfaces.tunnel.iter())
|
||||
.any(|other_iface| {
|
||||
*nat_iface == other_iface.interface
|
||||
&& other_iface.ip == iface.ip
|
||||
&& other_iface.mask == iface.mask
|
||||
});
|
||||
|
||||
if !is_nat_iface && !has_nat_subnet {
|
||||
nat += &format!(
|
||||
"-A POSTROUTING -s {intip}/{intmask} -o {natiface} -j MASQUERADE\n",
|
||||
intip = iface.ip,
|
||||
intmask = iface.mask,
|
||||
natiface = nat_iface,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue