netconfig: implement UDP port forwardings

This commit is contained in:
Michael Stapelberg 2018-06-14 21:05:43 +02:00
parent 93eaab99cb
commit 390c2af7db
2 changed files with 33 additions and 10 deletions

View File

@ -43,6 +43,12 @@ const goldenPortForwardings = `
"port": 8022,
"dest_addr": "192.168.42.99",
"dest_port": 22
},
{
"proto": "udp",
"port": 53,
"dest_addr": "192.168.42.99",
"dest_port": 53
}
]
}
@ -207,6 +213,7 @@ func TestNetconfig(t *testing.T) {
`table ip nat {`,
` chain prerouting {`,
` type nat hook prerouting priority 0; policy accept;`,
` iifname "uplink0" udp dport domain dnat to 192.168.42.99:domain`,
` iifname "uplink0" tcp dport 8022 dnat to 192.168.42.99:ssh`,
` iifname "uplink0" tcp dport http-alt dnat to 192.168.42.23:9999`,
` }`,

View File

@ -58,6 +58,10 @@ func applyDhcp4(dir string) error {
return err
}
if got.SubnetMask == "" {
return fmt.Errorf("invalid DHCP lease: no subnet mask present")
}
subnetSize, err := subnetMaskSize(got.SubnetMask)
if err != nil {
return err
@ -269,7 +273,7 @@ func ifname(n string) []byte {
return b
}
func portForwardExpr(port uint16, dest net.IP, dport uint16) []expr.Any {
func portForwardExpr(proto uint8, port uint16, dest net.IP, dport uint16) []expr.Any {
return []expr.Any{
// [ meta load iifname => reg 1 ]
&expr.Meta{Key: expr.MetaKeyIIFNAME, Register: 1},
@ -286,7 +290,7 @@ func portForwardExpr(port uint16, dest net.IP, dport uint16) []expr.Any {
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: []byte{0x06}, /* TCP */
Data: []byte{proto},
},
// [ payload load 2b @ transport header + 2 => reg 1 ]
@ -324,9 +328,10 @@ func portForwardExpr(port uint16, dest net.IP, dport uint16) []expr.Any {
}
type portForwarding struct {
Port uint16 `json:"port"` // e.g. 8080
DestAddr string `json:"dest_addr"` // e.g. 192.168.42.2
DestPort uint16 `json:"dest_port"` // e.g. 80
Proto string `json:"proto"` // e.g. “tcp” (or “tcp,udp”)
Port uint16 `json:"port"` // e.g. “8080”
DestAddr string `json:"dest_addr"` // e.g. “192.168.42.2”
DestPort uint16 `json:"dest_port"` // e.g. “80”
}
type portForwardings struct {
@ -347,12 +352,23 @@ func applyPortForwardings(dir string, c *nftables.Conn, nat *nftables.Table, pre
}
for _, fw := range cfg.Forwardings {
for _, proto := range strings.Split(fw.Proto, ",") {
var p uint8
switch proto {
case "", "tcp":
p = unix.IPPROTO_TCP
case "udp":
p = unix.IPPROTO_UDP
default:
return fmt.Errorf(`unknown proto %q, expected "tcp" or "udp"`, proto)
}
c.AddRule(&nftables.Rule{
Table: nat,
Chain: prerouting,
Exprs: portForwardExpr(fw.Port, net.ParseIP(fw.DestAddr), fw.DestPort),
Exprs: portForwardExpr(p, fw.Port, net.ParseIP(fw.DestAddr), fw.DestPort),
})
}
}
return nil
}