Set up ip masquerading using nftables

This commit is contained in:
Daniel Lundin
2019-05-01 20:05:36 +02:00
parent 21fda35e08
commit bf60a2c206
3 changed files with 71 additions and 1 deletions
+3 -1
View File
@@ -5,9 +5,11 @@ go 1.12
require (
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
github.com/google/nftables v0.0.0-20190430150743-07c974e3643d
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d // indirect
github.com/mdlayher/wireguardctrl v0.0.0-20190419142446-a4a944b88a6b
github.com/sirupsen/logrus v1.4.1
github.com/vishvananda/netlink v1.0.0
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc
gopkg.in/alecthomas/kingpin.v2 v2.2.6
)
+4
View File
@@ -5,6 +5,10 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/nftables v0.0.0-20190430150743-07c974e3643d h1:TC4HtISCtWOTUVPQmq4CAqe0+8R2fvnkJlQn47ep2hI=
github.com/google/nftables v0.0.0-20190430150743-07c974e3643d/go.mod h1:H/FvZdk1xWxiE2Ad0wX6mq/oqHvEE1LDDujRgYwi3ns=
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d h1:MFX8DxRnKMY/2M3H61iSsVbo/n3h0MWGmWNN1UViOU0=
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d/go.mod h1:QHb4k4cr1fQikUahfcRVPcEXiUgFsdIstGqlurL0XL4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/mdlayher/genetlink v0.0.0-20190419142426-b806ce69960a h1:tIPUNU99ot2Tko8SorsytkeFC0to6pRJB6koxswpeB8=
github.com/mdlayher/genetlink v0.0.0-20190419142426-b806ce69960a/go.mod h1:J+g63IQCVwjKLOxodrxOylt23f7d5vVB9rgNh+T13Uk=
+64
View File
@@ -4,10 +4,13 @@ import (
"net/http"
"os"
"github.com/google/nftables"
"github.com/google/nftables/expr"
"github.com/mdlayher/wireguardctrl"
"github.com/mdlayher/wireguardctrl/wgtypes"
log "github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
"gopkg.in/alecthomas/kingpin.v2"
)
@@ -15,6 +18,7 @@ var (
listenAddr = kingpin.Flag("listen-address", "Address to listen to").Default(":8080").String()
wgLinkName = kingpin.Flag("wg-device-name", "Wireguard network device name").Default("wg0").String()
wgLinkAddr = kingpin.Flag("wg-link-addr", "Wireguard interface address").Default("172.72.72.1/32").String()
natLink = kingpin.Flag("nat-device", "Network interface to masquerade").Default("wlp2s0").String()
wgListenPort = kingpin.Flag("wg-listen-port", "Wireguard UDP port to listen to").Default("51820").Int()
)
@@ -36,6 +40,12 @@ func (w *WgLink) Type() string {
return "wireguard"
}
func ifname(n string) []byte {
b := make([]byte, 16)
copy(b, []byte(n+"\x00"))
return b
}
func NewServer() *Server {
storage := NewStorage()
@@ -58,6 +68,7 @@ func (s *Server) initInterface() error {
attrs: &attrs,
}
log.Debug("Adding wireguard device: ", *wgLinkName)
err := netlink.LinkAdd(&link)
if os.IsExist(err) {
log.Infof("Wireguard interface %s already exists. Reusing.", *wgLinkName)
@@ -65,6 +76,7 @@ func (s *Server) initInterface() error {
return err
}
log.Debug("Adding ip address to wireguard device: ", *wgLinkAddr)
addr, _ := netlink.ParseAddr(*wgLinkAddr)
err = netlink.AddrAdd(&link, addr)
if os.IsExist(err) {
@@ -73,11 +85,63 @@ func (s *Server) initInterface() error {
return err
}
log.Debug("Adding NAT / IP masquerading using nftables")
ns, err := netns.Get()
if err != nil {
return err
}
conn := nftables.Conn{NetNS: int(ns)}
log.Debug("Flushing nftable rulesets")
conn.FlushRuleset()
log.Debug("Setting up nftable rules for ip masquerading")
nat := conn.AddTable(&nftables.Table{
Family: nftables.TableFamilyIPv4,
Name: "nat",
})
conn.AddChain(&nftables.Chain{
Name: "prerouting",
Table: nat,
Type: nftables.ChainTypeNAT,
Hooknum: nftables.ChainHookPrerouting,
Priority: nftables.ChainPriorityFilter,
})
post := conn.AddChain(&nftables.Chain{
Name: "postrouting",
Table: nat,
Type: nftables.ChainTypeNAT,
Hooknum: nftables.ChainHookPostrouting,
Priority: nftables.ChainPriorityNATSource,
})
conn.AddRule(&nftables.Rule{
Table: nat,
Chain: post,
Exprs: []expr.Any{
&expr.Meta{Key: expr.MetaKeyOIFNAME, Register: 1},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: ifname(*natLink),
},
&expr.Masq{},
},
})
conn.Flush()
wg, err := wireguardctrl.New()
if err != nil {
return err
}
log.Debug("Adding wireguard private key")
key, err := wgtypes.ParseKey(s.config.PrivateKey)
if err != nil {
return err