m/n/c/network: make SNAT generic
This changes the SNAT/Masquerade rule from being a thing set up per
interface which was only implemented by the dynamic network runnable to
a generic rule set up by the general network service part shared between
the static and dynamic implementations. It also tries to avoid NATing
host-originated traffic. Matching on interface names is argubly ugly but
the alternative is patching CNI plugins, which is also ugly.
Change-Id: I7ec40fc244ae4689b6f96ab87dbebe9a6c43dd70
Reviewed-on: https://review.monogon.dev/c/monogon/+/1844
Reviewed-by: Serge Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/node/core/network/main.go b/metropolis/node/core/network/main.go
index 956bb02..04f0afd 100644
--- a/metropolis/node/core/network/main.go
+++ b/metropolis/node/core/network/main.go
@@ -191,25 +191,6 @@
return err
}
- // Masquerade/SNAT all traffic going out of the external interface
- s.nftConn.AddRule(&nftables.Rule{
- Table: s.natTable,
- Chain: s.natPostroutingChain,
- Exprs: []expr.Any{
- &expr.Meta{Key: expr.MetaKeyOIFNAME, Register: 1},
- &expr.Cmp{
- Op: expr.CmpOpEq,
- Register: 1,
- Data: nfifname(iface.Attrs().Name),
- },
- &expr.Masq{},
- },
- })
-
- if err := s.nftConn.Flush(); err != nil {
- panic(err)
- }
-
return nil
}
@@ -280,8 +261,45 @@
Table: s.natTable,
Type: nftables.ChainTypeNAT,
})
+ // SNAT/Masquerade all traffic coming from interfaces starting with
+ // veth going to interfaces not starting with veth.
+ // This NATs all container traffic going out of the host without
+ // affecting anything else and without needing to care about specific
+ // interfaces. Will need to be changed when we support L3 attachments
+ // (BGP, ...).
+ s.nftConn.AddRule(&nftables.Rule{
+ Table: s.natTable,
+ Chain: s.natPostroutingChain,
+ Exprs: []expr.Any{
+ &expr.Meta{
+ Key: expr.MetaKeyIIFNAME,
+ Register: 8, // covers registers 8-12 (16 bytes/4 regs)
+ },
+ // Check if incoming interface starts with veth
+ &expr.Cmp{
+ Op: expr.CmpOpEq,
+ Register: 8,
+ Data: []byte{'v', 'e', 't', 'h'},
+ },
+ &expr.Meta{
+ Key: expr.MetaKeyOIFNAME,
+ Register: 8, // covers registers 8-12
+ },
+ // Check if outgoing interface doesn't start with veth
+ &expr.Cmp{
+ Op: expr.CmpOpNeq,
+ Register: 8,
+ Data: []byte{'v', 'e', 't', 'h'},
+ },
+ &expr.Masq{
+ FullyRandom: true,
+ Persistent: true,
+ },
+ },
+ })
+
if err := s.nftConn.Flush(); err != nil {
- logger.Fatalf("Failed to set up nftables base chains: %v", err)
+ logger.Fatalf("Failed to set up nftables nat chain: %v", err)
}
sysctlOpts := sysctlOptions{