github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/sample/tun_tcp_echo/main.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // +build linux 16 17 // This sample creates a stack with TCP and IPv4 protocols on top of a TUN 18 // device, and listens on a port. Data received by the server in the accepted 19 // connections is echoed back to the clients. 20 package main 21 22 import ( 23 "bytes" 24 "flag" 25 "io" 26 "log" 27 "math/rand" 28 "net" 29 "os" 30 "strconv" 31 "strings" 32 "time" 33 34 "github.com/SagerNet/gvisor/pkg/tcpip" 35 "github.com/SagerNet/gvisor/pkg/tcpip/link/fdbased" 36 "github.com/SagerNet/gvisor/pkg/tcpip/link/rawfile" 37 "github.com/SagerNet/gvisor/pkg/tcpip/link/tun" 38 "github.com/SagerNet/gvisor/pkg/tcpip/network/arp" 39 "github.com/SagerNet/gvisor/pkg/tcpip/network/ipv4" 40 "github.com/SagerNet/gvisor/pkg/tcpip/network/ipv6" 41 "github.com/SagerNet/gvisor/pkg/tcpip/stack" 42 "github.com/SagerNet/gvisor/pkg/tcpip/transport/tcp" 43 "github.com/SagerNet/gvisor/pkg/waiter" 44 ) 45 46 var tap = flag.Bool("tap", false, "use tap istead of tun") 47 var mac = flag.String("mac", "aa:00:01:01:01:01", "mac address to use in tap device") 48 49 type endpointWriter struct { 50 ep tcpip.Endpoint 51 } 52 53 type tcpipError struct { 54 inner tcpip.Error 55 } 56 57 func (e *tcpipError) Error() string { 58 return e.inner.String() 59 } 60 61 func (e *endpointWriter) Write(p []byte) (int, error) { 62 var r bytes.Reader 63 r.Reset(p) 64 n, err := e.ep.Write(&r, tcpip.WriteOptions{}) 65 if err != nil { 66 return int(n), &tcpipError{ 67 inner: err, 68 } 69 } 70 if n != int64(len(p)) { 71 return int(n), io.ErrShortWrite 72 } 73 return int(n), nil 74 } 75 76 func echo(wq *waiter.Queue, ep tcpip.Endpoint) { 77 defer ep.Close() 78 79 // Create wait queue entry that notifies a channel. 80 waitEntry, notifyCh := waiter.NewChannelEntry(nil) 81 82 wq.EventRegister(&waitEntry, waiter.ReadableEvents) 83 defer wq.EventUnregister(&waitEntry) 84 85 w := endpointWriter{ 86 ep: ep, 87 } 88 89 for { 90 _, err := ep.Read(&w, tcpip.ReadOptions{}) 91 if err != nil { 92 if _, ok := err.(*tcpip.ErrWouldBlock); ok { 93 <-notifyCh 94 continue 95 } 96 97 return 98 } 99 } 100 } 101 102 func main() { 103 flag.Parse() 104 if len(flag.Args()) != 3 { 105 log.Fatal("Usage: ", os.Args[0], " <tun-device> <local-address> <local-port>") 106 } 107 108 tunName := flag.Arg(0) 109 addrName := flag.Arg(1) 110 portName := flag.Arg(2) 111 112 rand.Seed(time.Now().UnixNano()) 113 114 // Parse the mac address. 115 maddr, err := net.ParseMAC(*mac) 116 if err != nil { 117 log.Fatalf("Bad MAC address: %v", *mac) 118 } 119 120 // Parse the IP address. Support both ipv4 and ipv6. 121 parsedAddr := net.ParseIP(addrName) 122 if parsedAddr == nil { 123 log.Fatalf("Bad IP address: %v", addrName) 124 } 125 126 var addr tcpip.Address 127 var proto tcpip.NetworkProtocolNumber 128 if parsedAddr.To4() != nil { 129 addr = tcpip.Address(parsedAddr.To4()) 130 proto = ipv4.ProtocolNumber 131 } else if parsedAddr.To16() != nil { 132 addr = tcpip.Address(parsedAddr.To16()) 133 proto = ipv6.ProtocolNumber 134 } else { 135 log.Fatalf("Unknown IP type: %v", addrName) 136 } 137 138 localPort, err := strconv.Atoi(portName) 139 if err != nil { 140 log.Fatalf("Unable to convert port %v: %v", portName, err) 141 } 142 143 // Create the stack with ip and tcp protocols, then add a tun-based 144 // NIC and address. 145 s := stack.New(stack.Options{ 146 NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol, arp.NewProtocol}, 147 TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol}, 148 }) 149 150 mtu, err := rawfile.GetMTU(tunName) 151 if err != nil { 152 log.Fatal(err) 153 } 154 155 var fd int 156 if *tap { 157 fd, err = tun.OpenTAP(tunName) 158 } else { 159 fd, err = tun.Open(tunName) 160 } 161 if err != nil { 162 log.Fatal(err) 163 } 164 165 linkEP, err := fdbased.New(&fdbased.Options{ 166 FDs: []int{fd}, 167 MTU: mtu, 168 EthernetHeader: *tap, 169 Address: tcpip.LinkAddress(maddr), 170 }) 171 if err != nil { 172 log.Fatal(err) 173 } 174 if err := s.CreateNIC(1, linkEP); err != nil { 175 log.Fatal(err) 176 } 177 178 if err := s.AddAddress(1, proto, addr); err != nil { 179 log.Fatal(err) 180 } 181 182 subnet, err := tcpip.NewSubnet(tcpip.Address(strings.Repeat("\x00", len(addr))), tcpip.AddressMask(strings.Repeat("\x00", len(addr)))) 183 if err != nil { 184 log.Fatal(err) 185 } 186 187 // Add default route. 188 s.SetRouteTable([]tcpip.Route{ 189 { 190 Destination: subnet, 191 NIC: 1, 192 }, 193 }) 194 195 // Create TCP endpoint, bind it, then start listening. 196 var wq waiter.Queue 197 ep, e := s.NewEndpoint(tcp.ProtocolNumber, proto, &wq) 198 if e != nil { 199 log.Fatal(e) 200 } 201 202 defer ep.Close() 203 204 if err := ep.Bind(tcpip.FullAddress{0, "", uint16(localPort)}); err != nil { 205 log.Fatal("Bind failed: ", err) 206 } 207 208 if err := ep.Listen(10); err != nil { 209 log.Fatal("Listen failed: ", err) 210 } 211 212 // Wait for connections to appear. 213 waitEntry, notifyCh := waiter.NewChannelEntry(nil) 214 wq.EventRegister(&waitEntry, waiter.ReadableEvents) 215 defer wq.EventUnregister(&waitEntry) 216 217 for { 218 n, wq, err := ep.Accept(nil) 219 if err != nil { 220 if _, ok := err.(*tcpip.ErrWouldBlock); ok { 221 <-notifyCh 222 continue 223 } 224 225 log.Fatal("Accept() failed:", err) 226 } 227 228 go echo(wq, n) // S/R-SAFE: sample code. 229 } 230 }