-
Notifications
You must be signed in to change notification settings - Fork 7
/
redir.go
69 lines (62 loc) · 1.54 KB
/
redir.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
package main
import (
"encoding/binary"
"fmt"
"net"
"github.com/ccsexyz/shadowsocks-go/internal/utils"
ss "github.com/ccsexyz/shadowsocks-go/shadowsocks"
)
func RunTCPRedirServer(c *ss.Config) {
RunTCPServer(c.Localaddr, c, ss.ListenRedir, tcpLocalHandler)
}
type redirUDPLocalConn struct {
net.Conn
}
func (conn *redirUDPLocalConn) Read(b []byte) (n int, err error) {
n, err = conn.Conn.Read(b)
if err != nil || n < 6 {
return
}
n = copy(b, b[6:n])
return
}
func getCreateFuncOfUDPRedirServer(c *ss.Config) func(*utils.SubConn) (net.Conn, net.Conn, error) {
return func(conn *utils.SubConn) (c1, c2 net.Conn, err error) {
buf := make([]byte, 2048)
n, err := conn.Read(buf)
if err != nil {
return nil, nil, err
}
if n < 6 {
return nil, nil, fmt.Errorf("can't read orig dst")
}
rconn, err := ss.DialUDP(c)
if err != nil {
c.Log(err)
return
}
hdrbuf := make([]byte, 512)
hdrlen := ss.PutHeader(buf, net.IP(buf[:4]).String(), int(binary.BigEndian.Uint16(buf[4:6])))
hdrbuf = ss.DupBuffer(hdrbuf[:hdrlen])
_, err = rconn.Write(append(hdrbuf, buf[6:]...))
if err != nil {
rconn.Close()
return
}
c1 = rconn
c2 = &udpRemoteConn{Conn: &redirUDPLocalConn{Conn: conn}, header: hdrbuf}
return
}
}
func RunUDPRedirServer(c *ss.Config) {
listener, err := utils.NewUDPListener(c.Localaddr)
if err != nil {
c.Logger.Fatal(err)
}
defer listener.Close()
tproxyListner, err := ss.NewUDPTProxyConn(listener)
if err != nil {
c.Logger.Fatal(err)
}
RunUDPServer(tproxyListner, c, getCreateFuncOfUDPRedirServer)
}