Skip to content

Commit

Permalink
0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
mmmdbybyd authored Mar 13, 2020
1 parent 6848d4b commit 77eeeda
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 101 deletions.
4 changes: 4 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
0.2
改进加密(以后应该不需要改进了)
添加tcpDNS Over udpDNS,让客户端的tcpDNS解析更快
修复了一些小bug,至于CPU占用100%,目前还不知道有没有解决
37 changes: 37 additions & 0 deletions CuteBi_XorCrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// CuteBi_XorCrypt.go
package main

import (
"encoding/base64"
"errors"
)

var CuteBi_XorCrypt_password []byte

/* 一个简单的异或加密 */
func CuteBi_XorCrypt(data []byte, passwordSub int) int {
for dataSub := 0; dataSub < len(data); {
data[dataSub] ^= CuteBi_XorCrypt_password[passwordSub] | byte(passwordSub) //如果只是data[dataSub] ^= CuteBi_XorCrypt_password[passwordSub],则密码"12"跟密码"1212"没用任何区别
dataSub++
passwordSub++
if passwordSub == len(CuteBi_XorCrypt_password) {
passwordSub = 0
}
}

return passwordSub
}

func CuteBi_decrypt_host(host []byte) ([]byte, error) {
hostDec := make([]byte, len(host))
n, err := base64.StdEncoding.Decode(hostDec, host)
if err != nil {
return nil, err
}
CuteBi_XorCrypt(hostDec, 0)
if hostDec[n-1] != 0 {
return nil, errors.New("Decrypt failed.")
}

return hostDec[:n-1], nil
}
29 changes: 16 additions & 13 deletions cns.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import (
)

var (
listener *net.TCPListener
udpFlag string
proxyKey []byte
tcp_timeout, udp_timeout, tcp_keepAlive time.Duration
enable_httpDNS, enable_TFO bool
listener *net.TCPListener
udpFlag string
proxyKey []byte
tcp_timeout, udp_timeout, tcp_keepAlive time.Duration
enable_dns_tcpOverUdp, enable_httpDNS, enable_TFO bool
)

