diff --git a/Changes b/Changes index c7d2aaa..c307433 100644 --- a/Changes +++ b/Changes @@ -21,3 +21,7 @@ 0.3.1 重新添加tcpFastOpen功能 取消多个tls配置 + +0.3.2 + 修复tunnel握手后转为tls的情况下udp无法代理 + 优化TFO diff --git a/README.md b/README.md index 3f43c8e..7cb0a6c 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # CuteBi Network Server -网络代理服务端, 支持IPV6,tcpFastOpen,UDP_Over_HttpTunnel(需要配合专门的客户端) +CuteBi网络代理服务端, 支持IPV6,tcpFastOpen(win暂不支持),UDP_Over_HttpTunnel(需要配合专门的客户端) 1. 普通的CONNECT代理服务器(暂时不考虑添加普通http支持) 2. 实现与114DNS以及腾讯的dnsPod一样的httpDNS服务端 - 3. 配合专门的客户端可以实现TCP/UDP全局代理, 目前有: https://github.com/mmmdbybyd/CLNC + 3. 配合专门的客户端可以实现TCP/UDP全局代理, 目前有: [CLNC](https://github.com/mmmdbybyd/CLNC) 单独服务端: -------- 1. 普通的CONNECT代理服务器(暂时不考虑添加普通http支持) 2. 实现与114DNS以及腾讯的dnsPod一样的httpDNS服务端 - + 服务端+客户端: -------- 1. 可伪装为各种HTTP/HTTPS数据, 并加密传输流量(可选) @@ -26,8 +26,9 @@ go build -o cns ~~~~~ ##### 启动命令: +[配置文件格式](config/cns.json) ~~~~~ -./cns -daemon=true -json=cns.json #配置文件格式请查看config文件夹 +./cns -daemon=true -json=cns.json ~~~~~ ##### Linux一键: @@ -35,4 +36,3 @@ go build -o cns 安装: `type curl &>/dev/null && echo 'curl -O' || echo 'wget -O cns.sh'` http://pros.cutebi.taobao69.cn:666/cns/cns.sh && sh cns.sh 卸载: `type curl &>/dev/null && echo 'curl -O' || echo 'wget -O cns.sh'` http://pros.cutebi.taobao69.cn:666/cns/cns.sh && sh cns.sh uninstall ~~~~~ - diff --git a/cns.go b/cns.go index 0ce4c98..cd0abd2 100644 --- a/cns.go +++ b/cns.go @@ -71,7 +71,7 @@ func handleCmd() { if help == true { fmt.Println(" /) /)\n" + "ฅ(՞•ﻌ•՞)ฅ\n" + - "CuteBi Network Server 0.3.1\nAuthor: CuteBi(Mmmdbybyd)\nE-mail: 915445800@qq.com\n") + "CuteBi Network Server 0.3.2\nAuthor: CuteBi(Mmmdbybyd)\nE-mail: 915445800@qq.com\n") flag.Usage() os.Exit(0) } @@ -90,6 +90,11 @@ func handleCmd() { log.Println(err) os.Exit(1) } + //有效uid不为0(root)的关闭tfo + if config.Enable_TFO == true && os.Geteuid() != 0 { + config.Enable_TFO = false + fmt.Println("TFO cannot be opened: CNS effective UID isn't 0(root).") + } if config.Pid_path != "" { pidSaveToFile(config.Pid_path) } diff --git a/http_tunnel.go b/http_tunnel.go index 64c0eff..048c944 100644 --- a/http_tunnel.go +++ b/http_tunnel.go @@ -59,13 +59,13 @@ func handleTunnel(cConn net.Conn, payload []byte, tlsConfig *tls.Config) { cConn.Close() return } + /* 转为tls的conn */ + if tlsConfig != nil { + cConn = tls.Server(cConn, tlsConfig) + } if bytes.Contains(payload[:RLen], []byte(config.Udp_flag)) == true { - handleTunnel(cConn, payload, tlsConfig) //httpUDP需要读取到二进制数据才进行处理 + handleUdpSession(cConn, nil) } else { - /* 转为tls的conn */ - if tlsConfig != nil { - cConn = tls.Server(cConn, tlsConfig) - } handleTcpSession(cConn, payload) } } diff --git a/tfo/listener_isNotWin.go b/tfo/listener_isNotWin.go index 4fdce85..c635216 100644 --- a/tfo/listener_isNotWin.go +++ b/tfo/listener_isNotWin.go @@ -4,7 +4,6 @@ package tfo import ( "bytes" - "context" "net" "os" "syscall" @@ -20,47 +19,49 @@ type tfoListener struct { ServerAddr [16]byte ServerPort int fd int - ctx context.Context } // Listen will listen given host and give back a Listener which implement the net.Listener func Listen(host string) (Listener, error) { r := &tfoListener{} - addr, err := net.ResolveTCPAddr("tcp", host) - if err != nil { - return nil, err + addr, err := net.ResolveTCPAddr("tcp6", host) + if err == nil { + //addr.IP存放的是ipv6地址,直接复制 + copy(r.ServerAddr[:], addr.IP) + } else { + //不是ipv6地址,尝试解析ipv4地址 + addr, err = net.ResolveTCPAddr("tcp4", host) + if err != nil { + return nil, err + } + if bytes.HasSuffix(addr.IP, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) { + //addr.IP前4字节存放ipv4地址,转为ipv4映射ipv6 + copy(r.ServerAddr[:12], []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff}) + copy(r.ServerAddr[12:], addr.IP[:4]) + } else { + //addr.IP存放的是ipv4映射ipv6地址 直接复制 + copy(r.ServerAddr[:], addr.IP) + } } r.ServerPort = addr.Port - copy(r.ServerAddr[:], addr.IP) - /* 如果为ipv4格式则转为ipv4映射ipv6格式 */ - if bytes.HasSuffix(r.ServerAddr[:], []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) { - copy(r.ServerAddr[12:], r.ServerAddr[:4]) - copy(r.ServerAddr[:12], []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff}) - } - sa := &syscall.SockaddrInet6{Addr: r.ServerAddr, Port: r.ServerPort} - fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, 0) + r.fd, err = syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, 0) if err != nil { if err == syscall.ENOPROTOOPT { return nil, ErrTFONotSupport } return nil, err } - r.fd = fd - syscall.SetsockoptInt(r.fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) - - err = syscall.Bind(r.fd, sa) + err = syscall.Bind(r.fd, &syscall.SockaddrInet6{Addr: r.ServerAddr, Port: r.ServerPort}) if err != nil { return nil, err } - err = syscall.SetsockoptInt(r.fd, syscall.IPPROTO_TCP, TCPFastOpen, 3) if err != nil { return nil, err } - err = syscall.Listen(r.fd, ListenBacklog) if err != nil { return nil, err diff --git a/tfo/listener_isWin.go b/tfo/listener_isWin.go index c3c683e..325115a 100644 --- a/tfo/listener_isWin.go +++ b/tfo/listener_isWin.go @@ -1,100 +1,13 @@ // +build windows +/* windows暂时不支持tcpFastOpen */ + package tfo import ( - "bytes" - "context" "net" - "os" - "syscall" -) - -const ( - TCPFastOpen int = 23 - ListenBacklog int = 23 ) -// tfoListener implement the RazorListener can also be used as the net.Listener -type tfoListener struct { - ServerAddr [16]byte - ServerPort int - fd syscall.Handle - ctx context.Context -} - -// Listen will listen given host and give back a Listener which implement the net.Listener func Listen(host string) (Listener, error) { - r := &tfoListener{} - - addr, err := net.ResolveTCPAddr("tcp", host) - if err != nil { - return nil, err - } - r.ServerPort = addr.Port - copy(r.ServerAddr[:], addr.IP) - /* 如果为ipv4格式则转为ipv4映射ipv6格式 */ - if bytes.HasSuffix(r.ServerAddr[:], []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) { - copy(r.ServerAddr[12:], r.ServerAddr[:4]) - copy(r.ServerAddr[:12], []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff}) - } - sa := &syscall.SockaddrInet6{Addr: r.ServerAddr, Port: r.ServerPort} - - fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, 0) - if err != nil { - if err == syscall.ENOPROTOOPT { - return nil, ErrTFONotSupport - } - return nil, err - } - r.fd = fd - - syscall.SetsockoptInt(r.fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) - - err = syscall.Bind(r.fd, sa) - if err != nil { - return nil, err - } - - err = syscall.SetsockoptInt(r.fd, syscall.IPPROTO_TCP, TCPFastOpen, 3) - if err != nil { - return nil, err - } - - err = syscall.Listen(r.fd, ListenBacklog) - if err != nil { - return nil, err - } - - return r, nil -} - -func (r *tfoListener) Accept() (net.Conn, error) { - cfd, _, err := syscall.Accept(r.fd) - if err != nil { - return nil, err - } - - f := os.NewFile(uintptr(cfd), "") - defer f.Close() - return net.FileConn(f) -} - -func (r *tfoListener) Close() error { - err := syscall.Shutdown(r.fd, syscall.SHUT_RDWR) - if err != nil { - return err - } - err = syscall.Close(r.fd) - if err != nil { - return err - } - return nil -} - -func (r *tfoListener) Addr() net.Addr { - return &net.TCPAddr{ - IP: r.ServerAddr[:], - Port: r.ServerPort, - } + return net.Listen("tcp", host) } diff --git a/udp.go b/udp.go index f288cb1..e253f56 100644 --- a/udp.go +++ b/udp.go @@ -105,13 +105,16 @@ func (udpSess *UdpSession) udpClientToServer(httpUDP_data []byte) { var payload_len, RLen, WLen int var err error - WLen = udpSess.writeToServer(httpUDP_data) - if WLen == -1 { - return - } + payload := make([]byte, 65536) - if WLen < len(httpUDP_data) { - payload_len = copy(payload, httpUDP_data[WLen:]) + if httpUDP_data != nil { + WLen = udpSess.writeToServer(httpUDP_data) + if WLen == -1 { + return + } + if WLen < len(httpUDP_data) { + payload_len = copy(payload, httpUDP_data[WLen:]) + } } for { udpSess.cConn.SetReadDeadline(time.Now().Add(config.Udp_timeout)) @@ -137,7 +140,7 @@ func (udpSess *UdpSession) udpClientToServer(httpUDP_data []byte) { } func (udpSess *UdpSession) initUdp(httpUDP_data []byte) bool { - if len(CuteBi_XorCrypt_password) != 0 { + if httpUDP_data != nil && len(CuteBi_XorCrypt_password) != 0 { de := make([]byte, 5) copy(de, httpUDP_data[0:5]) CuteBi_XorCrypt(de, 0)