tun: add chain support
This commit is contained in:
parent
61eec87187
commit
42bf481ded
12
forward.go
12
forward.go
@ -187,14 +187,15 @@ func (h *udpDirectForwardHandler) Handle(conn net.Conn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var cc net.Conn
|
|
||||||
if h.options.Chain.IsEmpty() {
|
|
||||||
raddr, err := net.ResolveUDPAddr("udp", node.Addr)
|
raddr, err := net.ResolveUDPAddr("udp", node.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
node.MarkDead()
|
node.MarkDead()
|
||||||
log.Logf("[udp] %s - %s : %s", conn.LocalAddr(), node.Addr, err)
|
log.Logf("[udp] %s - %s : %s", conn.LocalAddr(), node.Addr, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cc net.Conn
|
||||||
|
if h.options.Chain.IsEmpty() {
|
||||||
cc, err = net.DialUDP("udp", nil, raddr)
|
cc, err = net.DialUDP("udp", nil, raddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
node.MarkDead()
|
node.MarkDead()
|
||||||
@ -208,7 +209,8 @@ func (h *udpDirectForwardHandler) Handle(conn net.Conn) {
|
|||||||
log.Logf("[udp] %s - %s : %s", conn.LocalAddr(), node.Addr, err)
|
log.Logf("[udp] %s - %s : %s", conn.LocalAddr(), node.Addr, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cc = &udpTunnelConn{Conn: cc, raddr: node.Addr}
|
|
||||||
|
cc = &udpTunnelConn{Conn: cc, raddr: raddr}
|
||||||
}
|
}
|
||||||
|
|
||||||
defer cc.Close()
|
defer cc.Close()
|
||||||
@ -763,7 +765,7 @@ func (l *tcpRemoteForwardListener) getSession() (s *muxSession, err error) {
|
|||||||
conn.SetDeadline(time.Now().Add(HandshakeTimeout))
|
conn.SetDeadline(time.Now().Add(HandshakeTimeout))
|
||||||
defer conn.SetDeadline(time.Time{})
|
defer conn.SetDeadline(time.Time{})
|
||||||
|
|
||||||
conn, err = socks5Handshake(conn, nil, l.chain.LastNode().User)
|
conn, err = socks5Handshake(conn, userSocks5HandshakeOption(l.chain.LastNode().User))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -798,7 +800,7 @@ func (l *tcpRemoteForwardListener) getSession() (s *muxSession, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *tcpRemoteForwardListener) waitConnectSOCKS5(conn net.Conn) (net.Conn, error) {
|
func (l *tcpRemoteForwardListener) waitConnectSOCKS5(conn net.Conn) (net.Conn, error) {
|
||||||
conn, err := socks5Handshake(conn, nil, l.chain.LastNode().User)
|
conn, err := socks5Handshake(conn, userSocks5HandshakeOption(l.chain.LastNode().User))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
2
gost.go
2
gost.go
@ -20,7 +20,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Version is the gost version.
|
// Version is the gost version.
|
||||||
const Version = "2.9.0"
|
const Version = "2.9.1-dev"
|
||||||
|
|
||||||
// Debug is a flag that enables the debug log.
|
// Debug is a flag that enables the debug log.
|
||||||
var Debug bool
|
var Debug bool
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
name: gost
|
name: gost
|
||||||
type: app
|
type: app
|
||||||
version: '2.9.0'
|
version: '2.9.1'
|
||||||
title: GO Simple Tunnel
|
title: GO Simple Tunnel
|
||||||
summary: A simple security tunnel written in golang
|
summary: A simple security tunnel written in golang
|
||||||
description: |
|
description: |
|
||||||
|
78
socks.go
78
socks.go
@ -213,7 +213,9 @@ func (c *socks5Connector) Connect(conn net.Conn, addr string, options ...Connect
|
|||||||
if user == nil {
|
if user == nil {
|
||||||
user = c.User
|
user = c.User
|
||||||
}
|
}
|
||||||
cc, err := socks5Handshake(conn, opts.Selector, user)
|
cc, err := socks5Handshake(conn,
|
||||||
|
selectorSocks5HandshakeOption(opts.Selector),
|
||||||
|
userSocks5HandshakeOption(user))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -281,7 +283,9 @@ func (c *socks5BindConnector) Connect(conn net.Conn, addr string, options ...Con
|
|||||||
if user == nil {
|
if user == nil {
|
||||||
user = c.User
|
user = c.User
|
||||||
}
|
}
|
||||||
cc, err := socks5Handshake(conn, opts.Selector, user)
|
cc, err := socks5Handshake(conn,
|
||||||
|
selectorSocks5HandshakeOption(opts.Selector),
|
||||||
|
userSocks5HandshakeOption(user))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -431,7 +435,7 @@ func (tr *socks5MuxBindTransporter) initSession(conn net.Conn, addr string, opts
|
|||||||
opts = &HandshakeOptions{}
|
opts = &HandshakeOptions{}
|
||||||
}
|
}
|
||||||
|
|
||||||
cc, err := socks5Handshake(conn, nil, opts.User)
|
cc, err := socks5Handshake(conn, userSocks5HandshakeOption(opts.User))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -515,7 +519,9 @@ func (c *socks5UDPConnector) Connect(conn net.Conn, addr string, options ...Conn
|
|||||||
if user == nil {
|
if user == nil {
|
||||||
user = c.User
|
user = c.User
|
||||||
}
|
}
|
||||||
cc, err := socks5Handshake(conn, opts.Selector, user)
|
cc, err := socks5Handshake(conn,
|
||||||
|
selectorSocks5HandshakeOption(opts.Selector),
|
||||||
|
userSocks5HandshakeOption(user))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -594,7 +600,9 @@ func (c *socks5UDPTunConnector) Connect(conn net.Conn, addr string, options ...C
|
|||||||
if user == nil {
|
if user == nil {
|
||||||
user = c.User
|
user = c.User
|
||||||
}
|
}
|
||||||
cc, err := socks5Handshake(conn, opts.Selector, user)
|
cc, err := socks5Handshake(conn,
|
||||||
|
selectorSocks5HandshakeOption(opts.Selector),
|
||||||
|
userSocks5HandshakeOption(user))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -636,7 +644,7 @@ func (c *socks5UDPTunConnector) Connect(conn net.Conn, addr string, options ...C
|
|||||||
}
|
}
|
||||||
log.Logf("[socks5] udp-tun associate on %s OK", baddr)
|
log.Logf("[socks5] udp-tun associate on %s OK", baddr)
|
||||||
|
|
||||||
return &udpTunnelConn{Conn: conn, raddr: taddr.String()}, nil
|
return &udpTunnelConn{Conn: conn, raddr: taddr}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type socks4Connector struct{}
|
type socks4Connector struct{}
|
||||||
@ -1122,7 +1130,7 @@ func (h *socks5Handler) handleUDPRelay(conn net.Conn, req *gosocks5.Request) {
|
|||||||
}
|
}
|
||||||
defer cc.Close()
|
defer cc.Close()
|
||||||
|
|
||||||
cc, err = socks5Handshake(cc, nil, h.options.Chain.LastNode().User)
|
cc, err = socks5Handshake(cc, userSocks5HandshakeOption(h.options.Chain.LastNode().User))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), socksAddr, err)
|
log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), socksAddr, err)
|
||||||
return
|
return
|
||||||
@ -1386,7 +1394,7 @@ func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
|
|||||||
}
|
}
|
||||||
defer cc.Close()
|
defer cc.Close()
|
||||||
|
|
||||||
cc, err = socks5Handshake(cc, nil, h.options.Chain.LastNode().User)
|
cc, err = socks5Handshake(cc, userSocks5HandshakeOption(h.options.Chain.LastNode().User))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||||
return
|
return
|
||||||
@ -1780,7 +1788,11 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
|
|||||||
conn.SetDeadline(time.Now().Add(HandshakeTimeout))
|
conn.SetDeadline(time.Now().Add(HandshakeTimeout))
|
||||||
defer conn.SetDeadline(time.Time{})
|
defer conn.SetDeadline(time.Time{})
|
||||||
|
|
||||||
cc, err := socks5Handshake(conn, nil, chain.LastNode().User)
|
node := chain.LastNode()
|
||||||
|
cc, err := socks5Handshake(conn,
|
||||||
|
userSocks5HandshakeOption(node.User),
|
||||||
|
noTLSSocks5HandshakeOption(node.GetBool("notls")),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1813,17 +1825,51 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func socks5Handshake(conn net.Conn, selector gosocks5.Selector, user *url.Userinfo) (net.Conn, error) {
|
type socks5HandshakeOptions struct {
|
||||||
|
selector gosocks5.Selector
|
||||||
|
user *url.Userinfo
|
||||||
|
tlsConfig *tls.Config
|
||||||
|
noTLS bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type socks5HandshakeOption func(opts *socks5HandshakeOptions)
|
||||||
|
|
||||||
|
func selectorSocks5HandshakeOption(selector gosocks5.Selector) socks5HandshakeOption {
|
||||||
|
return func(opts *socks5HandshakeOptions) {
|
||||||
|
opts.selector = selector
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func userSocks5HandshakeOption(user *url.Userinfo) socks5HandshakeOption {
|
||||||
|
return func(opts *socks5HandshakeOptions) {
|
||||||
|
opts.user = user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func noTLSSocks5HandshakeOption(noTLS bool) socks5HandshakeOption {
|
||||||
|
return func(opts *socks5HandshakeOptions) {
|
||||||
|
opts.noTLS = noTLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func socks5Handshake(conn net.Conn, opts ...socks5HandshakeOption) (net.Conn, error) {
|
||||||
|
options := socks5HandshakeOptions{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&options)
|
||||||
|
}
|
||||||
|
selector := options.selector
|
||||||
if selector == nil {
|
if selector == nil {
|
||||||
cs := &clientSelector{
|
cs := &clientSelector{
|
||||||
TLSConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
User: user,
|
User: options.user,
|
||||||
}
|
}
|
||||||
cs.AddMethod(
|
cs.AddMethod(
|
||||||
gosocks5.MethodNoAuth,
|
gosocks5.MethodNoAuth,
|
||||||
gosocks5.MethodUserPass,
|
gosocks5.MethodUserPass,
|
||||||
MethodTLS,
|
|
||||||
)
|
)
|
||||||
|
if !options.noTLS {
|
||||||
|
cs.AddMethod(MethodTLS)
|
||||||
|
}
|
||||||
selector = cs
|
selector = cs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1835,7 +1881,7 @@ func socks5Handshake(conn net.Conn, selector gosocks5.Selector, user *url.Userin
|
|||||||
}
|
}
|
||||||
|
|
||||||
type udpTunnelConn struct {
|
type udpTunnelConn struct {
|
||||||
raddr string
|
raddr net.Addr
|
||||||
net.Conn
|
net.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1859,11 +1905,7 @@ func (c *udpTunnelConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpTunnelConn) Write(b []byte) (n int, err error) {
|
func (c *udpTunnelConn) Write(b []byte) (n int, err error) {
|
||||||
addr, err := net.ResolveUDPAddr("udp", c.raddr)
|
dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(len(b)), 0, toSocksAddr(c.raddr)), b)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(len(b)), 0, toSocksAddr(addr)), b)
|
|
||||||
if err = dgram.Write(c.Conn); err != nil {
|
if err = dgram.Write(c.Conn); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
95
tuntap.go
95
tuntap.go
@ -114,12 +114,14 @@ func (l *tunListener) Close() error {
|
|||||||
type tunHandler struct {
|
type tunHandler struct {
|
||||||
options *HandlerOptions
|
options *HandlerOptions
|
||||||
routes sync.Map
|
routes sync.Map
|
||||||
|
chExit chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TunHandler creates a handler for tun tunnel.
|
// TunHandler creates a handler for tun tunnel.
|
||||||
func TunHandler(opts ...HandlerOption) Handler {
|
func TunHandler(opts ...HandlerOption) Handler {
|
||||||
h := &tunHandler{
|
h := &tunHandler{
|
||||||
options: &HandlerOptions{},
|
options: &HandlerOptions{},
|
||||||
|
chExit: make(chan struct{}, 1),
|
||||||
}
|
}
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(h.options)
|
opt(h.options)
|
||||||
@ -141,44 +143,76 @@ func (h *tunHandler) Handle(conn net.Conn) {
|
|||||||
defer os.Exit(0)
|
defer os.Exit(0)
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
laddr, raddr := h.options.Node.Addr, h.options.Node.Remote
|
|
||||||
var pc net.PacketConn
|
|
||||||
var err error
|
var err error
|
||||||
if h.options.TCPMode {
|
var raddr net.Addr
|
||||||
if raddr != "" {
|
if addr := h.options.Node.Remote; addr != "" {
|
||||||
pc, err = tcpraw.Dial("tcp", raddr)
|
raddr, err = net.ResolveUDPAddr("udp", addr)
|
||||||
} else {
|
|
||||||
pc, err = tcpraw.Listen("tcp", laddr)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
addr, _ := net.ResolveUDPAddr("udp", laddr)
|
|
||||||
pc, err = net.ListenUDP("udp", addr)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Logf("[tun] %s: %v", conn.LocalAddr(), err)
|
log.Logf("[tun] %s: remote addr: %v", conn.LocalAddr(), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tempDelay time.Duration
|
||||||
|
for {
|
||||||
|
err := func() error {
|
||||||
|
var err error
|
||||||
|
var pc net.PacketConn
|
||||||
|
if raddr != nil && !h.options.Chain.IsEmpty() {
|
||||||
|
var cc net.Conn
|
||||||
|
cc, err = getSOCKS5UDPTunnel(h.options.Chain, nil)
|
||||||
|
pc = &udpTunnelConn{Conn: cc, raddr: raddr}
|
||||||
|
} else {
|
||||||
|
laddr, _ := net.ResolveUDPAddr("udp", h.options.Node.Addr)
|
||||||
|
pc, err = net.ListenUDP("udp", laddr)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pc, err = h.initTunnelConn(pc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.transportTun(conn, pc, raddr)
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
log.Logf("[tun] %s: %v", conn.LocalAddr(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-h.chExit:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if tempDelay == 0 {
|
||||||
|
tempDelay = 1000 * time.Millisecond
|
||||||
|
} else {
|
||||||
|
tempDelay *= 2
|
||||||
|
}
|
||||||
|
if max := 6 * time.Second; tempDelay > max {
|
||||||
|
tempDelay = max
|
||||||
|
}
|
||||||
|
time.Sleep(tempDelay)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tempDelay = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tunHandler) initTunnelConn(pc net.PacketConn) (net.PacketConn, error) {
|
||||||
if len(h.options.Users) > 0 && h.options.Users[0] != nil {
|
if len(h.options.Users) > 0 && h.options.Users[0] != nil {
|
||||||
passwd, _ := h.options.Users[0].Password()
|
passwd, _ := h.options.Users[0].Password()
|
||||||
cipher, err := core.PickCipher(h.options.Users[0].Username(), nil, passwd)
|
cipher, err := core.PickCipher(h.options.Users[0].Username(), nil, passwd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Logf("[tun] %s - %s cipher: %v", conn.LocalAddr(), pc.LocalAddr(), err)
|
return nil, err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
pc = cipher.PacketConn(pc)
|
pc = cipher.PacketConn(pc)
|
||||||
}
|
}
|
||||||
|
return pc, nil
|
||||||
var ra net.Addr
|
|
||||||
if raddr != "" {
|
|
||||||
ra, err = net.ResolveUDPAddr("udp", raddr)
|
|
||||||
if err != nil {
|
|
||||||
log.Logf("[tun] %s - %s: remote addr: %v", conn.LocalAddr(), pc.LocalAddr(), err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h.transportTun(conn, pc, ra)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.Addr) error {
|
func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.Addr) error {
|
||||||
@ -192,6 +226,10 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
|
|||||||
|
|
||||||
n, err := tun.Read(b)
|
n, err := tun.Read(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
select {
|
||||||
|
case h.chExit <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,6 +361,10 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err := tun.Write(b[:n]); err != nil {
|
if _, err := tun.Write(b[:n]); err != nil {
|
||||||
|
select {
|
||||||
|
case h.chExit <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -339,7 +381,6 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
|
|||||||
if err != nil && err == io.EOF {
|
if err != nil && err == io.EOF {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
log.Logf("[tun] %s - %s: %v", tun.LocalAddr(), conn.LocalAddr(), err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user