func isHttpHeader(header []byte) bool {
Expand Down Expand Up @@ -58,16 +58,17 @@ func handleConn(cConn *net.TCPConn, payload []byte) {
cConn.SetKeepAlivePeriod(tcp_keepAlive)
cConn.SetReadDeadline(time.Now().Add(tcp_timeout))

RLen, _ := cConn.Read(payload)
if RLen <= 0 {
RLen, err := cConn.Read(payload)
if err != nil || RLen <= 0 {
cConn.Close()
return
}
if isHttpHeader(payload[:RLen]) == false {
handleUdpSession(cConn, payload[:RLen])
} else {
if enable_httpDNS == false || Respond_HttpDNS(cConn, payload[:RLen]) == false { /*优先处理httpDNS请求*/
if WLen, _ := cConn.Write(rspHeader(payload[:RLen])); WLen <= 0 {
if WLen, err := cConn.Write(rspHeader(payload[:RLen])); err != nil || WLen <= 0 {
cConn.Close()
return
}
if bytes.Contains(payload[:RLen], []byte(udpFlag)) == true {
Expand All @@ -93,17 +94,18 @@ func pidSaveToFile(pidPath string) {
}

func handleCmd() {
var listenAddrString, proxyKeyString, encryptPassword, pidPath string
var listenAddrString, proxyKeyString, CuteBi_XorCrypt_passwordStr, pidPath string
var help, enable_daemon bool

flag.StringVar(&proxyKeyString, "proxy-key", "Host", "tcp request proxy host key")
flag.StringVar(&udpFlag, "udp-flag", "httpUDP", "udp request flag string")
flag.StringVar(&listenAddrString, "listen-addr", ":8989", "listen aaddress")
flag.StringVar(&encryptPassword, "encrypt-password", "", "encrypt password")
flag.StringVar(&CuteBi_XorCrypt_passwordStr, "encrypt-password", "", "encrypt password")
flag.Int64Var((*int64)(&tcp_timeout), "tcp-timeout", 600, "tcp timeout second")
flag.Int64Var((*int64)(&udp_timeout), "udp-timeout", 30, "udp timeout second")
flag.Int64Var((*int64)(&tcp_keepAlive), "tcp-keepalive", 15, "tcp keepalive second")
flag.Int64Var((*int64)(&tcp_keepAlive), "tcp-keepalive", 60, "tcp keepalive second")
flag.StringVar(&pidPath, "pid-path", "", "pid file path")
flag.BoolVar(&enable_dns_tcpOverUdp, "dns-tcpOverUdp", false, "tcpDNS Over udpDNS switch")
flag.BoolVar(&enable_httpDNS, "enable-httpDNS", false, "httpDNS server switch")
flag.BoolVar(&enable_TFO, "enable-TFO", false, "listener tcpFastOpen switch")
flag.BoolVar(&enable_daemon, "daemon", false, "daemon mode switch")
Expand All @@ -126,7 +128,7 @@ func handleCmd() {
listener, err = net.ListenTCP("tcp", listenAddr)
if err != nil {
log.Println(err)
return
os.Exit(1)
}
if enable_TFO == true {
enableTcpFastopen(listener)
Expand All @@ -135,10 +137,10 @@ func handleCmd() {
pidSaveToFile(pidPath)
}
proxyKey = []byte("\n" + proxyKeyString + ": ")
CuteBi_XorCrypt_password = []byte(CuteBi_XorCrypt_passwordStr)
tcp_timeout *= time.Second
udp_timeout *= time.Second
tcp_keepAlive *= time.Second
make_CuteBi_encrypt_PassCode([]byte(encryptPassword))
}

func initProcess() {
Expand All @@ -161,6 +163,7 @@ func main() {
conn, err = listener.AcceptTCP()
if err != nil {
log.Println(err)
time.Sleep(3 * time.Second)
continue
}
go handleConn(conn, make([]byte, 8192))
Expand Down
94 changes: 94 additions & 0 deletions dns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// dns.go
package main

import (
"bytes"
"fmt"
"log"
"net"
"strings"
"time"
)

func dns_tcpOverUdp(cConn *net.TCPConn, host string, buffer []byte) {
log.Println("Start dns_tcpOverUdp")
defer cConn.Close()

var err error
var WLen, RLen, payloadLen int
var pkgLen uint16
for {
cConn.SetReadDeadline(time.Now().Add(tcp_timeout))
RLen, err = cConn.Read(buffer[payloadLen:])
if RLen <= 0 || err != nil {
return
}
//解密
if len(CuteBi_XorCrypt_password) != 0 {
CuteBi_XorCrypt(buffer[payloadLen:payloadLen+RLen], 0)
}
payloadLen += RLen
if payloadLen > 2 {
pkgLen = (uint16(buffer[0]) << 8) | (uint16(buffer[1])) //包长度转换
//防止访问非法数据
if int(pkgLen)+2 >= len(buffer) {
return
}
//如果读取到了一个完整的包,就跳出循环
if int(pkgLen)+2 <= payloadLen {
break
}
}
}
/* 连接目标地址 */
sConn, dialErr := net.Dial("udp", host)
if dialErr != nil {
log.Println(dialErr)
cConn.Write([]byte("Proxy address [" + host + "] DNS Dial() error"))
return
}
defer sConn.Close()
sConn.SetReadDeadline(time.Now().Add(udp_timeout))
if WLen, err = sConn.Write(buffer[2:payloadLen]); WLen <= 0 || err != nil {
return
}
if RLen, err = sConn.Read(buffer[2:]); RLen <= 0 || err != nil {
return
}
//包长度转换
buffer[0] = byte(RLen << 8)
buffer[1] = byte(RLen >> 8)
//加密
if len(CuteBi_XorCrypt_password) != 0 {
CuteBi_XorCrypt(buffer[:2+RLen], 0)
}
cConn.Write(buffer[:2+RLen])
}

func Respond_HttpDNS(cConn *net.TCPConn, header []byte) bool {
var domain string
httpDNS_DomainSub := bytes.Index(header[:], []byte("?dn="))
if httpDNS_DomainSub < 0 {
return false
}
if _, err := fmt.Sscanf(string(header[httpDNS_DomainSub+4:]), "%s", &domain); err != nil {
log.Println(err)
return false
}
log.Println("httpDNS domain: [" + domain + "]")
defer cConn.Close()
ips, err := net.LookupHost(domain)
if err != nil {
cConn.Write([]byte("HTTP/1.0 404 Not Found\r\nConnection: Close\r\nServer: CuteBi Linux Network httpDNS, (%>w<%)\r\nContent-type: charset=utf-8\r\n\r\n<html><head><title>HTTP DNS Server</title></head><body>查询域名失败<br/><br/>By: 萌萌萌得不要不要哒<br/>E-mail: [email protected]</body></html>"))
log.Println("httpDNS domain: [" + domain + "], Lookup failed")
} else {
for i := 0; i < len(ips); i++ {
if strings.Contains(ips[i], ":") == false { //跳过ipv6
fmt.Fprintf(cConn, "HTTP/1.0 200 OK\r\nConnection: Close\r\nServer: CuteBi Linux Network httpDNS, (%%>w<%%)\r\nContent-Length: %d\r\n\r\n%s", len(string(ips[i])), string(ips[i]))
break
}
}
log.Println("httpDNS domain: ["+domain+"], IPS: ", ips)
}
return true
}
58 changes: 36 additions & 22 deletions tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,54 @@ import (
//"fmt"
"log"
"net"
"strings"
"time"
)

/* 把fromConn的数据转发到toConn */
func tcpForward(fromConn, toConn net.Conn, payload []byte, ENorDE_Func func([]byte, byte) byte, dynamic_code byte) {
func tcpForward(fromConn, toConn *net.TCPConn, payload []byte) {
defer fromConn.Close()
defer toConn.Close()

var RLen, WLen int
var RLen, WLen, CuteBi_XorCrypt_passwordSub int
var err error
for {
fromConn.SetReadDeadline(time.Now().Add(tcp_timeout))
if RLen, _ = fromConn.Read(payload[:]); RLen <= 0 {
toConn.SetReadDeadline(time.Now().Add(tcp_timeout))
if RLen, err = fromConn.Read(payload); err != nil || RLen <= 0 {
return
}
if passLen_code != 0 {
dynamic_code = ENorDE_Func(payload[:RLen], dynamic_code)
if len(CuteBi_XorCrypt_password) != 0 {
CuteBi_XorCrypt_passwordSub = CuteBi_XorCrypt(payload[:RLen], CuteBi_XorCrypt_passwordSub)
}
toConn.SetWriteDeadline(time.Now().Add(tcp_timeout))
if WLen, _ = toConn.Write(payload[:RLen]); WLen <= 0 {
if WLen, err = toConn.Write(payload[:RLen]); err != nil || WLen <= 0 {
return
}
}
}

/* 从header中获取host */
func getProxyHost(header []byte) (string, byte) {
func getProxyHost(header []byte) string {
hostSub := bytes.Index(header, proxyKey)
if hostSub < 0 {
return "", 0
return ""
}
hostSub += len(proxyKey)
hostEndSub := bytes.IndexByte(header[hostSub:], '\r')
if hostEndSub < 0 {
return "", 0
return ""
}
hostEndSub += hostSub
if passLen_code != 0 {
host, dynamic_code, err := CuteBi_decrypt_host(header[hostSub:hostEndSub])
if len(CuteBi_XorCrypt_password) != 0 {
host, err := CuteBi_decrypt_host(header[hostSub:hostEndSub])
if err != nil {
log.Println(err)
return "", 0
return ""
}
return string(host), dynamic_code
return string(host)
} else {
return string(header[hostSub:hostEndSub]), 0
return string(header[hostSub:hostEndSub])
}
}

Expand All @@ -59,27 +62,38 @@ func handleTcpSession(cConn *net.TCPConn, header []byte) {
defer log.Println("A tcp client close")

/* 获取请求头中的host */
host, dynamic_code := getProxyHost(header)
host := getProxyHost(header)
if host == "" {
log.Println("No proxy host: {" + string(header) + "}")
cConn.Write([]byte("No proxy host"))
cConn.Close()
return
}
log.Println("proxyHost: " + host)
//tcpDNS over udpDNS
if enable_dns_tcpOverUdp && strings.HasSuffix(host, ":53") == true {
dns_tcpOverUdp(cConn, host, header)
return
}
/* 连接目标地址 */
sAddr, _ := net.ResolveTCPAddr("tcp", host)
sConn, err := net.DialTCP("tcp", nil, sAddr)
if err != nil {
log.Println(err)
cConn.Write([]byte("Proxy address [" + host + "] error"))
sAddr, resErr := net.ResolveTCPAddr("tcp", host)
if resErr != nil {
log.Println(resErr)
cConn.Write([]byte("Proxy address [" + host + "] ResolveTCP() error"))
cConn.Close()
return
}
sConn, dialErr := net.DialTCP("tcp", nil, sAddr)
if dialErr != nil {
log.Println(dialErr)
cConn.Write([]byte("Proxy address [" + host + "] DialTCP() error"))
cConn.Close()
return
}
sConn.SetKeepAlive(true)
sConn.SetKeepAlivePeriod(tcp_keepAlive)
/* 开始转发 */
log.Println("Start tcpForward")
go tcpForward(cConn, sConn, make([]byte, 8192), CuteBi_decrypt, dynamic_code)
tcpForward(sConn, cConn, header, CuteBi_encrypt, dynamic_code)
go tcpForward(cConn, sConn, make([]byte, 8192))
tcpForward(sConn, cConn, header)
}
Loading

0 comments on commit 77eeeda

Please sign in to comment.