|
@@ -3,6 +3,7 @@ package proxy
|
|
|
import (
|
|
|
"encoding/binary"
|
|
|
"errors"
|
|
|
+ "fmt"
|
|
|
"io"
|
|
|
"net"
|
|
|
"strconv"
|
|
@@ -154,27 +155,126 @@ func (s *Sock5ModeServer) handleConnect(c net.Conn) {
|
|
|
// passive mode
|
|
|
func (s *Sock5ModeServer) handleBind(c net.Conn) {
|
|
|
}
|
|
|
+func (s *Sock5ModeServer) sendUdpReply(writeConn net.Conn, c net.Conn, rep uint8, serverIp string) {
|
|
|
+ reply := []byte{
|
|
|
+ 5,
|
|
|
+ rep,
|
|
|
+ 0,
|
|
|
+ 1,
|
|
|
+ }
|
|
|
+ localHost, localPort, _ := net.SplitHostPort(c.LocalAddr().String())
|
|
|
+ localHost = serverIp
|
|
|
+ ipBytes := net.ParseIP(localHost).To4()
|
|
|
+ nPort, _ := strconv.Atoi(localPort)
|
|
|
+ reply = append(reply, ipBytes...)
|
|
|
+ portBytes := make([]byte, 2)
|
|
|
+ binary.BigEndian.PutUint16(portBytes, uint16(nPort))
|
|
|
+ reply = append(reply, portBytes...)
|
|
|
+ writeConn.Write(reply)
|
|
|
+
|
|
|
+}
|
|
|
|
|
|
-//udp
|
|
|
func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
|
|
- /*
|
|
|
- +----+------+------+----------+----------+----------+
|
|
|
- |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
|
|
|
- +----+------+------+----------+----------+----------+
|
|
|
- | 2 | 1 | 1 | Variable | 2 | Variable |
|
|
|
- +----+------+------+----------+----------+----------+
|
|
|
- */
|
|
|
- buf := make([]byte, 3)
|
|
|
- c.Read(buf)
|
|
|
- // relay udp datagram silently, without any notification to the requesting client
|
|
|
- if buf[2] != 0 {
|
|
|
- // does not support fragmentation, drop it
|
|
|
- logs.Warn("does not support fragmentation, drop")
|
|
|
- dummy := make([]byte, maxUDPPacketSize)
|
|
|
- c.Read(dummy)
|
|
|
+ defer c.Close()
|
|
|
+ addrType := make([]byte, 1)
|
|
|
+ c.Read(addrType)
|
|
|
+ var host string
|
|
|
+ switch addrType[0] {
|
|
|
+ case ipV4:
|
|
|
+ ipv4 := make(net.IP, net.IPv4len)
|
|
|
+ c.Read(ipv4)
|
|
|
+ host = ipv4.String()
|
|
|
+ case ipV6:
|
|
|
+ ipv6 := make(net.IP, net.IPv6len)
|
|
|
+ c.Read(ipv6)
|
|
|
+ host = ipv6.String()
|
|
|
+ case domainName:
|
|
|
+ var domainLen uint8
|
|
|
+ binary.Read(c, binary.BigEndian, &domainLen)
|
|
|
+ domain := make([]byte, domainLen)
|
|
|
+ c.Read(domain)
|
|
|
+ host = string(domain)
|
|
|
+ default:
|
|
|
+ s.sendReply(c, addrTypeNotSupported)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //读取端口
|
|
|
+ var port uint16
|
|
|
+ binary.Read(c, binary.BigEndian, &port)
|
|
|
+ fmt.Println(host, string(port))
|
|
|
+ replyAddr, err := net.ResolveUDPAddr("udp", s.task.ServerIp+":0")
|
|
|
+ if err != nil {
|
|
|
+ logs.Error("build local reply addr error", err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ reply, err := net.ListenUDP("udp", replyAddr)
|
|
|
+ if err != nil {
|
|
|
+ s.sendReply(c, addrTypeNotSupported)
|
|
|
+ logs.Error("listen local reply udp port error")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // reply the local addr
|
|
|
+ s.sendUdpReply(c, reply, succeeded, "106.12.146.199")
|
|
|
+ defer reply.Close()
|
|
|
+
|
|
|
+ // new a tunnel to client
|
|
|
+ link := conn.NewLink("udp", "", s.task.Client.Cnf.Crypt, s.task.Client.Cnf.Compress, c.RemoteAddr().String(), false)
|
|
|
+ target, err := s.bridge.SendLinkInfo(s.task.Client.Id, link, s.task)
|
|
|
+ if err != nil {
|
|
|
+ logs.Warn("get connection from client id %d error %s", s.task.Client.Id, err.Error())
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
- s.doConnect(c, associateMethod)
|
|
|
+ var clientAddr net.Addr
|
|
|
+ // copy buffer
|
|
|
+ go func() {
|
|
|
+ b := common.BufPoolUdp.Get().([]byte)
|
|
|
+ defer common.BufPoolUdp.Put(b)
|
|
|
+ defer c.Close()
|
|
|
+
|
|
|
+ for {
|
|
|
+ n, laddr, err := reply.ReadFrom(b)
|
|
|
+ if err != nil {
|
|
|
+ logs.Error("read data from %s err %s", reply.LocalAddr().String(), err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if clientAddr == nil {
|
|
|
+ clientAddr = laddr
|
|
|
+ }
|
|
|
+ if _, err := target.Write(b[:n]); err != nil {
|
|
|
+ logs.Error("write data to client error", err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ go func() {
|
|
|
+ b := common.BufPoolUdp.Get().([]byte)
|
|
|
+ defer common.BufPoolUdp.Put(b)
|
|
|
+ defer c.Close()
|
|
|
+ for {
|
|
|
+ n, err := target.Read(b)
|
|
|
+ if err != nil {
|
|
|
+ logs.Warn("read data form client error", err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if _, err := reply.WriteTo(b[:n], clientAddr); err != nil {
|
|
|
+ logs.Warn("write data to user ", err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ b := common.BufPoolUdp.Get().([]byte)
|
|
|
+ defer common.BufPoolUdp.Put(b)
|
|
|
+ for {
|
|
|
+ _, err := c.Read(b)
|
|
|
+ if err != nil {
|
|
|
+ c.Close()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
//new conn
|