├── .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 |
5 |
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 |
--------------------------------------------------------------------------------