summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2020-03-18 21:33:35 +0100
committerMikael Magnusson <mikma@users.sourceforge.net>2020-03-18 21:33:35 +0100
commit1d171254911cfcd62926f43938edde2ad20e64fc (patch)
tree77599760f09df953ca2793fe37e7b5131d7d696d /pkg
parent9ff81925ffcb1833871a409c4bc004144062ae22 (diff)
WIP move config to separate package
Diffstat (limited to 'pkg')
-rw-r--r--pkg/tcpip/config/config.go526
-rw-r--r--pkg/tcpip/sample/wg_tunnel/main.go601
2 files changed, 576 insertions, 551 deletions
diff --git a/pkg/tcpip/config/config.go b/pkg/tcpip/config/config.go
new file mode 100644
index 000000000..3c1f91ecc
--- /dev/null
+++ b/pkg/tcpip/config/config.go
@@ -0,0 +1,526 @@
+package config
+
+import (
+ "bufio"
+ "encoding/base64"
+ "encoding/hex"
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "runtime"
+ "strconv"
+ "strings"
+
+ "gvisor.dev/gvisor/pkg/tcpip"
+ "gvisor.dev/gvisor/pkg/tcpip/link/channel"
+ "gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
+ "gvisor.dev/gvisor/pkg/tcpip/link/loopback"
+ "gvisor.dev/gvisor/pkg/tcpip/link/rawfile"
+ "gvisor.dev/gvisor/pkg/tcpip/link/tun"
+ "gvisor.dev/gvisor/pkg/tcpip/link/wireguard"
+ "gvisor.dev/gvisor/pkg/tcpip/network/arp"
+ "gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
+ "gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
+ "gvisor.dev/gvisor/pkg/tcpip/stack"
+
+ "golang.zx2c4.com/wireguard/device"
+ "golang.zx2c4.com/wireguard/ipc"
+// wg_tun "golang.zx2c4.com/wireguard/tun"
+
+ "gopkg.in/yaml.v3"
+)
+
+type Route struct {
+ To string `yaml:"to"`
+ Via string `yaml:"via"`
+ Metric int `yaml:"metric"`
+ Mark uint32 `yaml:"mask"`
+ Markmask uint32 `yaml:"markmask"`
+}
+
+type Common struct {
+ Match struct {
+ Name string `yaml:"name"`
+ } `yaml:"match"`
+ Addresses []string `yaml:"addresses"`
+ Nameservers struct {
+ Addresses []string `yaml:"addresses"`
+ } `yaml:"nameservers"`
+ Macaddress string `yaml:"macaddress"`
+ Routes []Route `yaml:"routes"`
+ Mtu uint32 `yaml:"mtu"`
+}
+
+type Ethernet struct {
+ Common `yaml:",inline"`
+}
+
+type Tuntap struct {
+ Common `yaml:",inline"`
+ Mode string `yaml:"mode"`
+ Name string `yaml:"name"`
+}
+
+type WireguardKey []byte
+
+type Routes []tcpip.Route
+
+func (wgKey *WireguardKey) UnmarshalYAML(value *yaml.Node) error{
+ key, err := base64.StdEncoding.DecodeString(value.Value)
+ fmt.Println("UnmarshalYAML", key, err)
+ *wgKey = key
+ return err
+}
+
+type WireguardPeer struct {
+ PublicKey WireguardKey `yaml:"public_key"`
+ Endpoint string `yaml:"endpoint"`
+ AllowedIPs []string `yaml:"allowed_ips"`
+ PersistentKeepalive int `yaml:"persistent_keepalive"`
+}
+
+func (peer WireguardPeer) String() string{
+ return fmt.Sprintf("{PublicKey=%v, Endpoint=%v, AllowedIPs=%v, PersistentKeepalive=%v}", peer.PublicKey, peer.Endpoint, peer.AllowedIPs, peer.PersistentKeepalive)
+}
+
+type Wireguard struct {
+ Common `yaml:",inline"`
+ Name string `yaml:"name"`
+ ListenPort uint16 `yaml:"listen_port"`
+ PrivateKey WireguardKey `yaml:"private_key"`
+ Peers []*WireguardPeer `yaml:"peers"`
+}
+
+type Tunnel struct {
+ Common `yaml:",inline"`
+ Mode string `yaml:"mode"`
+ Local string `yaml:"local"`
+ Remote string `yaml:"remote"`
+
+ Conn *net.UDPConn
+ Sd *os.File
+}
+
+type Netplan struct {
+ Network struct {
+ Version int `yaml:"version"`
+ Renderer string `yaml:"renderer"`
+ Ethernets map[string] *Ethernet `yaml:"ethernets"`
+ Tuntaps map[string] *Tuntap `yaml:"tuntaps"`
+ Wireguards map[string] *Wireguard `yaml:"wireguards"`
+ Tunnels map[string] *Tunnel `yaml:"tunnels"`
+ } `yaml:"network"`
+}
+
+func CheckError(err error) {
+ if err != nil {
+ log.Fatal("Error: " , err)
+ }
+}
+
+func addTunLink(s *stack.Stack, nic tcpip.NICID, id string, tap bool, addr tcpip.LinkAddress, tuntap *Tuntap) {
+ var err error
+
+ mtu := tuntap.Mtu
+ tunName := tuntap.Name
+
+ if mtu == 0 {
+ mtu, err = rawfile.GetMTU(tunName)
+ if err != nil {
+ log.Fatal("GetMTU", err)
+ }
+ }
+
+ var fd int
+ if tap {
+ fd, err = tun.OpenTAP(tunName)
+ } else {
+ fd, err = tun.Open(tunName)
+ }
+ if err != nil {
+ log.Fatalf("Open %s %b %s", err, tap, tunName)
+ }
+
+ linkEP, err := fdbased.New(&fdbased.Options{
+ FDs: []int{fd},
+ MTU: mtu,
+ EthernetHeader: tap,
+ Address: addr,
+ })
+ if err := s.CreateNICWithOptions(nic, linkEP, stack.NICOptions{Name: id, Disabled: true}); err != nil {
+ log.Fatal("CreateNIC", err)
+ }
+
+ if tap {
+ if err := s.AddAddress(nic, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
+ log.Fatal("AddAddress", err)
+ }
+ }
+}
+
+func addRouterLink(s *stack.Stack, nic tcpip.NICID, id string, addr tcpip.LinkAddress,
+ tun *Tunnel) {
+
+ ServerAddr,err := net.ResolveUDPAddr("udp", tun.Remote)
+ CheckError(err)
+
+ LocalAddr, err := net.ResolveUDPAddr("udp", tun.Local)
+ CheckError(err)
+
+ conn, err := net.DialUDP("udp", LocalAddr, ServerAddr)
+ CheckError(err)
+
+ tun.Conn = conn
+
+ fmt.Println("Tunnel ", conn)
+
+ sd, err := conn.File()
+ CheckError(err)
+
+ tun.Sd = sd
+
+ conn.Close()
+
+ var fd int
+ fd = int(sd.Fd())
+ //TestFinialize(&tun.Conn)
+ runtime.GC()
+ linkEP, err := fdbased.New(&fdbased.Options{
+ FDs: []int{fd},
+ MTU: tun.Mtu,
+ EthernetHeader: true,
+// EthernetHeader: false,
+ Address: addr,
+ })
+ CheckError(err)
+
+ fmt.Println("addRouterLink MTU ", tun.Mtu, tun.Conn)
+ //channelSize := 128
+ // linkEP := channel.New(channelSize, mtu, addr)
+ if err := s.CreateNICWithOptions(nic, linkEP, stack.NICOptions{Name: id, Disabled: true}); err != nil {
+ log.Fatal("CreateNIC ", id, err)
+ }
+
+ if err := s.AddAddress(nic, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
+ log.Fatal("AddAddress", err)
+ }
+
+// client(linkEP.C)
+ fmt.Println("Tunnel ", tun.Conn)
+}
+
+func addWgLink(s *stack.Stack, nic tcpip.NICID, interfaceName string, addr tcpip.LinkAddress) *device.Device {
+ loglevel := device.LogLevelDebug
+
+ chanSize := 1024
+ var chanMtu uint32 = 1420
+ ep := channel.New(chanSize, chanMtu, addr)
+
+ logger := device.NewLogger(loglevel, "(wg_tunnel) ")
+
+ //mtu := 1500
+ // tun, err := wg_tun.CreateTUN(interfaceName, mtu)
+ tun, err := wireguard.CreateWgTun(s, ep)
+ if err != nil {
+ log.Fatal("CreateWgTun", err)
+ }
+
+
+ fileUAPI, err := func() (*os.File, error) {
+ ENV_WG_UAPI_FD := "WG_UAPI_FD"
+ uapiFdStr := os.Getenv(ENV_WG_UAPI_FD)
+ if uapiFdStr == "" {
+ return ipc.UAPIOpen(interfaceName)
+ }
+
+ // use supplied fd
+
+ fd, err := strconv.ParseUint(uapiFdStr, 10, 32)
+ if err != nil {
+ return nil, err
+ }
+
+ return os.NewFile(uintptr(fd), ""), nil
+ }()
+
+ if err != nil {
+ logger.Error.Println("UAPI listen error:", err)
+ log.Fatal("Setup failed")
+ }
+ // daemonize the process
+
+ device := device.NewDevice(tun, logger)
+
+ errs := make(chan error)
+
+ uapi, err := ipc.UAPIListen(interfaceName, fileUAPI)
+ if err != nil {
+ logger.Error.Println("Failed to listen on uapi socket:", err)
+ log.Fatal("Setup failed")
+ }
+
+ go func() {
+ for {
+ conn, err := uapi.Accept()
+ if err != nil {
+ errs <- err
+ return
+ }
+ go device.IpcHandle(conn)
+ }
+ }()
+
+ logger.Info.Println("UAPI listener started")
+ fmt.Println("Device ", device)
+
+ if err := s.CreateNICWithOptions(nic, ep, stack.NICOptions{Name: interfaceName, Disabled: true}); err != nil {
+ log.Fatal("CreateNIC", err)
+ }
+
+ return device
+}
+
+func parseAddress(addrName string) (tcpip.Address, tcpip.NetworkProtocolNumber) {
+ ip := net.ParseIP(addrName)
+
+ if ip.To4() != nil {
+ return tcpip.Address(ip.To4()), ipv4.ProtocolNumber
+ } else {
+ return tcpip.Address(ip.To16()), ipv6.ProtocolNumber
+ }
+}
+
+func ParseSubnet(subnetName string) (tcpip.Address, tcpip.Subnet, tcpip.NetworkProtocolNumber) {
+ parsedAddr, parsedNet, err := net.ParseCIDR(subnetName)
+ if err != nil {
+ log.Fatalf("Bad IP/CIDR address: %v", subnetName)
+ }
+
+ var addr tcpip.Address
+ var net tcpip.Address
+ var proto tcpip.NetworkProtocolNumber
+
+ if parsedAddr.To4() != nil {
+ addr = tcpip.Address(parsedAddr.To4())
+ net = tcpip.Address(parsedNet.IP.To4())
+ proto = ipv4.ProtocolNumber
+ } else {
+ addr = tcpip.Address(parsedAddr.To16())
+ net = tcpip.Address(parsedNet.IP.To16())
+ proto = ipv6.ProtocolNumber
+ }
+
+ // ones, zeros := parsedNet.Mask.Size()
+
+ mask, err := hex.DecodeString(parsedNet.Mask.String())
+ if err != nil {
+ log.Fatalf("Bad mask", err)
+ }
+
+ subnet, err := tcpip.NewSubnet(net, tcpip.AddressMask(mask))
+ if err != nil {
+ log.Fatalf("Bad subnet", err, net, parsedNet.Mask.String())
+ }
+
+ return addr, subnet, proto
+}
+
+func (routes *Routes) AddAddress(s *stack.Stack, nic tcpip.NICID, addrName string) tcpip.NetworkProtocolNumber {
+ // // Parse the IP address. Support both ipv4 and ipv6.
+ addr, subnet, proto := ParseSubnet(addrName)
+
+ if false {
+ if err := s.AddAddress(nic, proto, addr); err != nil {
+ log.Fatal("AddAddress", err)
+ }
+ } else {
+ addr := tcpip.ProtocolAddress{
+ Protocol: proto,
+ AddressWithPrefix: tcpip.AddressWithPrefix{
+ Address: addr,
+ PrefixLen: subnet.Prefix(),
+ }}
+
+ fmt.Println("Added address ", addr)
+
+ if err := s.AddProtocolAddress(nic, addr); err != nil {
+ log.Fatalf("AddProtocolAddress", err, nic)
+ }
+
+ route := tcpip.Route{
+ Destination: addr.AddressWithPrefix.Subnet(),
+ NIC: nic,
+ }
+
+ *routes = append(*routes, route)
+ }
+
+ // subnet, err := tcpip.NewSubnet(tcpip.Address(parsedNet.IP),
+ // tcpip.AddressMask(parsedNet.Mask))
+ // if err != nil {
+ // log.Fatal(err)
+ // }
+
+ return proto
+}
+
+func (routes *Routes) addRoute(nic tcpip.NICID, routeCfg Route){
+ _, dest, _ := ParseSubnet(routeCfg.To)
+ via, _ := parseAddress(routeCfg.Via)
+
+ route := tcpip.Route{
+ Destination: dest,
+ Gateway: via,
+ NIC: nic,
+ Mark: routeCfg.Mark,
+ Markmask: routeCfg.Markmask,
+ }
+
+ *routes = append(*routes, route)
+}
+
+func (routes *Routes) setupCommon(s *stack.Stack, nic tcpip.NICID, id string, cfg Common) {
+ for _, addr := range cfg.Addresses {
+ routes.AddAddress(s, nic, addr)
+ }
+
+ for _, route := range cfg.Routes {
+ fmt.Println("Add Route:", route)
+ routes.addRoute(nic, route)
+ }
+
+ for _, route := range *routes {
+ fmt.Println("Added Route:", route)
+ }
+
+ // TODO check after enabling the NICs
+ // if !s.CheckNIC(nic) {
+ // log.Fatal("not usable ", id)
+ // }
+}
+
+func (routes *Routes) setupLoopback(s *stack.Stack, nic tcpip.NICID, id string, eth *Ethernet) {
+ fmt.Println("Ethernet", id, nic, eth)
+
+ linkEP := loopback.New()
+ if err := s.CreateNICWithOptions(nic, linkEP, stack.NICOptions{Name: id, Disabled: true}); err != nil {
+ log.Fatal("CreateNIC", err)
+ }
+
+ routes.setupCommon(s, nic, id, eth.Common)
+}
+
+func (routes *Routes) setupTunnel(s *stack.Stack, nic tcpip.NICID, id string, tun *Tunnel) {
+ fmt.Println("TUN", id, nic, tun)
+
+ maddr, err := net.ParseMAC(tun.Macaddress)
+ if err != nil {
+ log.Fatalf("Bad MAC address: %v", tun.Macaddress)
+ }
+
+ addRouterLink(s, nic, id, tcpip.LinkAddress(maddr), tun)
+ fmt.Println("Tunnel 20", tun.Conn)
+ routes.setupCommon(s, nic, id, tun.Common)
+ fmt.Println("Tunnel 21", tun.Conn)
+}
+
+func (routes *Routes) setupTuntap(s *stack.Stack, nic tcpip.NICID, id string, tun *Tuntap) {
+ fmt.Println("Tuntap", id, nic, tun)
+
+ maddr, err := net.ParseMAC(tun.Macaddress)
+ if err != nil {
+ log.Fatalf("Bad MAC address: %v", tun.Macaddress)
+ }
+
+ var tap bool
+ switch tun.Mode {
+ case "tun":
+ tap = false
+ case "tap":
+ tap = true
+ default:
+ log.Fatalf("Bad mode: %v", tun.Mode)
+ }
+
+ addTunLink(s, nic, id, tap, tcpip.LinkAddress(maddr), tun)
+ routes.setupCommon(s, nic, id, tun.Common)
+}
+
+func (routes *Routes) setupWG(s *stack.Stack, nic tcpip.NICID, id string, wg *Wireguard) {
+ fmt.Println("WG", id, nic, wg.ListenPort, wg)
+ fmt.Printf("Peers %v\n", wg.Peers)
+
+ maddr, err := net.ParseMAC(wg.Macaddress)
+ if err != nil {
+ log.Fatalf("Bad MAC address: %v", wg.Macaddress)
+ }
+
+ //addTunLink(s, tunNic, tunName, tcpip.LinkAddress(tapMaddr))
+ device := addWgLink(s, nic, wg.Name, tcpip.LinkAddress(maddr))
+
+ var wgCmd strings.Builder
+ fmt.Fprintf(&wgCmd, "private_key=%s\nlisten_port=%d\nreplace_peers=true\n",
+ hex.EncodeToString(wg.PrivateKey), wg.ListenPort)
+ for _, peer := range wg.Peers {
+ fmt.Fprintf(&wgCmd, "public_key=%s\nendpoint=%s\npersistent_keepalive_interval=%d\nreplace_allowed_ips=true\n",
+ hex.EncodeToString(peer.PublicKey), peer.Endpoint, peer.PersistentKeepalive)
+ for _, allowedIp := range peer.AllowedIPs {
+ fmt.Fprintf(&wgCmd, "allowed_ip=%s\n", allowedIp)
+ }
+ wgCmd.WriteString("\n")
+ }
+ str := wgCmd.String()
+ fmt.Println("IpcSetOperation", str)
+ device.IpcSetOperation(bufio.NewReader(strings.NewReader(str)))
+
+ routes.setupCommon(s, nic, id, wg.Common)
+
+ go func() {
+ fmt.Println("Starting ", nic)
+
+ select {
+ // case <-term:
+ // case <-errs:
+ case <-device.Wait():
+ }
+
+ fmt.Println("Finnished ", nic)
+ }()
+}
+
+func (routes *Routes) Setup(s *stack.Stack, np *Netplan) {
+ s.SetForwarding(true)
+
+ var nic tcpip.NICID = -1
+// var wg2Nic tcpip.NICID = -1
+
+ for id, tun := range np.Network.Ethernets {
+ nic = nic + 1
+ routes.setupLoopback(s, nic, id, tun)
+ }
+
+ for id, tun := range np.Network.Tuntaps {
+ nic = nic + 1
+ routes.setupTuntap(s, nic, id, tun)
+ }
+
+ for id, wg := range np.Network.Wireguards {
+ nic = nic + 1
+ // if id == "wg2" {
+ // wg2Nic = nic
+ // }
+ routes.setupWG(s, nic, id, wg)
+ }
+
+ for id, tun := range np.Network.Tunnels {
+ nic = nic + 1
+ routes.setupTunnel(s, nic, id, tun)
+ }
+
+ nicCount := nic
+
+ for nic = 0; nic < nicCount; nic++ {
+ s.EnableNIC(nic)
+ }
+}
diff --git a/pkg/tcpip/sample/wg_tunnel/main.go b/pkg/tcpip/sample/wg_tunnel/main.go
index 1c87a09c2..066216dfb 100644
--- a/pkg/tcpip/sample/wg_tunnel/main.go
+++ b/pkg/tcpip/sample/wg_tunnel/main.go
@@ -20,10 +20,7 @@
package main
import (
- "bufio"
"context"
- "encoding/base64"
- "encoding/hex"
"flag"
"fmt"
"io/ioutil"
@@ -34,17 +31,11 @@ import (
"runtime"
"sort"
"strconv"
- "strings"
"time"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
- "gvisor.dev/gvisor/pkg/tcpip/link/channel"
- "gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
- "gvisor.dev/gvisor/pkg/tcpip/link/loopback"
- "gvisor.dev/gvisor/pkg/tcpip/link/rawfile"
- "gvisor.dev/gvisor/pkg/tcpip/link/tun"
- "gvisor.dev/gvisor/pkg/tcpip/link/wireguard"
+ "gvisor.dev/gvisor/pkg/tcpip/config"
"gvisor.dev/gvisor/pkg/tcpip/network/arp"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
@@ -54,9 +45,6 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
"gvisor.dev/gvisor/pkg/waiter"
- "golang.zx2c4.com/wireguard/device"
- "golang.zx2c4.com/wireguard/ipc"
-// wg_tun "golang.zx2c4.com/wireguard/tun"
"gopkg.in/yaml.v3"
@@ -66,86 +54,6 @@ import (
"github.com/insomniacslk/dhcp/iana"
)
-type Route struct {
- To string `yaml:"to"`
- Via string `yaml:"via"`
- Metric int `yaml:"metric"`
- Mark uint32 `yaml:"mask"`
- Markmask uint32 `yaml:"markmask"`
-}
-
-type Common struct {
- Match struct {
- Name string `yaml:"name"`
- } `yaml:"match"`
- Addresses []string `yaml:"addresses"`
- Nameservers struct {
- Addresses []string `yaml:"addresses"`
- } `yaml:"nameservers"`
- Macaddress string `yaml:"macaddress"`
- Routes []Route `yaml:"routes"`
- Mtu uint32 `yaml:"mtu"`
-}
-
-type Ethernet struct {
- Common `yaml:",inline"`
-}
-
-type Tuntap struct {
- Common `yaml:",inline"`
- Mode string `yaml:"mode"`
- Name string `yaml:"name"`
-}
-
-type WireguardKey []byte
-
-func (wgKey *WireguardKey) UnmarshalYAML(value *yaml.Node) error{
- key, err := base64.StdEncoding.DecodeString(value.Value)
- fmt.Println("UnmarshalYAML", key, err)
- *wgKey = key
- return err
-}
-
-type WireguardPeer struct {
- PublicKey WireguardKey `yaml:"public_key"`
- Endpoint string `yaml:"endpoint"`
- AllowedIPs []string `yaml:"allowed_ips"`
- PersistentKeepalive int `yaml:"persistent_keepalive"`
-}
-
-func (peer WireguardPeer) String() string{
- return fmt.Sprintf("{PublicKey=%v, Endpoint=%v, AllowedIPs=%v, PersistentKeepalive=%v}", peer.PublicKey, peer.Endpoint, peer.AllowedIPs, peer.PersistentKeepalive)
-}
-
-type Wireguard struct {
- Common `yaml:",inline"`
- Name string `yaml:"name"`
- ListenPort uint16 `yaml:"listen_port"`
- PrivateKey WireguardKey `yaml:"private_key"`
- Peers []*WireguardPeer `yaml:"peers"`
-}
-
-type Tunnel struct {
- Common `yaml:",inline"`
- Mode string `yaml:"mode"`
- Local string `yaml:"local"`
- Remote string `yaml:"remote"`
-
- Conn *net.UDPConn
- Sd *os.File
-}
-
-type Netplan struct {
- Network struct {
- Version int `yaml:"version"`
- Renderer string `yaml:"renderer"`
- Ethernets map[string] *Ethernet `yaml:"ethernets"`
- Tuntaps map[string] *Tuntap `yaml:"tuntaps"`
- Wireguards map[string] *Wireguard `yaml:"wireguards"`
- Tunnels map[string] *Tunnel `yaml:"tunnels"`
- } `yaml:"network"`
-}
-
func echo(wq *waiter.Queue, ep tcpip.Endpoint) {
defer ep.Close()
@@ -170,52 +78,6 @@ func echo(wq *waiter.Queue, ep tcpip.Endpoint) {
}
}
-func addTunLink(s *stack.Stack, nic tcpip.NICID, id string, tap bool, addr tcpip.LinkAddress, tuntap *Tuntap) {
- var err error
-
- mtu := tuntap.Mtu
- tunName := tuntap.Name
-
- if mtu == 0 {
- mtu, err = rawfile.GetMTU(tunName)
- if err != nil {
- log.Fatal("GetMTU", err)
- }
- }
-
- var fd int
- if tap {
- fd, err = tun.OpenTAP(tunName)
- } else {
- fd, err = tun.Open(tunName)
- }
- if err != nil {
- log.Fatalf("Open %s %b %s", err, tap, tunName)
- }
-
- linkEP, err := fdbased.New(&fdbased.Options{
- FDs: []int{fd},
- MTU: mtu,
- EthernetHeader: tap,
- Address: addr,
- })
- if err := s.CreateNICWithOptions(nic, linkEP, stack.NICOptions{Name: id, Disabled: true}); err != nil {
- log.Fatal("CreateNIC", err)
- }
-
- if tap {
- if err := s.AddAddress(nic, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
- log.Fatal("AddAddress", err)
- }
- }
-}
-
-func CheckError(err error) {
- if err != nil {
- log.Fatal("Error: " , err)
- }
-}
-
func TestFinialize(conn *net.UDPConn) {
event := make(chan string)
@@ -234,275 +96,51 @@ func TestFinialize(conn *net.UDPConn) {
}
}
-func addRouterLink(s *stack.Stack, nic tcpip.NICID, id string, addr tcpip.LinkAddress,
- tun *Tunnel) {
-
- ServerAddr,err := net.ResolveUDPAddr("udp", tun.Remote)
- CheckError(err)
-
- LocalAddr, err := net.ResolveUDPAddr("udp", tun.Local)
- CheckError(err)
-
- conn, err := net.DialUDP("udp", LocalAddr, ServerAddr)
- CheckError(err)
-
- tun.Conn = conn
-
- fmt.Println("Tunnel ", conn)
-
- sd, err := conn.File()
- CheckError(err)
-
- tun.Sd = sd
-
- conn.Close()
-
- var fd int
- fd = int(sd.Fd())
- //TestFinialize(&tun.Conn)
- runtime.GC()
- linkEP, err := fdbased.New(&fdbased.Options{
- FDs: []int{fd},
- MTU: tun.Mtu,
- EthernetHeader: true,
-// EthernetHeader: false,
- Address: addr,
- })
- CheckError(err)
-
- fmt.Println("addRouterLink MTU ", tun.Mtu, tun.Conn)
- //channelSize := 128
- // linkEP := channel.New(channelSize, mtu, addr)
- if err := s.CreateNICWithOptions(nic, linkEP, stack.NICOptions{Name: id, Disabled: true}); err != nil {
- log.Fatal("CreateNIC ", id, err)
- }
-
- if err := s.AddAddress(nic, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
- log.Fatal("AddAddress", err)
- }
-
-// client(linkEP.C)
- fmt.Println("Tunnel ", tun.Conn)
-}
-
-func addWgLink(s *stack.Stack, nic tcpip.NICID, interfaceName string, addr tcpip.LinkAddress) *device.Device {
- loglevel := device.LogLevelDebug
-
- chanSize := 1024
- var chanMtu uint32 = 1420
- ep := channel.New(chanSize, chanMtu, addr)
-
- logger := device.NewLogger(loglevel, "(wg_tunnel) ")
-
- //mtu := 1500
- // tun, err := wg_tun.CreateTUN(interfaceName, mtu)
- tun, err := wireguard.CreateWgTun(s, ep)
- if err != nil {
- log.Fatal("CreateWgTun", err)
- }
-
-
- fileUAPI, err := func() (*os.File, error) {
- ENV_WG_UAPI_FD := "WG_UAPI_FD"
- uapiFdStr := os.Getenv(ENV_WG_UAPI_FD)
- if uapiFdStr == "" {
- return ipc.UAPIOpen(interfaceName)
- }
-
- // use supplied fd
-
- fd, err := strconv.ParseUint(uapiFdStr, 10, 32)
- if err != nil {
- return nil, err
- }
-
- return os.NewFile(uintptr(fd), ""), nil
- }()
-
- if err != nil {
- logger.Error.Println("UAPI listen error:", err)
- log.Fatal("Setup failed")
- }
- // daemonize the process
-
- device := device.NewDevice(tun, logger)
-
- errs := make(chan error)
-
- uapi, err := ipc.UAPIListen(interfaceName, fileUAPI)
- if err != nil {
- logger.Error.Println("Failed to listen on uapi socket:", err)
- log.Fatal("Setup failed")
- }
-
- go func() {
- for {
- conn, err := uapi.Accept()
- if err != nil {
- errs <- err
- return
- }
- go device.IpcHandle(conn)
- }
- }()
-
- logger.Info.Println("UAPI listener started")
- fmt.Println("Device ", device)
-
- if err := s.CreateNICWithOptions(nic, ep, stack.NICOptions{Name: interfaceName, Disabled: true}); err != nil {
- log.Fatal("CreateNIC", err)
- }
-
- return device
-}
-
-func parseAddress(addrName string) (tcpip.Address, tcpip.NetworkProtocolNumber) {
- ip := net.ParseIP(addrName)
-
- if ip.To4() != nil {
- return tcpip.Address(ip.To4()), ipv4.ProtocolNumber
- } else {
- return tcpip.Address(ip.To16()), ipv6.ProtocolNumber
- }
-}
-
-func parseSubnet(subnetName string) (tcpip.Address, tcpip.Subnet, tcpip.NetworkProtocolNumber) {
- parsedAddr, parsedNet, err := net.ParseCIDR(subnetName)
- if err != nil {
- log.Fatalf("Bad IP/CIDR address: %v", subnetName)
- }
-
- var addr tcpip.Address
- var net tcpip.Address
- var proto tcpip.NetworkProtocolNumber
-
- if parsedAddr.To4() != nil {
- addr = tcpip.Address(parsedAddr.To4())
- net = tcpip.Address(parsedNet.IP.To4())
- proto = ipv4.ProtocolNumber
- } else {
- addr = tcpip.Address(parsedAddr.To16())
- net = tcpip.Address(parsedNet.IP.To16())
- proto = ipv6.ProtocolNumber
- }
-
- // ones, zeros := parsedNet.Mask.Size()
-
- mask, err := hex.DecodeString(parsedNet.Mask.String())
- if err != nil {
- log.Fatalf("Bad mask", err)
- }
-
- subnet, err := tcpip.NewSubnet(net, tcpip.AddressMask(mask))
- if err != nil {
- log.Fatalf("Bad subnet", err, net, parsedNet.Mask.String())
- }
-
- return addr, subnet, proto
-}
-
-func (routes *Routes) addAddress(s *stack.Stack, nic tcpip.NICID, addrName string) tcpip.NetworkProtocolNumber {
- // // Parse the IP address. Support both ipv4 and ipv6.
- addr, subnet, proto := parseSubnet(addrName)
-
- if false {
- if err := s.AddAddress(nic, proto, addr); err != nil {
- log.Fatal("AddAddress", err)
- }
- } else {
- addr := tcpip.ProtocolAddress{
- Protocol: proto,
- AddressWithPrefix: tcpip.AddressWithPrefix{
- Address: addr,
- PrefixLen: subnet.Prefix(),
- }}
-
- fmt.Println("Added address ", addr)
-
- if err := s.AddProtocolAddress(nic, addr); err != nil {
- log.Fatalf("AddProtocolAddress", err, nic)
- }
-
- route := tcpip.Route{
- Destination: addr.AddressWithPrefix.Subnet(),
- NIC: nic,
- }
+// func (routes *Routes) OnDuplicateAddressDetectionStatus(nicID tcpip.NICID, addr tcpip.Address, resolved bool, err *tcpip.Error) {
+// fmt.Println("OnDuplicateAddressDetectionStatus ", addr)
+// }
- *routes = append(*routes, route)
- }
+// func (routes *Routes) OnDefaultRouterDiscovered(nicID tcpip.NICID, addr tcpip.Address) bool {
+// fmt.Println("OnDefaultRouterDiscovered")
+// return true
+// }
- // subnet, err := tcpip.NewSubnet(tcpip.Address(parsedNet.IP),
- // tcpip.AddressMask(parsedNet.Mask))
- // if err != nil {
- // log.Fatal(err)
- // }
+// func (routes *Routes) OnDefaultRouterInvalidated(nicID tcpip.NICID, addr tcpip.Address) {
+// }
- return proto
-}
-
-type Routes []tcpip.Route
+// func (routes *Routes) OnOnLinkPrefixDiscovered(nicID tcpip.NICID, prefix tcpip.Subnet) bool {
+// fmt.Println("OnOnLinkPrefixDiscovered ", prefix)
+// return true
+// }
+// func (routes *Routes) OnOnLinkPrefixInvalidated(nicID tcpip.NICID, prefix tcpip.Subnet) {
+// }
-func (routes *Routes) OnDuplicateAddressDetectionStatus(nicID tcpip.NICID, addr tcpip.Address, resolved bool, err *tcpip.Error) {
- fmt.Println("OnDuplicateAddressDetectionStatus ", addr)
-}
+// func (routes *Routes) OnAutoGenAddress(tcpip.NICID, tcpip.AddressWithPrefix) bool {
+// return true
+// }
-func (routes *Routes) OnDefaultRouterDiscovered(nicID tcpip.NICID, addr tcpip.Address) bool {
- fmt.Println("OnDefaultRouterDiscovered")
- return true
-}
+// func (routes *Routes) OnAutoGenAddressDeprecated(tcpip.NICID, tcpip.AddressWithPrefix) {
+// }
-func (routes *Routes) OnDefaultRouterInvalidated(nicID tcpip.NICID, addr tcpip.Address) {
-}
+// func (routes *Routes) OnAutoGenAddressInvalidated(tcpip.NICID, tcpip.AddressWithPrefix) {
+// }
-func (routes *Routes) OnOnLinkPrefixDiscovered(nicID tcpip.NICID, prefix tcpip.Subnet) bool {
- fmt.Println("OnOnLinkPrefixDiscovered ", prefix)
- return true
-}
+// func (routes *Routes) OnRecursiveDNSServerOption(nicID tcpip.NICID, addrs []tcpip.Address, lifetime time.Duration) {
+// fmt.Println("OnRecursiveDNSServerOption ", addrs)
+// }
-func (routes *Routes) OnOnLinkPrefixInvalidated(nicID tcpip.NICID, prefix tcpip.Subnet) {
-}
-
-func (routes *Routes) OnAutoGenAddress(tcpip.NICID, tcpip.AddressWithPrefix) bool {
- return true
-}
-
-func (routes *Routes) OnAutoGenAddressDeprecated(tcpip.NICID, tcpip.AddressWithPrefix) {
-}
-
-func (routes *Routes) OnAutoGenAddressInvalidated(tcpip.NICID, tcpip.AddressWithPrefix) {
-}
-
-func (routes *Routes) OnRecursiveDNSServerOption(nicID tcpip.NICID, addrs []tcpip.Address, lifetime time.Duration) {
- fmt.Println("OnRecursiveDNSServerOption ", addrs)
-}
-
-func (routes *Routes) OnDHCPv6Configuration(nicID tcpip.NICID, config stack.DHCPv6ConfigurationFromNDPRA) {
- str := "undefined"
- switch config {
- case stack.DHCPv6NoConfiguration: str = "no config"
- case stack.DHCPv6ManagedAddress: str = "managed"
- case stack.DHCPv6OtherConfigurations: str = "other"
- }
+// func (routes *Routes) OnDHCPv6Configuration(nicID tcpip.NICID, config stack.DHCPv6ConfigurationFromNDPRA) {
+// str := "undefined"
+// switch config {
+// case stack.DHCPv6NoConfiguration: str = "no config"
+// case stack.DHCPv6ManagedAddress: str = "managed"
+// case stack.DHCPv6OtherConfigurations: str = "other"
+// }
- fmt.Println("OnDHCPv6Configuration ", str)
-}
-
+// fmt.Println("OnDHCPv6Configuration ", str)
+// }
-func (routes *Routes) addRoute(nic tcpip.NICID, routeCfg Route){
- _, dest, _ := parseSubnet(routeCfg.To)
- via, _ := parseAddress(routeCfg.Via)
-
- route := tcpip.Route{
- Destination: dest,
- Gateway: via,
- NIC: nic,
- Mark: routeCfg.Mark,
- Markmask: routeCfg.Markmask,
- }
-
- *routes = append(*routes, route)
-}
func protocolToString(proto tcpip.NetworkProtocolNumber) string {
switch proto {
@@ -533,120 +171,11 @@ func dumpRoutes(s *stack.Stack) {
}
}
-func (routes *Routes) setupCommon(s *stack.Stack, nic tcpip.NICID, id string, cfg Common) {
- for _, addr := range cfg.Addresses {
- routes.addAddress(s, nic, addr)
- }
-
- for _, route := range cfg.Routes {
- fmt.Println("Add Route:", route)
- routes.addRoute(nic, route)
- }
-
- for _, route := range *routes {
- fmt.Println("Added Route:", route)
- }
-
- // TODO check after enabling the NICs
- // if !s.CheckNIC(nic) {
- // log.Fatal("not usable ", id)
- // }
-}
-
-func (routes *Routes) setupLoopback(s *stack.Stack, nic tcpip.NICID, id string, eth *Ethernet) {
- fmt.Println("Ethernet", id, nic, eth)
-
- linkEP := loopback.New()
- if err := s.CreateNICWithOptions(nic, linkEP, stack.NICOptions{Name: id, Disabled: true}); err != nil {
- log.Fatal("CreateNIC", err)
- }
-
- routes.setupCommon(s, nic, id, eth.Common)
-}
-
-func (routes *Routes) setupTunnel(s *stack.Stack, nic tcpip.NICID, id string, tun *Tunnel) {
- fmt.Println("TUN", id, nic, tun)
-
- maddr, err := net.ParseMAC(tun.Macaddress)
- if err != nil {
- log.Fatalf("Bad MAC address: %v", tun.Macaddress)
- }
-
- addRouterLink(s, nic, id, tcpip.LinkAddress(maddr), tun)
- fmt.Println("Tunnel 20", tun.Conn)
- routes.setupCommon(s, nic, id, tun.Common)
- fmt.Println("Tunnel 21", tun.Conn)
-}
-
-func (routes *Routes) setupTuntap(s *stack.Stack, nic tcpip.NICID, id string, tun *Tuntap) {
- fmt.Println("Tuntap", id, nic, tun)
-
- maddr, err := net.ParseMAC(tun.Macaddress)
- if err != nil {
- log.Fatalf("Bad MAC address: %v", tun.Macaddress)
- }
-
- var tap bool
- switch tun.Mode {
- case "tun":
- tap = false
- case "tap":
- tap = true
- default:
- log.Fatalf("Bad mode: %v", tun.Mode)
- }
-
- addTunLink(s, nic, id, tap, tcpip.LinkAddress(maddr), tun)
- routes.setupCommon(s, nic, id, tun.Common)
-}
-
-func (routes *Routes) setupWG(s *stack.Stack, nic tcpip.NICID, id string, wg *Wireguard) {
- fmt.Println("WG", id, nic, wg.ListenPort, wg)
- fmt.Printf("Peers %v\n", wg.Peers)
-
- maddr, err := net.ParseMAC(wg.Macaddress)
- if err != nil {
- log.Fatalf("Bad MAC address: %v", wg.Macaddress)
- }
-
- //addTunLink(s, tunNic, tunName, tcpip.LinkAddress(tapMaddr))
- device := addWgLink(s, nic, wg.Name, tcpip.LinkAddress(maddr))
-
- var wgCmd strings.Builder
- fmt.Fprintf(&wgCmd, "private_key=%s\nlisten_port=%d\nreplace_peers=true\n",
- hex.EncodeToString(wg.PrivateKey), wg.ListenPort)
- for _, peer := range wg.Peers {
- fmt.Fprintf(&wgCmd, "public_key=%s\nendpoint=%s\npersistent_keepalive_interval=%d\nreplace_allowed_ips=true\n",
- hex.EncodeToString(peer.PublicKey), peer.Endpoint, peer.PersistentKeepalive)
- for _, allowedIp := range peer.AllowedIPs {
- fmt.Fprintf(&wgCmd, "allowed_ip=%s\n", allowedIp)
- }
- wgCmd.WriteString("\n")
- }
- str := wgCmd.String()
- fmt.Println("IpcSetOperation", str)
- device.IpcSetOperation(bufio.NewReader(strings.NewReader(str)))
-
- routes.setupCommon(s, nic, id, wg.Common)
-
- go func() {
- fmt.Println("Starting ", nic)
-
- select {
- // case <-term:
- // case <-errs:
- case <-device.Wait():
- }
-
- fmt.Println("Finnished ", nic)
- }()
-}
-
-func KeepAliveTunnel(np *Netplan) {
+func KeepAliveTunnel(np *config.Netplan) {
KeepAliveTunnelEx(np, true)
}
-func KeepAliveTunnelEx(np *Netplan, debug bool) {
+func KeepAliveTunnelEx(np *config.Netplan, debug bool) {
for _, tun := range np.Network.Tunnels {
if debug {
fmt.Println("Tunnel ", tun.Mode, tun.Local, tun.Remote, tun.Conn, tun.Sd)
@@ -719,7 +248,7 @@ func NewDHCPv4Query(flags uint32, modifiers ...dhcpv6.Modifier) (*dhcpv6.Message
return msg, nil
}
-func (routes *Routes) doClient(s *stack.Stack, nic tcpip.NICID) {
+func doClient(s *stack.Stack, routes *config.Routes, nic tcpip.NICID) {
fmt.Println("doClient start")
// TODO use link local address
@@ -832,14 +361,14 @@ func (routes *Routes) doClient(s *stack.Stack, nic tcpip.NICID) {
// client.Close()
fmt.Println("doClient end", ack.YourIPAddr, ack.SubnetMask())
ip := net.IPNet{IP: ack.YourIPAddr, Mask:ack.SubnetMask()}
- routes.addAddress(s, nic, ip.String())
+ routes.AddAddress(s, nic, ip.String())
iana := msg.GetOneOption(dhcpv6.OptionIANA).(*dhcpv6.OptIANA)
for _, addr := range iana.Options.Get(dhcpv6.OptionIAAddr) {
str := addr.(*dhcpv6.OptIAAddress).IPv6Addr.String() + "/128"
- routes.addAddress(s, nic, str)
+ routes.AddAddress(s, nic, str)
- _, dest, _ := parseSubnet(addr.(*dhcpv6.OptIAAddress).IPv6Addr.String() + "/64")
+ _, dest, _ := config.ParseSubnet(addr.(*dhcpv6.OptIAAddress).IPv6Addr.String() + "/64")
route := tcpip.Route{
Destination: dest,
NIC: nic,
@@ -853,7 +382,7 @@ func (routes *Routes) doClient(s *stack.Stack, nic tcpip.NICID) {
for _, opt := range iapd.Options.Get(dhcpv6.OptionIAPrefix) {
prefix := opt.(*dhcpv6.OptIAPrefix)
str := prefix.Prefix.IP.String()+"1"+"/128"
- routes.addAddress(s, loNic, str)
+ routes.AddAddress(s, loNic, str)
}
dumpAddresses(s)
@@ -912,7 +441,7 @@ func main() {
log.Fatalf("File reading error", err)
}
- var np Netplan
+ var np config.Netplan
err = yaml.Unmarshal(data, &np)
fmt.Println("err", err)
fmt.Println("res", np)
@@ -926,7 +455,7 @@ func main() {
log.Fatalf("Unable to convert port %v: %v", portName, err)
}
- routes := Routes{}
+ routes := config.Routes{}
// Create the stack with ip and tcp protocols, then add a tun-based
// NIC and address.
@@ -942,40 +471,8 @@ func main() {
})
// FIXME enable
- s.SetForwarding(true)
-
- var nic tcpip.NICID = -1
- var wg2Nic tcpip.NICID = -1
-
- for id, tun := range np.Network.Ethernets {
- nic = nic + 1
- routes.setupLoopback(s, nic, id, tun)
- }
-
- for id, tun := range np.Network.Tuntaps {
- nic = nic + 1
- routes.setupTuntap(s, nic, id, tun)
- }
-
- for id, wg := range np.Network.Wireguards {
- nic = nic + 1
- if id == "wg2" {
- wg2Nic = nic
- }
- routes.setupWG(s, nic, id, wg)
- }
-
- for id, tun := range np.Network.Tunnels {
- nic = nic + 1
- routes.setupTunnel(s, nic, id, tun)
- }
-
- nicCount := nic
-
- for nic = 0; nic < nicCount; nic++ {
- s.EnableNIC(nic)
- }
-
+ routes.Setup(s, &np)
+
KeepAliveTunnel(&np)
// Sort route table for longest prefix match
@@ -986,8 +483,10 @@ func main() {
s.SetRouteTable(routes)
// FIXME disabled for now, to test startSolicitingRouters
- if true {
- routes.doClient(s, wg2Nic)
+ if false {
+ // FIXME
+ var wg2Nic tcpip.NICID = -1
+ doClient(s, &routes, wg2Nic)
}
// Sort route table for longest prefix match