From 2709c3027cc2d21fa43e285a60fa3aa0b74f9e50 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Tue, 16 Feb 2021 00:41:11 +0100 Subject: WIP gre test and wg_tunnel sample --- pkg/tcpip/sample/tun_tcp_connect/main.go | 77 ++++++++++++++++---- pkg/tcpip/sample/wg_tunnel/config.yaml | 116 ++++++++++++++++++++++++++++++ pkg/tcpip/sample/wg_tunnel/gobgp/main.go | 119 +++++++++++++++++++++++++++++++ pkg/tcpip/sample/wg_tunnel/test/main.go | 66 +++++++++++++++++ 4 files changed, 366 insertions(+), 12 deletions(-) create mode 100644 pkg/tcpip/sample/wg_tunnel/config.yaml create mode 100644 pkg/tcpip/sample/wg_tunnel/gobgp/main.go create mode 100644 pkg/tcpip/sample/wg_tunnel/test/main.go diff --git a/pkg/tcpip/sample/tun_tcp_connect/main.go b/pkg/tcpip/sample/tun_tcp_connect/main.go index 05b879543..2bbb7ffcc 100644 --- a/pkg/tcpip/sample/tun_tcp_connect/main.go +++ b/pkg/tcpip/sample/tun_tcp_connect/main.go @@ -57,8 +57,11 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/link/rawfile" "gvisor.dev/gvisor/pkg/tcpip/link/sniffer" "gvisor.dev/gvisor/pkg/tcpip/link/tun" + "gvisor.dev/gvisor/pkg/tcpip/link/tunnel" "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" + "gvisor.dev/gvisor/pkg/tcpip/network/ipv6" "gvisor.dev/gvisor/pkg/tcpip/stack" + "gvisor.dev/gvisor/pkg/tcpip/transport/gre" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" "gvisor.dev/gvisor/pkg/waiter" ) @@ -89,9 +92,29 @@ func writer(ch chan struct{}, ep tcpip.Endpoint) { } } +func parseIP(s string) tcpip.Address { + addr := tcpip.Address(net.ParseIP(s)) + ip4addr := addr.To4(); if ip4addr != "" { + return ip4addr + } else { + return addr + } +} + +func addAddress(s *stack.Stack, id tcpip.NICID, addr tcpip.Address) *tcpip.Error { + var proto tcpip.NetworkProtocolNumber + if addr.To4() == "" { + proto = ipv6.ProtocolNumber + } else { + proto = ipv4.ProtocolNumber + } + + return s.AddAddress(id, proto, addr) +} + func main() { - if len(os.Args) != 6 { - log.Fatal("Usage: ", os.Args[0], " ") + if len(os.Args) != 8 { + log.Fatal("Usage: ", os.Args[0], " ") } tunName := os.Args[1] @@ -99,15 +122,21 @@ func main() { portName := os.Args[3] remoteAddrName := os.Args[4] remotePortName := os.Args[5] + greAddrName := os.Args[6] + greRemoteAddrName := os.Args[7] rand.Seed(time.Now().UnixNano()) - addr := tcpip.Address(net.ParseIP(addrName).To4()) + addr := parseIP(addrName) + greAddr := parseIP(greAddrName) + greRemoteAddr := parseIP(greRemoteAddrName) remote := tcpip.FullAddress{ - NIC: 1, - Addr: tcpip.Address(net.ParseIP(remoteAddrName).To4()), + NIC: 0, + Addr: parseIP(remoteAddrName), } + log.Printf("local:%v remote:%v", addr, remote) + var localPort uint16 if v, err := strconv.Atoi(portName); err != nil { log.Fatalf("Unable to convert port %v: %v", portName, err) @@ -124,8 +153,8 @@ func main() { // Create the stack with ipv4 and tcp protocols, then add a tun-based // NIC and ipv4 address. s := stack.New(stack.Options{ - NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol}, - TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol}, + NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol}, + TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, gre.NewProtocol}, }) mtu, err := rawfile.GetMTU(tunName) @@ -146,21 +175,42 @@ func main() { log.Fatal(err) } - protocolAddr := tcpip.ProtocolAddress{ - Protocol: ipv4.ProtocolNumber, - AddressWithPrefix: addr.WithPrefix(), + if err := addAddress(s, 1, greAddr); err != nil { + log.Fatal(err) + } + + greEP := tunnel.New(mtu - 24) + if err := s.CreateNIC(2, sniffer.New(greEP)); err != nil { + log.Fatal(err) } - if err := s.AddProtocolAddress(1, protocolAddr, stack.AddressProperties{}); err != nil { - log.Fatalf("AddProtocolAddress(%d, %+v, {}): %s", 1, protocolAddr, err) + if err := addAddress(s, 2, addr); err != nil { + log.Fatal(err) } // Add default route. + subnet, err := tcpip.NewSubnet( + tcpip.Address(parseIP("10.0.0.0")), + tcpip.AddressMask(parseIP("255.255.255.0"))) + if err != nil { + panic(err) + } s.SetRouteTable([]tcpip.Route{ + { + Destination: subnet, + NIC: 1, + }, { Destination: header.IPv4EmptySubnet, + NIC: 2, + }, + { + Destination: header.IPv6EmptySubnet, NIC: 1, }, }) + log.Printf("Nics enabled 1:%v 2:%v 3:%v", s.CheckNIC(1), s.CheckNIC(2), s.CheckNIC(3)) + + greEP.Start(s, &greAddr, &greRemoteAddr) // Create TCP endpoint. var wq waiter.Queue @@ -193,6 +243,9 @@ func main() { fmt.Println("Connected") + payload := tcpip.SlicePayload([]byte("GET / HTTP/1.0\r\nHost: www.m7n.se\r\n\r\n")) + ep.Write(payload, tcpip.WriteOptions{}) + // Start the writer in its own goroutine. writerCompletedCh := make(chan struct{}) go writer(writerCompletedCh, ep) // S/R-SAFE: sample code. diff --git a/pkg/tcpip/sample/wg_tunnel/config.yaml b/pkg/tcpip/sample/wg_tunnel/config.yaml new file mode 100644 index 000000000..7a0c250dc --- /dev/null +++ b/pkg/tcpip/sample/wg_tunnel/config.yaml @@ -0,0 +1,116 @@ +network: + version: 2 + renderer: gvisor + ethernets: + lo: + addresses: + - 127.0.0.1/8 + - ::1/128 + - 10.1.0.1/24 + - 2001:470:de6f:5310::1/64 + routes: + - to: 10.1.15.0/24 + - to: 2001:470:de6f:531f::/64 + tuntaps: + tun: + name: tun1 + mode: tun + mtu: 1280 +# fd: 0 +# name: tap1 +# mode: tap + addresses: + - 10.1.1.2/24 + - 2001:470:de6f:5311::2/64 + nameservers: + addresses: + - 8.8.8.8 + - 8.8.4.4 +# routes: +# - to: 0.0.0.0/0 +# via: 10.1.1.1 +# metric: 200 +# - to: ::/0 +# via: 2001:470:de6f:5311::1 +# metric: 200 + macaddress: aa:00:01:01:02:01 + + tunnels: + tun1: + mode: udp + local: 0.0.0.0:10002 + remote: 127.0.0.1:10001 + #FIXME detect MTU + mtu: 1280 #1500 + addresses: + - 10.1.2.1/24 + - 2001:470:de6f:5312::1/64 + routes: +# - to: 0.0.0.0/0 +# via: 10.1.2.2 +# metric: 100 +# - to: ::/0 +# via: 2001:470:de6f:5312::2 +# metric: 100 + macaddress: aa:00:01:01:02:02 + + wireguards: +# wg1: +# name: wg1 +# addresses: +# - 10.1.3.2/24 +# - 2001:470:de6f:5313::2/64 +# listen_port: 51820 +# private_key: cCBLRrAKF0oqLua2IGYr6ngQRLdgCSTa8hzDLQvezUI= +# peers: +# - public_key: igb6I+JFOEXPN4JjZvSslxNDPQK1/Ofi6310RzH2HAk= +# endpoint: 10.49.50.1:51820 +# allowed_ips: +# - 10.1.2.3/32 +# - 0.0.0.0/0 +# - ::/0 +# # persistent_keepalive: 3600 +# nameservers: +# addresses: +# - 8.8.8.8 +# - 8.8.4.4 +# routes: +# - to: 0.0.0.0/0 +# via: 10.1.3.1 +# metric: 100 +# mark: 1 +# mask: 255 +# - to: ::/0 +# via: 2001:470:de6f:5313::1 +# metric: 100 +# mark: 1 +# mask: 255 +# macaddress: aa:00:01:01:02:03 + + wg2: + name: wg2 + addresses: + - 10.49.124.111/32 + - 2001:470:dfae:6300::111/128 + - 2001:470:dfae:6300::1:111/128 + - fe80::111/64 + listen_port: 51820 + private_key: cCBLRrAKF0oqLua2IGYr6ngQRLdgCSTa8hzDLQvezUI= + peers: + - public_key: 5Q5KIFIeskMh/QanwH9/5lHQ9NhWBsY16kwaS0ELQyg= + endpoint: 10.49.50.215:51820 + allowed_ips: + - 2001:470:dfae:6300::1:3/128 + - ::/0 + - 0.0.0.0/0 + persistent_keepalive: 3600 + nameservers: + addresses: + - 8.8.8.8 + - 8.8.4.4 + routes: + - to: 10.49.124.0/24 + - to: 0.0.0.0/0 + - to: ::/0 + - to: 2001:470:dfae:6300::/64 + macaddress: aa:00:01:01:02:04 diff --git a/pkg/tcpip/sample/wg_tunnel/gobgp/main.go b/pkg/tcpip/sample/wg_tunnel/gobgp/main.go new file mode 100644 index 000000000..3f51adc69 --- /dev/null +++ b/pkg/tcpip/sample/wg_tunnel/gobgp/main.go @@ -0,0 +1,119 @@ +package main + +import ( + "context" + "time" + + "github.com/golang/protobuf/ptypes" + "github.com/golang/protobuf/ptypes/any" + api "github.com/osrg/gobgp/api" + gobgp "github.com/osrg/gobgp/pkg/server" + log "github.com/sirupsen/logrus" +) + +func main() { + log.SetLevel(log.DebugLevel) + s := gobgp.NewBgpServer() + go s.Serve() + + // global configuration + if err := s.StartBgp(context.Background(), &api.StartBgpRequest{ + Global: &api.Global{ + As: 65003, + RouterId: "10.0.255.254", + ListenPort: -1, // gobgp won't listen on tcp:179 + }, + }); err != nil { + log.Fatal(err) + } + + // monitor the change of the peer state + if err := s.MonitorPeer(context.Background(), &api.MonitorPeerRequest{}, func(p *api.Peer) { log.Info(p) }); err != nil { + log.Fatal(err) + } + + // neighbor configuration + n := &api.Peer{ + Conf: &api.PeerConf{ + NeighborAddress: "172.17.0.2", + PeerAs: 65002, + }, + } + + if err := s.AddPeer(context.Background(), &api.AddPeerRequest{ + Peer: n, + }); err != nil { + log.Fatal(err) + } + + // add routes + nlri, _ := ptypes.MarshalAny(&api.IPAddressPrefix{ + Prefix: "10.0.0.0", + PrefixLen: 24, + }) + + a1, _ := ptypes.MarshalAny(&api.OriginAttribute{ + Origin: 0, + }) + a2, _ := ptypes.MarshalAny(&api.NextHopAttribute{ + NextHop: "10.0.0.1", + }) + a3, _ := ptypes.MarshalAny(&api.AsPathAttribute{ + Segments: []*api.AsSegment{ + { + Type: 2, + Numbers: []uint32{6762, 39919, 65000, 35753, 65000}, + }, + }, + }) + attrs := []*any.Any{a1, a2, a3} + + _, err := s.AddPath(context.Background(), &api.AddPathRequest{ + Path: &api.Path{ + Family: &api.Family{Afi: api.Family_AFI_IP, Safi: api.Family_SAFI_UNICAST}, + Nlri: nlri, + Pattrs: attrs, + }, + }) + if err != nil { + log.Fatal(err) + } + + v6Family := &api.Family{ + Afi: api.Family_AFI_IP6, + Safi: api.Family_SAFI_UNICAST, + } + + // add v6 route + nlri, _ = ptypes.MarshalAny(&api.IPAddressPrefix{ + PrefixLen: 64, + Prefix: "2001:db8:1::", + }) + v6Attrs, _ := ptypes.MarshalAny(&api.MpReachNLRIAttribute{ + Family: v6Family, + NextHops: []string{"2001:db8::1"}, + Nlris: []*any.Any{nlri}, + }) + + c, _ := ptypes.MarshalAny(&api.CommunitiesAttribute{ + Communities: []uint32{100, 200}, + }) + + _, err = s.AddPath(context.Background(), &api.AddPathRequest{ + Path: &api.Path{ + Family: v6Family, + Nlri: nlri, + Pattrs: []*any.Any{a1, v6Attrs, c}, + }, + }) + if err != nil { + log.Fatal(err) + } + + s.ListPath(context.Background(), &api.ListPathRequest{Family: v6Family}, func(p *api.Destination) { + log.Info(p) + }) + + // do something useful here instead of exiting + time.Sleep(time.Minute * 3) +} diff --git a/pkg/tcpip/sample/wg_tunnel/test/main.go b/pkg/tcpip/sample/wg_tunnel/test/main.go new file mode 100644 index 000000000..5373ca840 --- /dev/null +++ b/pkg/tcpip/sample/wg_tunnel/test/main.go @@ -0,0 +1,66 @@ +package main + +import ( + "fmt" + "log" + "net" + "runtime" + "syscall" + "time" +) + +func CheckError(err error) { + if err != nil { + log.Fatal("Error: " , err) + } +} + +func TestFinalize(conn *net.UDPConn) { + event := make(chan string) + + runtime.SetFinalizer(conn, func (obj *net.UDPConn) { + fmt.Println("Finalize: UDPConn", obj.LocalAddr(), obj.RemoteAddr()) + event <- "Finalize UDPConn" + }) + + runtime.GC() + + select { + case res := <-event: + fmt.Println(res) + case <-time.After(2 * time.Second): + fmt.Println("No finalize") + } +} + +func test() { + ServerAddr,err := net.ResolveUDPAddr("udp", "127.0.0.1:10001") + CheckError(err) + + LocalAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:10002") + CheckError(err) + + conn, err := net.DialUDP("udp", LocalAddr, ServerAddr) + CheckError(err) + + runtime.KeepAlive(conn) + + sd, err := conn.File() + CheckError(err) + + TestFinalize(conn) + + var fd int + fd = int(sd.Fd()) + + syscall.SetNonblock(fd, true) + + // conn.Write([]byte("HelloWorld!")) + //_, err = sd.Write([]byte("HelloWorld!")) + _, err = syscall.Write(fd, []byte("HelloWorld!")) + CheckError(err) +} + +func main() { + test() +} -- cgit v1.2.3