Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add dns-hijack for tun mode #45

Merged
merged 16 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions client/rvpn_conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,59 @@ package client
import (
"github.com/mythologyli/zju-connect/log"
"io"
"sync"
)

type RvpnConn struct {
easyConnectClient *EasyConnectClient

sendConn io.WriteCloser
sendLock sync.Mutex
sendErrCount int

recvConn io.ReadCloser
recvLock sync.Mutex
recvErrCount int
}

// always success or panic
// try best to read, if return err!=nil, please panic
func (r *RvpnConn) Read(p []byte) (n int, err error) {
r.recvLock.Lock()
defer r.recvLock.Unlock()
for n, err = r.recvConn.Read(p); err != nil && r.recvErrCount < 5; {

log.Printf("Error occurred while receiving, retrying: %v", err)

// Do handshake again and create a new recvConn
_ = r.recvConn.Close()
r.recvConn, err = r.easyConnectClient.RecvConn()
if err != nil {
// TODO graceful shutdown
panic(err)
return 0, err
}
r.recvErrCount++
if r.recvErrCount >= 5 {
panic("recv retry limit exceeded.")
return 0, err
}
}
return
}

// always success or panic
// try best to write, if return err!=nil, please panic
func (r *RvpnConn) Write(p []byte) (n int, err error) {
r.sendLock.Lock()
defer r.sendLock.Unlock()
for n, err = r.sendConn.Write(p); err != nil && r.sendErrCount < 5; {
log.Printf("Error occurred while sending, retrying: %v", err)

// Do handshake again and create a new sendConn
_ = r.sendConn.Close()
r.sendConn, err = r.easyConnectClient.SendConn()
if err != nil {
// TODO graceful shutdown
panic(err)
return 0, err
}
r.sendErrCount++
if r.sendErrCount >= 5 {
panic("send retry limit exceeded.")
return 0, err
}
}
return
Expand All @@ -76,13 +82,13 @@ func NewRvpnConn(ec *EasyConnectClient) (*RvpnConn, error) {
c.sendConn, err = ec.SendConn()
if err != nil {
log.Printf("Error occurred while creating sendConn: %v", err)
panic(err)
return nil, err
}

c.recvConn, err = ec.RecvConn()
if err != nil {
log.Printf("Error occurred while creating recvConn: %v", err)
panic(err)
return nil, err
}
return c, nil
}
2 changes: 1 addition & 1 deletion config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ disable_keep_alive = false
zju_dns_server = "10.10.0.21"
secondary_dns_server = "114.114.114.114"
dns_server_bind = ""
tun_dns_server = ""
dns_hijack = false
debug_dump = false

# Port forwarding
Expand Down
12 changes: 10 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ require (
github.com/BurntSushi/toml v1.2.1
github.com/beevik/etree v1.2.0
github.com/cloverstd/tcping v0.1.1
github.com/cxz66666/sing-tun v0.0.0-20231028191617-2867d9374292
github.com/miekg/dns v1.1.56
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
github.com/things-go/go-socks5 v0.0.4
golang.org/x/net v0.17.0
golang.org/x/sys v0.13.0
golang.zx2c4.com/wireguard v0.0.0-20231022001213-2e0774f246fb
golang.zx2c4.com/wireguard/windows v0.5.3
Expand All @@ -23,14 +22,23 @@ require (
require (
github.com/andybalholm/brotli v1.0.6 // indirect
github.com/cloudflare/circl v1.3.5 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gaukas/godicttls v0.0.4 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/klauspost/compress v1.17.1 // indirect
github.com/metacubex/gvisor v0.0.0-20231001104248-0f672c3fb8d8 // indirect
github.com/quic-go/quic-go v0.39.1 // indirect
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
github.com/sagernet/sing v0.2.14 // indirect
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.14.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
Expand Down
24 changes: 22 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ github.com/cloudflare/circl v1.3.5 h1:g+wWynZqVALYAlpSQFAa7TscDnUK8mKYtrxMpw6AUK
github.com/cloudflare/circl v1.3.5/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloverstd/tcping v0.1.1 h1:3Yp9nvSDI7Z63zoVQDJzVk1PUczrF9tJoOrKGV30iOk=
github.com/cloverstd/tcping v0.1.1/go.mod h1:NYXTrTDwlwuOKQ0vwksUVUbIr0sxDDsf1J6aFpScCBo=
github.com/cxz66666/sing-tun v0.0.0-20231028191617-2867d9374292 h1:ualmTq9VM4rYWNYgr7/9Pg6SHz1uXWHKmI2Ufd8sEQY=
github.com/cxz66666/sing-tun v0.0.0-20231028191617-2867d9374292/go.mod h1:MBoiGEiPODP6YZko83BH5Nhnp2IqRIclCYNyFdLocWM=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
Expand All @@ -25,6 +31,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g=
github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/metacubex/gvisor v0.0.0-20231001104248-0f672c3fb8d8 h1:npBvaPAT145UY8682AzpUMWpdIxJti/WPLjy7gCiYYs=
github.com/metacubex/gvisor v0.0.0-20231001104248-0f672c3fb8d8/go.mod h1:ZR6Gas7P1GcADCVBc1uOrA0bLQqDDyp70+63fD/BE2c=
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
Expand All @@ -39,12 +47,21 @@ github.com/quic-go/quic-go v0.39.1 h1:d/m3oaN/SD2c+f7/yEjZxe2zEVotXprnrCCJ2y/ZZF
github.com/quic-go/quic-go v0.39.1/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
github.com/refraction-networking/utls v1.5.4 h1:9k6EO2b8TaOGsQ7Pl7p9w6PUhx18/ZCeT0WNTZ7Uw4o=
github.com/refraction-networking/utls v1.5.4/go.mod h1:SPuDbBmgLGp8s+HLNc83FuavwZCFoMmExj+ltUHiHUw=
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.2.14 h1:L3AXDh22nsOOYz2nTRU1JvpRsmzViWKI1B8TsQYG1eY=
github.com/sagernet/sing v0.2.14/go.mod h1:AhNEHu0GXrpqkuzvTwvC8+j2cQUU/dh+zLEmq4C99pg=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/things-go/go-socks5 v0.0.4 h1:jMQjIc+qhD4z9cITOMnBiwo9dDmpGuXmBlkRFrl/qD0=
github.com/things-go/go-socks5 v0.0.4/go.mod h1:sh4K6WHrmHZpjxLTCHyYtXYH8OUuD+yZun41NomR1IQ=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE=
go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA=
Expand All @@ -70,8 +87,11 @@ golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
8 changes: 4 additions & 4 deletions init.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type (
ZJUDNSServer string
SecondaryDNSServer string
DNSServerBind string
TUNDNSServer string
DNSHijack bool
DebugDump bool
PortForwardingList []SinglePortForwarding
CustomDNSList []SingleCustomDNS
Expand Down Expand Up @@ -72,7 +72,7 @@ type (
ZJUDNSServer *string `toml:"zju_dns_server"`
SecondaryDNSServer *string `toml:"secondary_dns_server"`
DNSServerBind *string `toml:"dns_server_bind"`
TUNDNSServer *string `toml:"tun_dns_server"`
DNSHijack *bool `toml:"dns_hijack"`
DebugDump *bool `toml:"debug_dump"`
PortForwarding []SinglePortForwardingTOML `toml:"port_forwarding"`
CustomDNS []SingleCustomDNSTOML `toml:"custom_dns"`
Expand Down Expand Up @@ -127,7 +127,7 @@ func parseTOMLConfig(configFile string, conf *Config) error {
conf.ZJUDNSServer = getTOMLVal(confTOML.ZJUDNSServer, "10.10.0.21")
conf.SecondaryDNSServer = getTOMLVal(confTOML.SecondaryDNSServer, "114.114.114.114")
conf.DNSServerBind = getTOMLVal(confTOML.DNSServerBind, "")
conf.TUNDNSServer = getTOMLVal(confTOML.TUNDNSServer, "")
conf.DNSHijack = getTOMLVal(confTOML.DNSHijack, false)

for _, singlePortForwarding := range confTOML.PortForwarding {
if singlePortForwarding.NetworkType == nil {
Expand Down Expand Up @@ -193,7 +193,7 @@ func init() {
flag.StringVar(&conf.ZJUDNSServer, "zju-dns-server", "10.10.0.21", "ZJU DNS server address")
flag.StringVar(&conf.SecondaryDNSServer, "secondary-dns-server", "114.114.114.114", "Secondary DNS server address. Leave empty to use system default DNS server")
flag.StringVar(&conf.DNSServerBind, "dns-server-bind", "", "The address DNS server listens on (e.g. 127.0.0.1:53)")
flag.StringVar(&conf.TUNDNSServer, "tun-dns-server", "", "DNS Server address for TUN interface (e.g. 127.0.0.1). You should not specify the port")
flag.BoolVar(&conf.DNSHijack, "dns-hijack", false, "Hijack all dns query to ZJU Connect")
flag.StringVar(&conf.TwfID, "twf-id", "", "Login using twfID captured (mostly for debug usage)")
flag.StringVar(&tcpPortForwarding, "tcp-port-forwarding", "", "TCP port forwarding (e.g. 0.0.0.0:9898-10.10.98.98:80,127.0.0.1:9899-10.10.98.98:80)")
flag.StringVar(&udpPortForwarding, "udp-port-forwarding", "", "UDP port forwarding (e.g. 127.0.0.1:53-10.10.0.21:53)")
Expand Down
43 changes: 43 additions & 0 deletions internal/terminal_func/terminal_func.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package terminal_func

import (
"context"
"github.com/mythologyli/zju-connect/log"
)

type TerminalFunc func(ctx context.Context) error
type TerminalItem struct {
f TerminalFunc
name string
}

var terminalFuncList []TerminalItem

var terminalBegin = false

func RegisterTerminalFunc(execName string, fun TerminalFunc) {
terminalFuncList = append(terminalFuncList, TerminalItem{
f: fun,
name: execName,
})
log.Println("Register func on terminal:", execName)
}

func ExecTerminalFunc(ctx context.Context) []error {
var errList []error
terminalBegin = true
for _, item := range terminalFuncList {
log.Println("Exec func on terminal:", item.name)
if err := item.f(ctx); err != nil {
errList = append(errList, err)
log.Println("Exec func on terminal ", item.name, "failed:", err)
} else {
log.Println("Exec func on terminal ", item.name, "success")
}
}
return errList
}

func IsTerminal() bool {
return terminalBegin
}
13 changes: 13 additions & 0 deletions internal/zcdns/local_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package zcdns

import (
"context"

"github.com/miekg/dns"
"net"
)

type LocalServer interface {
HandleDnsMsg(ctx context.Context, msg *dns.Msg) (*dns.Msg, error)
CheckDnsHijack(dstIP net.IP) bool
}
40 changes: 40 additions & 0 deletions internal/zctcpip/icmp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package zctcpip

import (
"encoding/binary"
)

type ICMPType = byte

const (
ICMPTypePingRequest byte = 0x8
ICMPTypePingResponse byte = 0x0
)

type ICMPPacket []byte

func (p ICMPPacket) Type() ICMPType {
return p[0]
}

func (p ICMPPacket) SetType(v ICMPType) {
p[0] = v
}

func (p ICMPPacket) Code() byte {
return p[1]
}

func (p ICMPPacket) Checksum() uint16 {
return binary.BigEndian.Uint16(p[2:])
}

func (p ICMPPacket) SetChecksum(sum [2]byte) {
p[2] = sum[0]
p[3] = sum[1]
}

func (p ICMPPacket) ResetChecksum() {
p.SetChecksum(zeroChecksum)
p.SetChecksum(Checksum(0, p))
}
Loading
Loading