-
Notifications
You must be signed in to change notification settings - Fork 0
/
forward.go
113 lines (95 loc) · 2.41 KB
/
forward.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package main
import (
"context"
"errors"
"net"
"time"
"github.com/xjasonlyu/tun2socks/v2/dialer"
"github.com/xjasonlyu/tun2socks/v2/log"
M "github.com/xjasonlyu/tun2socks/v2/metadata"
"github.com/xjasonlyu/tun2socks/v2/proxy/proto"
)
// Base is the base proxy type.
type Base struct {
addr string
proto proto.Proto
}
// Addr returns the address of the proxy.
func (b *Base) Addr() string {
return b.addr
}
// Proto returns the protocol of the proxy.
func (b *Base) Proto() proto.Proto {
return b.proto
}
// DialContext dials a connection to the proxy.
func (b *Base) DialContext(context.Context, *M.Metadata) (net.Conn, error) {
return nil, errors.ErrUnsupported
}
// DialUDP dials a UDP connection to the proxy.
func (b *Base) DialUDP(*M.Metadata) (net.PacketConn, error) {
return nil, errors.ErrUnsupported
}
// Direct is a direct proxy.
type Direct struct {
*Base
}
// NewDirect creates a new Direct proxy.
func NewDirect() *Direct {
return &Direct{
Base: &Base{
addr: "direct",
proto: proto.Direct,
},
}
}
// DialContext dials a connection to the proxy.
func (d *Direct) DialContext(ctx context.Context, metadata *M.Metadata) (net.Conn, error) {
fwd, err := GetForwardedService(_kclient, metadata.DestinationAddress())
if err != nil {
return nil, err
}
c, err := dialer.DialContext(ctx, "tcp", fwd.String())
if err != nil {
return nil, err
}
setKeepAlive(c)
return c, nil
}
// DialUDP dials a UDP connection to the proxy.
func (d *Direct) DialUDP(*M.Metadata) (net.PacketConn, error) {
pc, err := dialer.ListenPacket("udp", "")
if err != nil {
return nil, err
}
return &directPacketConn{PacketConn: pc}, nil
}
type directPacketConn struct {
net.PacketConn
}
func (pc *directPacketConn) WriteTo(b []byte, addr net.Addr) (int, error) {
if udpAddr, ok := addr.(*net.UDPAddr); ok {
return pc.PacketConn.WriteTo(b, udpAddr)
}
udpAddr, err := net.ResolveUDPAddr("udp", addr.String())
if err != nil {
return 0, err
}
return pc.PacketConn.WriteTo(b, udpAddr)
}
const (
tcpKeepAlivePeriod = 30 * time.Second
)
// setKeepAlive sets tcp keepalive option for tcp connection.
func setKeepAlive(c net.Conn) {
if tcp, ok := c.(*net.TCPConn); ok {
err := tcp.SetKeepAlive(true)
if err != nil {
log.Infof("[Direct] failed to set keepalive: %v", err)
}
err = tcp.SetKeepAlivePeriod(tcpKeepAlivePeriod)
if err != nil {
log.Infof("[Direct] failed to set keepalive period: %v", err)
}
}
}