|
|
|
@ -15,7 +15,6 @@ import ( |
|
|
|
"github.com/shadowsocks/go-shadowsocks2/shadowstream" |
|
|
|
"github.com/songgao/water" |
|
|
|
"github.com/songgao/water/waterutil" |
|
|
|
"github.com/xtaci/tcpraw" |
|
|
|
"golang.org/x/net/ipv4" |
|
|
|
"golang.org/x/net/ipv6" |
|
|
|
) |
|
|
|
@ -472,12 +471,14 @@ func (l *tapListener) Close() error { |
|
|
|
type tapHandler struct { |
|
|
|
options *HandlerOptions |
|
|
|
routes sync.Map |
|
|
|
chExit chan struct{} |
|
|
|
} |
|
|
|
|
|
|
|
// TapHandler creates a handler for tap tunnel.
|
|
|
|
func TapHandler(opts ...HandlerOption) Handler { |
|
|
|
h := &tapHandler{ |
|
|
|
options: &HandlerOptions{}, |
|
|
|
chExit: make(chan struct{}, 1), |
|
|
|
} |
|
|
|
for _, opt := range opts { |
|
|
|
opt(h.options) |
|
|
|
@ -499,44 +500,76 @@ func (h *tapHandler) Handle(conn net.Conn) { |
|
|
|
defer os.Exit(0) |
|
|
|
defer conn.Close() |
|
|
|
|
|
|
|
laddr, raddr := h.options.Node.Addr, h.options.Node.Remote |
|
|
|
var pc net.PacketConn |
|
|
|
var err error |
|
|
|
if h.options.TCPMode { |
|
|
|
if raddr != "" { |
|
|
|
pc, err = tcpraw.Dial("tcp", raddr) |
|
|
|
} else { |
|
|
|
pc, err = tcpraw.Listen("tcp", laddr) |
|
|
|
var raddr net.Addr |
|
|
|
if addr := h.options.Node.Remote; addr != "" { |
|
|
|
raddr, err = net.ResolveUDPAddr("udp", addr) |
|
|
|
if err != nil { |
|
|
|
log.Logf("[tap] %s: remote addr: %v", conn.LocalAddr(), err) |
|
|
|
return |
|
|
|
} |
|
|
|
} else { |
|
|
|
addr, _ := net.ResolveUDPAddr("udp", laddr) |
|
|
|
pc, err = net.ListenUDP("udp", addr) |
|
|
|
} |
|
|
|
if err != nil { |
|
|
|
log.Logf("[tap] %s: %v", conn.LocalAddr(), err) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
if len(h.options.Users) > 0 && h.options.Users[0] != nil { |
|
|
|
passwd, _ := h.options.Users[0].Password() |
|
|
|
cipher, err := core.PickCipher(h.options.Users[0].Username(), nil, passwd) |
|
|
|
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.transportTap(conn, pc, raddr) |
|
|
|
}() |
|
|
|
if err != nil { |
|
|
|
log.Logf("[tap] %s - %s cipher: %v", conn.LocalAddr(), pc.LocalAddr(), err) |
|
|
|
log.Logf("[tap] %s: %v", conn.LocalAddr(), err) |
|
|
|
} |
|
|
|
|
|
|
|
select { |
|
|
|
case <-h.chExit: |
|
|
|
return |
|
|
|
default: |
|
|
|
} |
|
|
|
pc = cipher.PacketConn(pc) |
|
|
|
} |
|
|
|
|
|
|
|
var ra net.Addr |
|
|
|
if raddr != "" { |
|
|
|
ra, err = net.ResolveUDPAddr("udp", raddr) |
|
|
|
if err != nil { |
|
|
|
log.Logf("[tap] %s - %s: remote addr: %v", conn.LocalAddr(), pc.LocalAddr(), err) |
|
|
|
return |
|
|
|
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 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
h.transportTap(conn, pc, ra) |
|
|
|
func (h *tapHandler) initTunnelConn(pc net.PacketConn) (net.PacketConn, error) { |
|
|
|
if len(h.options.Users) > 0 && h.options.Users[0] != nil { |
|
|
|
passwd, _ := h.options.Users[0].Password() |
|
|
|
cipher, err := core.PickCipher(h.options.Users[0].Username(), nil, passwd) |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
pc = cipher.PacketConn(pc) |
|
|
|
} |
|
|
|
return pc, nil |
|
|
|
} |
|
|
|
|
|
|
|
func (h *tapHandler) transportTap(tap net.Conn, conn net.PacketConn, raddr net.Addr) error { |
|
|
|
@ -550,6 +583,10 @@ func (h *tapHandler) transportTap(tap net.Conn, conn net.PacketConn, raddr net.A |
|
|
|
|
|
|
|
n, err := tap.Read(b) |
|
|
|
if err != nil { |
|
|
|
select { |
|
|
|
case h.chExit <- struct{}{}: |
|
|
|
default: |
|
|
|
} |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
@ -654,6 +691,10 @@ func (h *tapHandler) transportTap(tap net.Conn, conn net.PacketConn, raddr net.A |
|
|
|
} |
|
|
|
|
|
|
|
if _, err := tap.Write(b[:n]); err != nil { |
|
|
|
select { |
|
|
|
case h.chExit <- struct{}{}: |
|
|
|
default: |
|
|
|
} |
|
|
|
return err |
|
|
|
} |
|
|
|
return nil |
|
|
|
@ -670,7 +711,6 @@ func (h *tapHandler) transportTap(tap net.Conn, conn net.PacketConn, raddr net.A |
|
|
|
if err != nil && err == io.EOF { |
|
|
|
err = nil |
|
|
|
} |
|
|
|
log.Logf("[tap] %s - %s: %v", tap.LocalAddr(), conn.LocalAddr(), err) |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
|