| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,6 +15,32 @@ import ( | |||
| 15 | 15 | "gvisor.dev/gvisor/pkg/tcpip/transport/udp" | |
| 16 | 16 | ) | |
| 17 | 17 | ||
| 18 | + type GConnHandler interface { | ||
| 19 | + TCP() GTCPConnHandler | ||
| 20 | + UDP() GUDPConnHandler | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + type gconnhandler struct { | ||
| 24 | + GConnHandler | ||
| 25 | + tcp GTCPConnHandler | ||
| 26 | + udp GUDPConnHandler | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + func NewGConnHandler(tcp GTCPConnHandler, udp GUDPConnHandler) GConnHandler { | ||
| 30 | + return &gconnhandler{ | ||
| 31 | + tcp: tcp, | ||
| 32 | + udp: udp, | ||
| 33 | + } | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + func (g *gconnhandler) TCP() GTCPConnHandler { | ||
| 37 | + return g.tcp | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + func (g *gconnhandler) UDP() GUDPConnHandler { | ||
| 41 | + return g.udp | ||
| 42 | + } | ||
| 43 | + | ||
| 18 | 44 | func NewEndpoint(dev int, mtu uint32) (stack.LinkEndpoint, error) { | |
| 19 | 45 | var endpoint stack.LinkEndpoint | |
| 20 | 46 | var fd_array []int | |
@@ -29,7 +55,7 @@ func NewEndpoint(dev int, mtu uint32) (stack.LinkEndpoint, error) { | |||
| 29 | 55 | ||
| 30 | 56 | const nic tcpip.NICID = 0x01 | |
| 31 | 57 | ||
| 32 | - func NewStack(handler GTCPConnHandler, endpoint stack.LinkEndpoint) (*stack.Stack, error) { | ||
| 58 | + func NewStack(handler GConnHandler, endpoint stack.LinkEndpoint) (*stack.Stack, error) { | ||
| 33 | 59 | var o stack.Options | |
| 34 | 60 | o = stack.Options{ | |
| 35 | 61 | NetworkProtocols: []stack.NetworkProtocolFactory{ | |
@@ -60,8 +86,9 @@ func NewStack(handler GTCPConnHandler, endpoint stack.LinkEndpoint) (*stack.Stac | |||
| 60 | 86 | assertNoErr(s.SetSpoofing(nic, true)) | |
| 61 | 87 | // allow all packets sent to our fake nic through to netstack | |
| 62 | 88 | assertNoErr(s.SetPromiscuousMode(nic, true)) | |
| 63 | - setupTcpHandler(s, handler) | ||
| 64 | - // setupUdpHandler(s, handler) | ||
| 89 | + setupTcpHandler(s, handler.TCP()) | ||
| 90 | + setupUdpHandler(s, handler.UDP()) | ||
| 91 | + //setupUdpHandler(s, handler) | ||
| 65 | 92 | // setupIcmpHandler(s, endpoint, handler) | |
| 66 | 93 | ||
| 67 | 94 | return s, nil | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,7 +18,7 @@ import ( | |||
| 18 | 18 | ) | |
| 19 | 19 | ||
| 20 | 20 | type GTCPConnHandler interface { | |
| 21 | - NewConnection(conn GTCPConn, src, dst net.TCPAddr) | ||
| 21 | + NewTCPConnection(conn GTCPConn, src, dst net.TCPAddr) | ||
| 22 | 22 | } | |
| 23 | 23 | ||
| 24 | 24 | func setupTcpHandler(s *stack.Stack, handler GTCPConnHandler) { | |
@@ -43,7 +43,7 @@ func setupTcpHandler(s *stack.Stack, handler GTCPConnHandler) { | |||
| 43 | 43 | Port: int(id.LocalPort), | |
| 44 | 44 | } | |
| 45 | 45 | ||
| 46 | - go handler.NewConnection(GTCPConn{endpoint, gonet.NewTCPConn(waitQueue, endpoint)}, src, dst) | ||
| 46 | + go handler.NewTCPConnection(GTCPConn{endpoint, gonet.NewTCPConn(waitQueue, endpoint)}, src, dst) | ||
| 47 | 47 | }) | |
| 48 | 48 | s.SetTransportProtocolHandler(tcp.ProtocolNumber, forwarder.HandlePacket) | |
| 49 | 49 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,108 @@ | |||
| 1 | + package netstack | ||
| 2 | + | ||
| 3 | + import ( | ||
| 4 | + "net" | ||
| 5 | + "strconv" | ||
| 6 | + "time" | ||
| 7 | + | ||
| 8 | + // "github.com/v2fly/v2ray-core/v5/common/buf" | ||
| 9 | + // v2rayNet "github.com/v2fly/v2ray-core/v5/common/net" | ||
| 10 | + "github.com/eycorsican/go-tun2socks/core" | ||
| 11 | + "gvisor.dev/gvisor/pkg/tcpip" | ||
| 12 | + | ||
| 13 | + "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet" | ||
| 14 | + | ||
| 15 | + "gvisor.dev/gvisor/pkg/tcpip/stack" | ||
| 16 | + "gvisor.dev/gvisor/pkg/tcpip/transport/udp" | ||
| 17 | + "gvisor.dev/gvisor/pkg/waiter" | ||
| 18 | + // "libcore/tun" | ||
| 19 | + ) | ||
| 20 | + | ||
| 21 | + var _ core.UDPConn = (*GUDPConn)(nil) | ||
| 22 | + | ||
| 23 | + type GUDPConnHandler interface { | ||
| 24 | + NewUDPConnection(conn *GUDPConn, src, dst *net.UDPAddr) bool | ||
| 25 | + HandleData(conn *GUDPConn, data []byte, addr *net.UDPAddr) error | ||
| 26 | + } | ||
| 27 | + type GUDPConn struct { | ||
| 28 | + core.UDPConn | ||
| 29 | + ep tcpip.Endpoint | ||
| 30 | + gudp *gonet.UDPConn | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + func setupUdpHandler(s *stack.Stack, handler GUDPConnHandler) { | ||
| 34 | + forwarder := udp.NewForwarder(s, func(request *udp.ForwarderRequest) { | ||
| 35 | + id := request.ID() | ||
| 36 | + waitQueue := new(waiter.Queue) | ||
| 37 | + endpoint, errT := request.CreateEndpoint(waitQueue) | ||
| 38 | + if errT != nil { | ||
| 39 | + | ||
| 40 | + return | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + src := &net.UDPAddr{ | ||
| 44 | + IP: net.IP(id.RemoteAddress), | ||
| 45 | + Port: int(id.RemotePort), | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + dst := &net.UDPAddr{ | ||
| 49 | + IP: net.IP(id.LocalAddress), | ||
| 50 | + Port: int(id.LocalPort), | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + gc := &GUDPConn{ | ||
| 54 | + ep: endpoint, | ||
| 55 | + gudp: gonet.NewUDPConn(s, waitQueue, endpoint), | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + go func() { | ||
| 59 | + ok := handler.NewUDPConnection(gc, src, dst) | ||
| 60 | + | ||
| 61 | + if !ok { | ||
| 62 | + gc.gudp.Close() | ||
| 63 | + return | ||
| 64 | + } | ||
| 65 | + const maxUDPReqSize = 1600 // FIXME: MTU | ||
| 66 | + const readDeadline = 30 * time.Second // FIXME: Udp.Timeout | ||
| 67 | + q := make([]byte, maxUDPReqSize) | ||
| 68 | + for { | ||
| 69 | + gc.gudp.SetReadDeadline(time.Now().Add(readDeadline)) | ||
| 70 | + if n, addr, err := gc.gudp.ReadFrom(q); err == nil { | ||
| 71 | + ipstr, portstr, _ := net.SplitHostPort(addr.String()) | ||
| 72 | + port, _ := strconv.Atoi(portstr) | ||
| 73 | + udpaddr := &net.UDPAddr{ | ||
| 74 | + IP: net.ParseIP(ipstr), | ||
| 75 | + Port: port, | ||
| 76 | + } | ||
| 77 | + handler.HandleData(gc, q[:n], udpaddr) | ||
| 78 | + } else { | ||
| 79 | + break | ||
| 80 | + } | ||
| 81 | + } | ||
| 82 | + }() | ||
| 83 | + }) | ||
| 84 | + s.SetTransportProtocolHandler(udp.ProtocolNumber, forwarder.HandlePacket) | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + func (g *GUDPConn) LocalAddr() *net.UDPAddr { | ||
| 88 | + return g.gudp.LocalAddr().(*net.UDPAddr) | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + // ReceiveTo will be called when data arrives from TUN, and the received | ||
| 92 | + // data should be sent to addr. | ||
| 93 | + func (g *GUDPConn) ReceiveTo(_ []byte, _ *net.UDPAddr) error { | ||
| 94 | + return nil | ||
| 95 | + // no-op; forwarder.HandlePacket takes care of this | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + // WriteFrom writes data to TUN, addr will be set as source address of | ||
| 99 | + // UDP packets that output to TUN. | ||
| 100 | + func (g *GUDPConn) WriteFrom(data []byte, addr *net.UDPAddr) (int, error) { | ||
| 101 | + // nb: write-deadlines set by intra.udp | ||
| 102 | + return g.gudp.WriteTo(data, addr) | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + // Close closes the connection. | ||
| 106 | + func (g *GUDPConn) Close() error { | ||
| 107 | + return g.gudp.Close() | ||
| 108 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -238,7 +238,7 @@ func (h *tcpHandler) onConn(localConn net.Conn, target *net.TCPAddr) (netid stri | |||
| 238 | 238 | return | |
| 239 | 239 | } | |
| 240 | 240 | ||
| 241 | - func (h *tcpHandler) NewConnection(conn netstack.GTCPConn, src, dst net.TCPAddr) { | ||
| 241 | + func (h *tcpHandler) NewTCPConnection(conn netstack.GTCPConn, src, dst net.TCPAddr) { | ||
| 242 | 242 | /*gconn := GTCPConn{C: conn} | |
| 243 | 243 | newConn:= gconn.(net.Conn)*/ | |
| 244 | 244 | if err := h.Handle(conn, &dst); err != nil { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -125,8 +125,17 @@ func NewGTunnel(fakedns string, dohdns doh.Transport, fd int, mtu uint32, dialer | |||
| 125 | 125 | ||
| 126 | 126 | tunmode := settings.DefaultTunMode() | |
| 127 | 127 | ||
| 128 | + // RFC 4787 REQ-5 requires a timeout no shorter than 5 minutes. | ||
| 129 | + udptimeout, _ := time.ParseDuration("5m") | ||
| 130 | + | ||
| 131 | + udpfakedns, err := net.ResolveUDPAddr("udp", fakedns) | ||
| 132 | + if err != nil { | ||
| 133 | + return nil, err | ||
| 134 | + } | ||
| 135 | + | ||
| 128 | 136 | tcph := NewTCPHandler(fakednsaddr, dialer, flow, tunmode, listener) | |
| 129 | - t, err := tunnel.NewGTunnel(fd, mtu, tcph) | ||
| 137 | + udph := NewUDPHandler(*udpfakedns, udptimeout, flow, tunmode, config, listener) | ||
| 138 | + t, err := tunnel.NewGTunnel(fd, mtu, tcph, udph) | ||
| 130 | 139 | ||
| 131 | 140 | if err != nil { | |
| 132 | 141 | return nil, err | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -44,6 +44,8 @@ import ( | |||
| 44 | 44 | "github.com/celzero/firestack/intra/doh" | |
| 45 | 45 | "github.com/celzero/firestack/intra/protect" | |
| 46 | 46 | "github.com/celzero/firestack/intra/settings" | |
| 47 | + | ||
| 48 | + "github.com/celzero/firestack/intra/netstack" | ||
| 47 | 49 | ) | |
| 48 | 50 | ||
| 49 | 51 | // UDPSocketSummary describes a non-DNS UDP association, reported when it is discarded. | |
@@ -73,6 +75,8 @@ func makeTracker(conn interface{}) *tracker { | |||
| 73 | 75 | // UDPHandler adds DOH support to the base UDPConnHandler interface. | |
| 74 | 76 | type UDPHandler interface { | |
| 75 | 77 | core.UDPConnHandler | |
| 78 | + netstack.GUDPConnHandler | ||
| 79 | + | ||
| 76 | 80 | SetDNS(dns doh.Transport) | |
| 77 | 81 | onConn(localudp core.UDPConn, target *net.UDPAddr) string | |
| 78 | 82 | SetDNSCryptProxy(*dnscrypt.Proxy) | |
@@ -97,7 +101,7 @@ type udpHandler struct { | |||
| 97 | 101 | proxies map[string]*proxy.Dialer | |
| 98 | 102 | } | |
| 99 | 103 | ||
| 100 | - // NewUDPHandler makes a UDP handler with Intra-style DNS redirection: | ||
| 104 | + // NewUDPHandler makes a UDP handler with Intra-style DNS redirection:udpHandler | ||
| 101 | 105 | // All packets are routed directly to their destination, except packets whose | |
| 102 | 106 | // destination is `fakedns`. Those packets are redirected to DOH. | |
| 103 | 107 | // `timeout` controls the effective NAT mapping lifetime. | |
@@ -176,8 +180,10 @@ func (h *udpHandler) onConn(localudp core.UDPConn, target *net.UDPAddr) (netid s | |||
| 176 | 180 | if h.tunMode.BlockMode == settings.BlockModeNone { | |
| 177 | 181 | return protect.NetIdActive | |
| 178 | 182 | } | |
| 183 | + // localudp is either core.UDPConn or gonet.UDPConn wrapped in GUDPConn | ||
| 184 | + uconn := localudp.LocalAddr() | ||
| 179 | 185 | // Next-up If: BlockModeFilter or BlockModeFilterProc | |
| 180 | - return h.onNewConn(localudp.LocalAddr(), target) | ||
| 186 | + return h.onNewConn(uconn, target) | ||
| 181 | 187 | } | |
| 182 | 188 | ||
| 183 | 189 | func (h *udpHandler) onNewConn(source *net.UDPAddr, target *net.UDPAddr) (netid string) { | |
@@ -199,6 +205,15 @@ func (h *udpHandler) onNewConn(source *net.UDPAddr, target *net.UDPAddr) (netid | |||
| 199 | 205 | return | |
| 200 | 206 | } | |
| 201 | 207 | ||
| 208 | + func (h *udpHandler) NewUDPConnection(conn *netstack.GUDPConn, _, dst *net.UDPAddr) bool { | ||
| 209 | + /*gconn := GTCPConn{C: conn} | ||
| 210 | + newConn:= gconn.(net.Conn)*/ | ||
| 211 | + if err := h.Connect(conn, dst); err != nil { | ||
| 212 | + return false | ||
| 213 | + } | ||
| 214 | + return true | ||
| 215 | + } | ||
| 216 | + | ||
| 202 | 217 | // Connect connects the proxy server. Note that target can be nil. | |
| 203 | 218 | func (h *udpHandler) Connect(conn core.UDPConn, target *net.UDPAddr) error { | |
| 204 | 219 | netid := h.onConn(conn, target) | |
@@ -361,6 +376,10 @@ func (h *udpHandler) dnsOverride(nat *tracker, conn core.UDPConn, addr *net.UDPA | |||
| 361 | 376 | return false | |
| 362 | 377 | } | |
| 363 | 378 | ||
| 379 | + func (h *udpHandler) HandleData(conn *netstack.GUDPConn, data []byte, addr *net.UDPAddr) error { | ||
| 380 | + return h.ReceiveTo(conn, data, addr) | ||
| 381 | + } | ||
| 382 | + | ||
| 364 | 383 | // ReceiveTo is called when data arrives from conn (tun). | |
| 365 | 384 | func (h *udpHandler) ReceiveTo(conn core.UDPConn, data []byte, addr *net.UDPAddr) (err error) { | |
| 366 | 385 | h.RLock() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -87,12 +87,13 @@ func (t *tunnel) Write(data []byte) (int, error) { | |||
| 87 | 87 | return t.lwipStack.Write(data) | |
| 88 | 88 | } | |
| 89 | 89 | ||
| 90 | - func NewGTunnel(fd int, mtu uint32, tcphdl netstack.GTCPConnHandler) (Tunnel, error) { | ||
| 90 | + func NewGTunnel(fd int, mtu uint32, tcph netstack.GTCPConnHandler, udph netstack.GUDPConnHandler) (Tunnel, error) { | ||
| 91 | 91 | endpoint, err := netstack.NewEndpoint(fd, mtu) | |
| 92 | 92 | if err != nil { | |
| 93 | 93 | return nil, err | |
| 94 | 94 | } | |
| 95 | - stack, err := netstack.NewStack(tcphdl, endpoint) | ||
| 95 | + ghdl := netstack.NewGConnHandler(tcph, udph) | ||
| 96 | + stack, err := netstack.NewStack(ghdl, endpoint) | ||
| 96 | 97 | if err != nil { | |
| 97 | 98 | return nil, err | |
| 98 | 99 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments