├── .idea ├── .gitignore ├── go-tun2socks.iml ├── misc.xml ├── modules.xml └── vcs.xml ├── LICENSE ├── README.md ├── core └── comm.go ├── dns └── dns.go ├── go.mod ├── go.sum ├── main.go ├── socks └── socks.go ├── tun ├── dev.go ├── nowin.go ├── wasm.go ├── win.go └── wintun │ ├── amd64 │ └── wintun.dll │ ├── arm │ └── wintun.dll │ ├── arm64 │ └── wintun.dll │ └── x86 │ └── wintun.dll └── tun2socks └── tun2socks.go /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/go-tun2socks.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 dosgo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tun2socks 2 | 3 | 4 | A tun2socks implementation written in Go. 5 | 6 | 7 | 8 | # use 9 | 10 | var tunDevice="tun0"; 11 | 12 | var tunAddr="10.0.0.2"; 13 | 14 | var tunMask="255.255.255.0"; 15 | 16 | var tunGw="10.0.0.1"; 17 | 18 | var mtu=1500; 19 | 20 | var socksAddr="127.0.0.1:1080"; 21 | 22 | var tunDns="127.0.0.1:53"; 23 | 24 | tun2socks.StartTunDevice(tunDevice,tunAddr, tunMask, tunGw, mtu,socksAddr,tunDns); 25 | 26 | # thank 27 | github.com/google/netstack 28 | 29 | 30 | github.com/miekg/dns 31 | -------------------------------------------------------------------------------- /core/comm.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "log" 7 | 8 | "net" 9 | "time" 10 | 11 | "gvisor.dev/gvisor/pkg/tcpip" 12 | "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet" 13 | "gvisor.dev/gvisor/pkg/tcpip/header" 14 | "gvisor.dev/gvisor/pkg/tcpip/link/channel" 15 | "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" 16 | "gvisor.dev/gvisor/pkg/tcpip/network/ipv6" 17 | "gvisor.dev/gvisor/pkg/tcpip/stack" 18 | "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" 19 | "gvisor.dev/gvisor/pkg/tcpip/transport/udp" 20 | "gvisor.dev/gvisor/pkg/waiter" 21 | ) 22 | 23 | type CommIPConn interface { 24 | SetDeadline(t time.Time) error 25 | SetReadDeadline(t time.Time) error 26 | SetWriteDeadline(t time.Time) error 27 | LocalAddr() net.Addr 28 | RemoteAddr() net.Addr 29 | } 30 | 31 | type CommTCPConn interface { 32 | CommIPConn 33 | io.ReadWriteCloser 34 | } 35 | type CommUDPConn interface { 36 | CommIPConn 37 | io.ReadWriteCloser 38 | } 39 | 40 | type CommEndpoint interface { 41 | tcpip.Endpoint 42 | } 43 | 44 | type ForwarderCall func(conn CommTCPConn) error 45 | type UdpForwarderCall func(conn CommUDPConn, ep CommEndpoint) error 46 | 47 | func NewDefaultStack(mtu int, tcpCallback ForwarderCall, udpCallback UdpForwarderCall) (*stack.Stack, *channel.Endpoint, error) { 48 | 49 | // Generate unique NIC id. 50 | 51 | _netStack := stack.New(stack.Options{ 52 | NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol}, 53 | TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol}, 54 | }) 55 | 56 | macAddr, _ := net.ParseMAC("de:ad:be:ee:ee:ef") 57 | 58 | var nicid tcpip.NICID = 1 59 | var linkID stack.LinkEndpoint 60 | var channelLinkID = channel.New(1024, uint32(mtu), tcpip.LinkAddress(macAddr)) 61 | linkID = channelLinkID 62 | if err := _netStack.CreateNIC(nicid, linkID); err != nil { 63 | return _netStack, nil, errors.New(err.String()) 64 | } 65 | _netStack.CreateNICWithOptions(nicid, linkID, 66 | stack.NICOptions{ 67 | Disabled: false, 68 | QDisc: nil, 69 | }) 70 | 71 | _netStack.SetPromiscuousMode(nicid, true) 72 | _netStack.SetSpoofing(nicid, true) 73 | 74 | _netStack.SetRouteTable([]tcpip.Route{ 75 | { 76 | Destination: header.IPv4EmptySubnet, 77 | NIC: nicid, 78 | }, 79 | { 80 | Destination: header.IPv6EmptySubnet, 81 | NIC: nicid, 82 | }, 83 | }) 84 | 85 | tcpForwarder := tcp.NewForwarder(_netStack, 30000, 10, func(r *tcp.ForwarderRequest) { 86 | var wq waiter.Queue 87 | ep, err := r.CreateEndpoint(&wq) 88 | if err != nil { 89 | log.Printf("CreateEndpoint" + err.String() + "\r\n") 90 | r.Complete(true) 91 | return 92 | } 93 | r.Complete(false) 94 | setSocketOptions(_netStack, ep) 95 | conn := gonet.NewTCPConn(&wq, ep) 96 | tcpCallback(conn) 97 | }) 98 | _netStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tcpForwarder.HandlePacket) 99 | 100 | udpForwarder := udp.NewForwarder(_netStack, func(r *udp.ForwarderRequest) { 101 | var wq waiter.Queue 102 | ep, err := r.CreateEndpoint(&wq) 103 | if err != nil { 104 | log.Printf("r.CreateEndpoint() = %v", err) 105 | return 106 | } 107 | go udpCallback(gonet.NewUDPConn(&wq, ep), ep) 108 | }) 109 | _netStack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket) 110 | 111 | return _netStack, channelLinkID, nil 112 | } 113 | 114 | func setSocketOptions(s *stack.Stack, ep tcpip.Endpoint) tcpip.Error { 115 | { /* TCP keepalive options */ 116 | ep.SocketOptions().SetKeepAlive(true) 117 | 118 | idle := tcpip.KeepaliveIdleOption(60 * time.Second) 119 | if err := ep.SetSockOpt(&idle); err != nil { 120 | return err 121 | } 122 | 123 | interval := tcpip.KeepaliveIntervalOption(30 * time.Second) 124 | if err := ep.SetSockOpt(&interval); err != nil { 125 | return err 126 | } 127 | 128 | if err := ep.SetSockOptInt(tcpip.KeepaliveCountOption, 9); err != nil { 129 | return err 130 | } 131 | } 132 | { /* TCP recv/send buffer size */ 133 | var ss tcpip.TCPSendBufferSizeRangeOption 134 | if err := s.TransportProtocolOption(header.TCPProtocolNumber, &ss); err == nil { 135 | ep.SocketOptions().SetSendBufferSize(int64(ss.Default), false) 136 | } 137 | 138 | var rs tcpip.TCPReceiveBufferSizeRangeOption 139 | if err := s.TransportProtocolOption(header.TCPProtocolNumber, &rs); err == nil { 140 | ep.SocketOptions().SetReceiveBufferSize(int64(rs.Default), false) 141 | } 142 | } 143 | return nil 144 | } 145 | -------------------------------------------------------------------------------- /dns/dns.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "fmt" 5 | "github.com/miekg/dns" 6 | "net" 7 | "github.com/sensepost/godoh/dnsclient" 8 | "time" 9 | ) 10 | 11 | var dohC *dnsclient.CloudflareDNS 12 | 13 | func StartDns(dnsPort string) error { 14 | 15 | 16 | dohC= dnsclient.NewCloudFlareDNS() 17 | 18 | udpServer := &dns.Server{ 19 | Net: "udp", 20 | Addr: ":"+dnsPort, 21 | Handler: dns.HandlerFunc(serveDNS), 22 | UDPSize: 4096, 23 | ReadTimeout: time.Duration(10) * time.Second, 24 | WriteTimeout: time.Duration(10) * time.Second, 25 | } 26 | tcpServer:= &dns.Server{ 27 | Net: "tcp", 28 | Addr: ":"+dnsPort, 29 | Handler: dns.HandlerFunc(serveDNS), 30 | UDPSize: 4096, 31 | ReadTimeout: time.Duration(10) * time.Second, 32 | WriteTimeout: time.Duration(10) * time.Second, 33 | } 34 | go udpServer.ListenAndServe(); 35 | tcpServer.ListenAndServe(); 36 | return nil; 37 | } 38 | 39 | 40 | func isIPv4Query(q dns.Question) bool { 41 | if q.Qclass == dns.ClassINET && q.Qtype == dns.TypeA { 42 | return true 43 | } 44 | return false 45 | } 46 | 47 | 48 | func resolve(r *dns.Msg) (*dns.Msg, error) { 49 | fmt.Printf("dns ipv6\r\n") 50 | m := &dns.Msg{} 51 | m.SetReply(r) 52 | m.Authoritative = false 53 | domain := r.Question[0].Name 54 | m.Answer = append(r.Answer, &dns.AAAA{ 55 | Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 60}, 56 | AAAA: net.ParseIP("fd3e:4f5a:5b81::1"), 57 | }) 58 | return m, nil 59 | } 60 | 61 | 62 | func doIPv4Query(r *dns.Msg) (*dns.Msg, error) { 63 | m := &dns.Msg{} 64 | m.SetReply(r) 65 | m.Authoritative = false 66 | domain := r.Question[0].Name 67 | var ip string; 68 | DnsRes:=dohC.Lookup(domain,dns.TypeA) 69 | ip=DnsRes.Data; 70 | //use dot dot 71 | m.Answer = append(r.Answer, &dns.A{ 72 | Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60}, 73 | A: net.ParseIP(ip), 74 | }) 75 | // final 76 | return m, nil 77 | } 78 | 79 | 80 | 81 | func serveDNS(w dns.ResponseWriter, r *dns.Msg) { 82 | isIPv4 := isIPv4Query(r.Question[0]) 83 | var msg *dns.Msg 84 | var err error 85 | if isIPv4 { 86 | msg, err = doIPv4Query(r) 87 | } else { 88 | msg, err = resolve(r) 89 | } 90 | if err != nil { 91 | dns.HandleFailed(w, r) 92 | } else { 93 | w.WriteMsg(msg) 94 | } 95 | } 96 | 97 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/dosgo/go-tun2socks 2 | 3 | go 1.22.0 4 | 5 | toolchain go1.22.2 6 | 7 | require ( 8 | github.com/miekg/dns v1.1.59 9 | github.com/sensepost/godoh v0.0.0-20231219072135-f1edcfc473f4 10 | github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 11 | golang.org/x/crypto v0.24.0 12 | golang.org/x/sys v0.21.0 13 | golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 14 | golang.zx2c4.com/wireguard/windows v0.5.3 15 | gvisor.dev/gvisor v0.0.0-20240521174809-5eedbf551134 16 | ) 17 | 18 | require ( 19 | github.com/google/btree v1.1.2 // indirect 20 | golang.org/x/mod v0.17.0 // indirect 21 | golang.org/x/net v0.25.0 // indirect 22 | golang.org/x/sync v0.7.0 // indirect 23 | golang.org/x/text v0.16.0 // indirect 24 | golang.org/x/time v0.5.0 // indirect 25 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect 26 | golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect 27 | ) 28 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 2 | github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 3 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 4 | github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= 5 | github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 6 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 7 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 8 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 9 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 10 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 11 | github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= 12 | github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= 13 | github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= 14 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 15 | github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= 16 | github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= 17 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 18 | github.com/sensepost/godoh v0.0.0-20231219072135-f1edcfc473f4 h1:s+NZn/q/E3IQJCfGcnkN6cqFb5a9AcVTtRw5WaXDcPE= 19 | github.com/sensepost/godoh v0.0.0-20231219072135-f1edcfc473f4/go.mod h1:P2DIDZIYj/qfbB2e491i9fdDpijrEXb2sQfKVanaqCU= 20 | github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8= 21 | github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= 22 | github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= 23 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 24 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 25 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 26 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 27 | golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= 28 | golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= 29 | golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= 30 | golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= 31 | golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= 32 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 33 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 34 | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 35 | golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 36 | golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= 37 | golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 38 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 39 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 40 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 41 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 42 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 43 | golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= 44 | golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= 45 | golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= 46 | golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= 47 | golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= 48 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 49 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 50 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 51 | golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= 52 | golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= 53 | golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 54 | golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= 55 | golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 56 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 57 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 58 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 59 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 60 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 61 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 62 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 63 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 64 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 65 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 66 | golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 67 | golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 68 | golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= 69 | golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 70 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 71 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 72 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 73 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 74 | golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= 75 | golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= 76 | golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= 77 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 78 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 79 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 80 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 81 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 82 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 83 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 84 | golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= 85 | golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 86 | golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= 87 | golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 88 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 89 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 90 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 91 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 92 | golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= 93 | golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= 94 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= 95 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 96 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 97 | golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= 98 | golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= 99 | golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4= 100 | golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA= 101 | golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE= 102 | golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI= 103 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 104 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 105 | gvisor.dev/gvisor v0.0.0-20240521174809-5eedbf551134 h1:1z4zM83z6dioBoh05I26Rla37eEUW9Rii0VDaobzfzM= 106 | gvisor.dev/gvisor v0.0.0-20240521174809-5eedbf551134/go.mod h1:sxc3Uvk/vHcd3tj7/DHVBoR5wvWT/MmRq2pj7HRJnwU= 107 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/dosgo/go-tun2socks/dns" 5 | "github.com/dosgo/go-tun2socks/tun2socks" 6 | ) 7 | 8 | func main() { 9 | var tunDns = "127.0.0.1:53" 10 | var socksAddr = "127.0.0.1:1080" 11 | 12 | //start local dns server (doh) 13 | dns.StartDns(tunDns) 14 | 15 | tun2socks.StartTunDevice("tun0", "10.0.0.2", "255.255.255.0", "10.0.0.1", 1500, socksAddr, tunDns) 16 | } 17 | -------------------------------------------------------------------------------- /socks/socks.go: -------------------------------------------------------------------------------- 1 | package socks 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "io" 7 | "log" 8 | "net" 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | /*to socks5*/ 14 | func SocksCmd(socksConn net.Conn, cmd uint8, host string) error { 15 | //socks5 auth 16 | socksConn.Write([]byte{0x05, 0x01, 0x00}) 17 | authBack := make([]byte, 2) 18 | _, err := io.ReadFull(socksConn, authBack) 19 | if err != nil { 20 | log.Println(err) 21 | return err 22 | } 23 | //connect head 24 | hosts := strings.Split(host, ":") 25 | rAddr := net.ParseIP(hosts[0]) 26 | _port, _ := strconv.Atoi(hosts[1]) 27 | msg := []byte{0x05, cmd, 0x00, 0x01} 28 | buffer := bytes.NewBuffer(msg) 29 | //ip 30 | binary.Write(buffer, binary.BigEndian, rAddr.To4()) 31 | //port 32 | binary.Write(buffer, binary.BigEndian, uint16(_port)) 33 | socksConn.Write(buffer.Bytes()) 34 | conectBack := make([]byte, 10) 35 | _, err = io.ReadFull(socksConn, conectBack) 36 | if err != nil { 37 | log.Println(err) 38 | return err 39 | } 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /tun/dev.go: -------------------------------------------------------------------------------- 1 | package tun 2 | 3 | import "golang.zx2c4.com/wireguard/tun" 4 | 5 | type DevReadWriteCloser struct { 6 | tunDev *tun.NativeTun 7 | } 8 | 9 | func (conn DevReadWriteCloser) Read(buf []byte) (int, error) { 10 | data := [][]byte{buf} 11 | dataLen := []int{0} 12 | _, err := conn.tunDev.Read(data, dataLen, 0) 13 | return dataLen[0], err 14 | } 15 | 16 | func (conn DevReadWriteCloser) Write(buf []byte) (int, error) { 17 | data := [][]byte{buf} 18 | return conn.tunDev.Write(data, 0) 19 | } 20 | 21 | func (conn DevReadWriteCloser) Close() error { 22 | if conn.tunDev == nil { 23 | return nil 24 | } 25 | return conn.tunDev.Close() 26 | } 27 | -------------------------------------------------------------------------------- /tun/nowin.go: -------------------------------------------------------------------------------- 1 | //go:build !windows && !wasm 2 | // +build !windows,!wasm 3 | 4 | package tun 5 | 6 | import ( 7 | "fmt" 8 | "net" 9 | "os/exec" 10 | "runtime" 11 | "strconv" 12 | "strings" 13 | 14 | "github.com/songgao/water" 15 | "golang.zx2c4.com/wireguard/tun" 16 | ) 17 | 18 | func GetCidrIpRange(cidr string) (string, string) { 19 | ip := strings.Split(cidr, "/")[0] 20 | ipSegs := strings.Split(ip, ".") 21 | maskLen, _ := strconv.Atoi(strings.Split(cidr, "/")[1]) 22 | seg3MinIp, seg3MaxIp := getIpSeg3Range(ipSegs, maskLen) 23 | seg4MinIp, seg4MaxIp := getIpSeg4Range(ipSegs, maskLen) 24 | ipPrefix := ipSegs[0] + "." + ipSegs[1] + "." 25 | 26 | return ipPrefix + strconv.Itoa(seg3MinIp) + "." + strconv.Itoa(seg4MinIp), 27 | ipPrefix + strconv.Itoa(seg3MaxIp) + "." + strconv.Itoa(seg4MaxIp) 28 | } 29 | 30 | // 得到第四段IP的区间(第一片段.第二片段.第三片段.第四片段) 31 | func getIpSeg4Range(ipSegs []string, maskLen int) (int, int) { 32 | ipSeg, _ := strconv.Atoi(ipSegs[3]) 33 | segMinIp, segMaxIp := getIpSegRange(uint8(ipSeg), uint8(32-maskLen)) 34 | return segMinIp + 1, segMaxIp 35 | } 36 | 37 | // 得到第三段IP的区间(第一片段.第二片段.第三片段.第四片段) 38 | func getIpSeg3Range(ipSegs []string, maskLen int) (int, int) { 39 | if maskLen > 24 { 40 | segIp, _ := strconv.Atoi(ipSegs[2]) 41 | return segIp, segIp 42 | } 43 | ipSeg, _ := strconv.Atoi(ipSegs[2]) 44 | return getIpSegRange(uint8(ipSeg), uint8(24-maskLen)) 45 | } 46 | 47 | // 根据用户输入的基础IP地址和CIDR掩码计算一个IP片段的区间 48 | func getIpSegRange(userSegIp, offset uint8) (int, int) { 49 | var ipSegMax uint8 = 255 50 | netSegIp := ipSegMax << offset 51 | segMinIp := netSegIp & userSegIp 52 | segMaxIp := userSegIp&(255< 0 { 57 | os.WriteFile(dllPath, dllBin, os.ModePerm) 58 | } else { 59 | // 60 | oldBin, err := os.ReadFile(dllPath) 61 | if err != nil { 62 | return 63 | } 64 | oldMd5 := fmt.Sprintf("%x", md5.Sum(oldBin)) 65 | newMd5 := fmt.Sprintf("%x", md5.Sum(dllBin)) 66 | //update 67 | if oldMd5 != newMd5 { 68 | os.WriteFile(dllPath, dllBin, os.ModePerm) 69 | } 70 | } 71 | } 72 | 73 | /*windows use wintun*/ 74 | func RegTunDev(tunDevice string, tunAddr string, tunMask string, tunGW string, tunDNS string) (*DevReadWriteCloser, error) { 75 | if len(tunDevice) == 0 { 76 | tunDevice = "socksTun0" 77 | } 78 | if len(tunAddr) == 0 { 79 | tunAddr = "10.0.0.2" 80 | } 81 | if len(tunMask) == 0 { 82 | tunMask = "255.255.255.0" 83 | } 84 | if len(tunGW) == 0 { 85 | tunGW = "10.0.0.1" 86 | } 87 | if len(tunDNS) == 0 { 88 | tunDNS = "114.114.114.114" 89 | } 90 | tunDev, err := tun.CreateTUN(tunDevice, 1500) 91 | if err != nil { 92 | return nil, err 93 | } 94 | setInterfaceAddress4(tunDev.(*tun.NativeTun), tunAddr, tunMask, tunGW, tunDNS) 95 | return &DevReadWriteCloser{tunDev.(*tun.NativeTun)}, nil 96 | } 97 | func setInterfaceAddress4(tunDev *tun.NativeTun, addr, mask, gateway, tunDNS string) error { 98 | luid := winipcfg.LUID(tunDev.LUID()) 99 | ipnet := net.IPNet{ 100 | IP: net.ParseIP(addr).To4(), 101 | Mask: net.IPMask(net.ParseIP(mask).To4()), 102 | } 103 | addresses := append([]netip.Prefix{}, netip.MustParsePrefix(ipnet.String())) 104 | err := luid.SetIPAddressesForFamily(windows.AF_INET, addresses) 105 | if errors.Is(err, windows.ERROR_OBJECT_ALREADY_EXISTS) { 106 | cleanupAddressesOnDisconnectedInterfaces(windows.AF_INET, addresses) 107 | err = luid.SetIPAddressesForFamily(windows.AF_INET, addresses) 108 | } 109 | if err != nil { 110 | return err 111 | } 112 | 113 | err = luid.SetDNS(windows.AF_INET, []netip.Addr{netip.MustParseAddr(tunDNS)}, []string{}) 114 | return err 115 | } 116 | 117 | // setInterfaceAddress6 is ... 118 | func setInterfaceAddress6(tunDev *tun.NativeTun, addr, mask, gateway, tunDNS string) error { 119 | luid := winipcfg.LUID(tunDev.LUID()) 120 | 121 | ipnet := net.IPNet{ 122 | IP: net.ParseIP(addr).To16(), 123 | Mask: net.IPMask(net.ParseIP(mask).To16()), 124 | } 125 | addresses := append([]netip.Prefix{}, netip.MustParsePrefix(ipnet.String())) 126 | 127 | err := luid.SetIPAddressesForFamily(windows.AF_INET6, addresses) 128 | if errors.Is(err, windows.ERROR_OBJECT_ALREADY_EXISTS) { 129 | cleanupAddressesOnDisconnectedInterfaces(windows.AF_INET6, addresses) 130 | err = luid.SetIPAddressesForFamily(windows.AF_INET6, addresses) 131 | } 132 | if err != nil { 133 | return err 134 | } 135 | 136 | err = luid.SetDNS(windows.AF_INET6, []netip.Addr{netip.MustParseAddr(tunDNS)}, []string{}) 137 | return err 138 | } 139 | 140 | func determineGUID(name string) *windows.GUID { 141 | b := make([]byte, unsafe.Sizeof(windows.GUID{})) 142 | if _, err := io.ReadFull(hkdf.New(md5.New, []byte(name), nil, nil), b); err != nil { 143 | return nil 144 | } 145 | return (*windows.GUID)(unsafe.Pointer(&b[0])) 146 | } 147 | 148 | //go:linkname cleanupAddressesOnDisconnectedInterfaces golang.zx2c4.com/wireguard/windows/tunnel.cleanupAddressesOnDisconnectedInterfaces 149 | func cleanupAddressesOnDisconnectedInterfaces(family winipcfg.AddressFamily, addresses []netip.Prefix) 150 | -------------------------------------------------------------------------------- /tun/wintun/amd64/wintun.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dosgo/go-tun2socks/026fc4c61cfb8d7c67d9a0867c83fd7ef2c46352/tun/wintun/amd64/wintun.dll -------------------------------------------------------------------------------- /tun/wintun/arm/wintun.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dosgo/go-tun2socks/026fc4c61cfb8d7c67d9a0867c83fd7ef2c46352/tun/wintun/arm/wintun.dll -------------------------------------------------------------------------------- /tun/wintun/arm64/wintun.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dosgo/go-tun2socks/026fc4c61cfb8d7c67d9a0867c83fd7ef2c46352/tun/wintun/arm64/wintun.dll -------------------------------------------------------------------------------- /tun/wintun/x86/wintun.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dosgo/go-tun2socks/026fc4c61cfb8d7c67d9a0867c83fd7ef2c46352/tun/wintun/x86/wintun.dll -------------------------------------------------------------------------------- /tun2socks/tun2socks.go: -------------------------------------------------------------------------------- 1 | package tun2socks 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net" 9 | "strings" 10 | 11 | "github.com/dosgo/go-tun2socks/core" 12 | "github.com/dosgo/go-tun2socks/socks" 13 | "github.com/dosgo/go-tun2socks/tun" 14 | "gvisor.dev/gvisor/pkg/buffer" 15 | "gvisor.dev/gvisor/pkg/tcpip/header" 16 | "gvisor.dev/gvisor/pkg/tcpip/stack" 17 | ) 18 | 19 | var wrapnet uint32 20 | var mask uint32 21 | var relayip net.IP 22 | var port uint16 23 | var sock5Addr string 24 | var tunDNS string 25 | 26 | func StartTunDevice(tunDevice string, tunAddr string, tunMask string, tunGW string, mtu int, _sock5Addr string, _tunDNS string) { 27 | dev, err := tun.RegTunDev(tunDevice, tunAddr, tunMask, tunGW, tunDNS) 28 | if err != nil { 29 | fmt.Println("start tun err:", err) 30 | return 31 | } 32 | sock5Addr = _sock5Addr 33 | tunDNS = _tunDNS 34 | ForwardTransportFromIo(dev, mtu, rawTcpForwarder, rawUdpForwarder) 35 | } 36 | 37 | func rawTcpForwarder(conn core.CommTCPConn) error { 38 | defer conn.Close() 39 | socksConn, err1 := net.Dial("tcp", sock5Addr) 40 | if err1 != nil { 41 | log.Println(err1) 42 | return nil 43 | } 44 | defer socksConn.Close() 45 | if socks.SocksCmd(socksConn, 1, conn.LocalAddr().String()) == nil { 46 | go io.Copy(conn, socksConn) 47 | io.Copy(socksConn, conn) 48 | } 49 | return nil 50 | } 51 | 52 | func rawUdpForwarder(conn core.CommUDPConn, ep core.CommEndpoint) error { 53 | defer conn.Close() 54 | //dns port 55 | if strings.HasSuffix(conn.LocalAddr().String(), ":53") { 56 | dnsReq(conn, "udp", tunDNS) 57 | } 58 | return nil 59 | } 60 | 61 | func ForwardTransportFromIo(dev io.ReadWriteCloser, mtu int, tcpCallback core.ForwarderCall, udpCallback core.UdpForwarderCall) error { 62 | _, channelLinkID, err := core.NewDefaultStack(mtu, tcpCallback, udpCallback) 63 | if err != nil { 64 | log.Printf("err:%v", err) 65 | return err 66 | } 67 | 68 | ctx, cancel := context.WithCancel(context.Background()) 69 | defer cancel() 70 | 71 | // write tun 72 | go func(_ctx context.Context) { 73 | for { 74 | info := channelLinkID.ReadContext(_ctx) 75 | if info==nil { 76 | log.Printf("channelLinkID exit \r\n") 77 | break 78 | } 79 | info.ToView().WriteTo(dev) 80 | info.DecRef() 81 | } 82 | }(ctx) 83 | 84 | // read tun data 85 | var buf = make([]byte, mtu+80) 86 | var recvLen=0; 87 | for { 88 | recvLen, err = dev.Read(buf[:]) 89 | if err != nil { 90 | log.Printf("err:%v", err) 91 | break 92 | } 93 | 94 | pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 95 | Payload: buffer.MakeWithData(buf[:recvLen]), 96 | }) 97 | 98 | switch header.IPVersion(buf) { 99 | case header.IPv4Version: 100 | channelLinkID.InjectInbound(header.IPv4ProtocolNumber, pkt) 101 | case header.IPv6Version: 102 | channelLinkID.InjectInbound(header.IPv6ProtocolNumber, pkt) 103 | } 104 | pkt.DecRef() 105 | } 106 | return nil 107 | } 108 | 109 | /*to dns*/ 110 | func dnsReq(conn core.CommUDPConn, action string, dnsAddr string) error { 111 | if action == "tcp" { 112 | dnsConn, err := net.Dial(action, dnsAddr) 113 | if err != nil { 114 | fmt.Println(err.Error()) 115 | return err 116 | } 117 | defer dnsConn.Close() 118 | go io.Copy(conn, dnsConn) 119 | io.Copy(dnsConn, conn) 120 | fmt.Printf("dnsReq Tcp\r\n") 121 | return nil 122 | } else { 123 | buf := make([]byte, 4096) 124 | var n = 0 125 | var err error 126 | n, err = conn.Read(buf) 127 | if err != nil { 128 | fmt.Printf("c.Read() = %v", err) 129 | return err 130 | } 131 | dnsConn, err := net.Dial("udp", dnsAddr) 132 | if err != nil { 133 | fmt.Println(err.Error()) 134 | return err 135 | } 136 | defer dnsConn.Close() 137 | _, err = dnsConn.Write(buf[:n]) 138 | if err != nil { 139 | fmt.Println(err.Error()) 140 | return err 141 | } 142 | n, err = dnsConn.Read(buf) 143 | if err != nil { 144 | fmt.Println(err.Error()) 145 | return err 146 | } 147 | _, err = conn.Write(buf[:n]) 148 | if err != nil { 149 | fmt.Println(err.Error()) 150 | return err 151 | } 152 | } 153 | return nil 154 | } 155 | --------------------------------------------------------------------------------