增加gomobile sdk对android/ios进行支持.

优化错误控制

Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>
This commit is contained in:
arraykeys@gmail.com
2018-04-09 16:16:55 +08:00
parent a11ce38747
commit 3aba428b76
15 changed files with 626 additions and 354 deletions

41
sdk/release.sh Executable file
View File

@ -0,0 +1,41 @@
#/bin/bash
VER="v4.7"
rm -rf release-*
#arm
gomobile bind -v -target=android/arm
mkdir proxy-sdk-arm
mv sdk.aar proxy-sdk-arm/proxy-sdk-arm.aar
mv sdk-sources.jar proxy-sdk-arm/proxy-sdk-arm-sources.jar
tar zcfv proxy-sdk-arm-${VER}.tar.gz proxy-sdk-arm
rm -rf proxy-sdk-arm
#arm64
gomobile bind -v -target=android/arm64
mkdir proxy-sdk-arm64
mv sdk.aar proxy-sdk-arm64/proxy-sdk-arm64.aar
mv sdk-sources.jar proxy-sdk-arm64/proxy-sdk-arm64-sources.jar
tar zcfv proxy-sdk-arm64-${VER}.tar.gz proxy-sdk-arm64
rm -rf proxy-sdk-arm64
#386
gomobile bind -v -target=android/386
mkdir proxy-sdk-386
mv sdk.aar proxy-sdk-386/proxy-sdk-386.aar
mv sdk-sources.jar proxy-sdk-386/proxy-sdk-386-sources.jar
tar zcfv proxy-sdk-386-${VER}.tar.gz proxy-sdk-386
rm -rf proxy-sdk-386
#amd64
gomobile bind -v -target=android/amd64
mkdir proxy-sdk-amd64
mv sdk.aar proxy-sdk-amd64/proxy-sdk-amd64.aar
mv sdk-sources.jar proxy-sdk-amd64/proxy-sdk-amd64-sources.jar
tar zcfv proxy-sdk-amd64-${VER}.tar.gz proxy-sdk-amd64
rm -rf proxy-sdk-amd64
#all-in-one
gomobile bind -v -target=android
mkdir proxy-sdk-all
mv sdk.aar proxy-sdk-all/proxy-sdk-all.aar
mv sdk-sources.jar proxy-sdk-all/proxy-sdk-all-sources.jar
tar zcfv proxy-sdk-all-${VER}.tar.gz proxy-sdk-all
rm -rf proxy-sdk-all
mkdir proxy-sdk-release-${VER}
mv *.tar.gz proxy-sdk-release-${VER}
echo "done."

325
sdk/sdk.go Normal file
View File

@ -0,0 +1,325 @@
package sdk
import (
"crypto/sha1"
"fmt"
"log"
"os"
"snail007/proxy/services"
"snail007/proxy/services/kcpcfg"
"strings"
kcp "github.com/xtaci/kcp-go"
"golang.org/x/crypto/pbkdf2"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
var (
app *kingpin.Application
service *services.ServiceItem
)
//Start argsStr: is the whole command line args string
//such as :
//1."http -t tcp -p :8989"
//2."socks -t tcp -p :8989"
//and so on.
//if an error occured , errStr will be the error reason
//if start success, errStr is empty.
func Start(argsStr string) (errStr string) {
//define args
tcpArgs := services.TCPArgs{}
httpArgs := services.HTTPArgs{}
tunnelServerArgs := services.TunnelServerArgs{}
tunnelClientArgs := services.TunnelClientArgs{}
tunnelBridgeArgs := services.TunnelBridgeArgs{}
muxServerArgs := services.MuxServerArgs{}
muxClientArgs := services.MuxClientArgs{}
muxBridgeArgs := services.MuxBridgeArgs{}
udpArgs := services.UDPArgs{}
socksArgs := services.SocksArgs{}
spsArgs := services.SPSArgs{}
kcpArgs := kcpcfg.KCPConfigArgs{}
//build srvice args
app = kingpin.New("proxy", "happy with proxy")
app.Author("snail").Version("4.7")
debug := app.Flag("debug", "debug log output").Default("false").Bool()
logfile := app.Flag("log", "log file path").Default("").String()
kcpArgs.Key = app.Flag("kcp-key", "pre-shared secret between client and server").Default("secrect").String()
kcpArgs.Crypt = app.Flag("kcp-method", "encrypt/decrypt method, can be: aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, sm4, none").Default("aes").Enum("aes", "aes-128", "aes-192", "salsa20", "blowfish", "twofish", "cast5", "3des", "tea", "xtea", "xor", "sm4", "none")
kcpArgs.Mode = app.Flag("kcp-mode", "profiles: fast3, fast2, fast, normal, manual").Default("fast").Enum("fast3", "fast2", "fast", "normal", "manual")
kcpArgs.MTU = app.Flag("kcp-mtu", "set maximum transmission unit for UDP packets").Default("1350").Int()
kcpArgs.SndWnd = app.Flag("kcp-sndwnd", "set send window size(num of packets)").Default("1024").Int()
kcpArgs.RcvWnd = app.Flag("kcp-rcvwnd", "set receive window size(num of packets)").Default("1024").Int()
kcpArgs.DataShard = app.Flag("kcp-ds", "set reed-solomon erasure coding - datashard").Default("10").Int()
kcpArgs.ParityShard = app.Flag("kcp-ps", "set reed-solomon erasure coding - parityshard").Default("3").Int()
kcpArgs.DSCP = app.Flag("kcp-dscp", "set DSCP(6bit)").Default("0").Int()
kcpArgs.NoComp = app.Flag("kcp-nocomp", "disable compression").Default("false").Bool()
kcpArgs.AckNodelay = app.Flag("kcp-acknodelay", "be carefull! flush ack immediately when a packet is received").Default("true").Bool()
kcpArgs.NoDelay = app.Flag("kcp-nodelay", "be carefull!").Default("0").Int()
kcpArgs.Interval = app.Flag("kcp-interval", "be carefull!").Default("50").Int()
kcpArgs.Resend = app.Flag("kcp-resend", "be carefull!").Default("0").Int()
kcpArgs.NoCongestion = app.Flag("kcp-nc", "be carefull! no congestion").Default("0").Int()
kcpArgs.SockBuf = app.Flag("kcp-sockbuf", "be carefull!").Default("4194304").Int()
kcpArgs.KeepAlive = app.Flag("kcp-keepalive", "be carefull!").Default("10").Int()
//########http#########
http := app.Command("http", "proxy on http mode")
httpArgs.Parent = http.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
httpArgs.CaCertFile = http.Flag("ca", "ca cert file for tls").Default("").String()
httpArgs.CertFile = http.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
httpArgs.KeyFile = http.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
httpArgs.LocalType = http.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
httpArgs.ParentType = http.Flag("parent-type", "parent protocol type <tls|tcp|ssh|kcp>").Short('T').Enum("tls", "tcp", "ssh", "kcp")
httpArgs.Always = http.Flag("always", "always use parent proxy").Default("false").Bool()
httpArgs.Timeout = http.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Default("2000").Int()
httpArgs.HTTPTimeout = http.Flag("http-timeout", "check domain if blocked , http request timeout milliseconds when connect to host").Default("3000").Int()
httpArgs.Interval = http.Flag("interval", "check domain if blocked every interval seconds").Default("10").Int()
httpArgs.Blocked = http.Flag("blocked", "blocked domain file , one domain each line").Default("blocked").Short('b').String()
httpArgs.Direct = http.Flag("direct", "direct domain file , one domain each line").Default("direct").Short('d').String()
httpArgs.AuthFile = http.Flag("auth-file", "http basic auth file,\"username:password\" each line in file").Short('F').String()
httpArgs.Auth = http.Flag("auth", "http basic auth username and password, mutiple user repeat -a ,such as: -a user1:pass1 -a user2:pass2").Short('a').Strings()
httpArgs.PoolSize = http.Flag("pool-size", "conn pool size , which connect to parent proxy, zero: means turn off pool").Short('L').Default("0").Int()
httpArgs.CheckParentInterval = http.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
httpArgs.Local = http.Flag("local", "local ip:port to listen,multiple address use comma split,such as: 0.0.0.0:80,0.0.0.0:443").Short('p').Default(":33080").String()
httpArgs.SSHUser = http.Flag("ssh-user", "user for ssh").Short('u').Default("").String()
httpArgs.SSHKeyFile = http.Flag("ssh-key", "private key file for ssh").Short('S').Default("").String()
httpArgs.SSHKeyFileSalt = http.Flag("ssh-keysalt", "salt of ssh private key").Short('s').Default("").String()
httpArgs.SSHPassword = http.Flag("ssh-password", "password for ssh").Short('A').Default("").String()
httpArgs.LocalIPS = http.Flag("local bind ips", "if your host behind a nat,set your public ip here avoid dead loop").Short('g').Strings()
httpArgs.AuthURL = http.Flag("auth-url", "http basic auth username and password will send to this url,response http code equal to 'auth-code' means ok,others means fail.").Default("").String()
httpArgs.AuthURLTimeout = http.Flag("auth-timeout", "access 'auth-url' timeout milliseconds").Default("3000").Int()
httpArgs.AuthURLOkCode = http.Flag("auth-code", "access 'auth-url' success http code").Default("204").Int()
httpArgs.AuthURLRetry = http.Flag("auth-retry", "access 'auth-url' fail and retry count").Default("1").Int()
httpArgs.DNSAddress = http.Flag("dns-address", "if set this, proxy will use this dns for resolve doamin").Short('q').Default("").String()
httpArgs.DNSTTL = http.Flag("dns-ttl", "caching seconds of dns query result").Short('e').Default("300").Int()
//########tcp#########
tcp := app.Command("tcp", "proxy on tcp mode")
tcpArgs.Parent = tcp.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
tcpArgs.CertFile = tcp.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
tcpArgs.KeyFile = tcp.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('e').Default("2000").Int()
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|kcp|udp>").Short('T').Enum("tls", "tcp", "udp", "kcp")
tcpArgs.LocalType = tcp.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
tcpArgs.PoolSize = tcp.Flag("pool-size", "conn pool size , which connect to parent proxy, zero: means turn off pool").Short('L').Default("0").Int()
tcpArgs.CheckParentInterval = tcp.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
tcpArgs.Local = tcp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
//########udp#########
udp := app.Command("udp", "proxy on udp mode")
udpArgs.Parent = udp.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
udpArgs.CertFile = udp.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
udpArgs.KeyFile = udp.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
udpArgs.Timeout = udp.Flag("timeout", "tcp timeout milliseconds when connect to parent proxy").Short('t').Default("2000").Int()
udpArgs.ParentType = udp.Flag("parent-type", "parent protocol type <tls|tcp|udp>").Short('T').Enum("tls", "tcp", "udp")
udpArgs.PoolSize = udp.Flag("pool-size", "conn pool size , which connect to parent proxy, zero: means turn off pool").Short('L').Default("0").Int()
udpArgs.CheckParentInterval = udp.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
udpArgs.Local = udp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
//########mux-server#########
muxServer := app.Command("server", "proxy on mux server mode")
muxServerArgs.Parent = muxServer.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
muxServerArgs.ParentType = muxServer.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Default("tls").Short('T').Enum("tls", "tcp", "kcp")
muxServerArgs.CertFile = muxServer.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
muxServerArgs.KeyFile = muxServer.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
muxServerArgs.Timeout = muxServer.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
muxServerArgs.IsUDP = muxServer.Flag("udp", "proxy on udp mux server mode").Default("false").Bool()
muxServerArgs.Key = muxServer.Flag("k", "client key").Default("default").String()
muxServerArgs.Route = muxServer.Flag("route", "local route to client's network, such as: PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings()
muxServerArgs.IsCompress = muxServer.Flag("c", "compress data when tcp|tls mode").Default("false").Bool()
muxServerArgs.SessionCount = muxServer.Flag("session-count", "session count which connect to bridge").Short('n').Default("10").Int()
//########mux-client#########
muxClient := app.Command("client", "proxy on mux client mode")
muxClientArgs.Parent = muxClient.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
muxClientArgs.ParentType = muxClient.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Default("tls").Short('T').Enum("tls", "tcp", "kcp")
muxClientArgs.CertFile = muxClient.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
muxClientArgs.KeyFile = muxClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
muxClientArgs.Timeout = muxClient.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
muxClientArgs.Key = muxClient.Flag("k", "key same with server").Default("default").String()
muxClientArgs.IsCompress = muxClient.Flag("c", "compress data when tcp|tls mode").Default("false").Bool()
muxClientArgs.SessionCount = muxClient.Flag("session-count", "session count which connect to bridge").Short('n').Default("10").Int()
//########mux-bridge#########
muxBridge := app.Command("bridge", "proxy on mux bridge mode")
muxBridgeArgs.CertFile = muxBridge.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
muxBridgeArgs.KeyFile = muxBridge.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
muxBridgeArgs.Timeout = muxBridge.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
muxBridgeArgs.Local = muxBridge.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
muxBridgeArgs.LocalType = muxBridge.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tls").Short('t').Enum("tls", "tcp", "kcp")
//########tunnel-server#########
tunnelServer := app.Command("tserver", "proxy on tunnel server mode")
tunnelServerArgs.Parent = tunnelServer.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
tunnelServerArgs.CertFile = tunnelServer.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
tunnelServerArgs.KeyFile = tunnelServer.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
tunnelServerArgs.Timeout = tunnelServer.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
tunnelServerArgs.IsUDP = tunnelServer.Flag("udp", "proxy on udp tunnel server mode").Default("false").Bool()
tunnelServerArgs.Key = tunnelServer.Flag("k", "client key").Default("default").String()
tunnelServerArgs.Route = tunnelServer.Flag("route", "local route to client's network, such as: PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings()
//########tunnel-client#########
tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
tunnelClientArgs.Parent = tunnelClient.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
tunnelClientArgs.CertFile = tunnelClient.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
tunnelClientArgs.KeyFile = tunnelClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
tunnelClientArgs.Timeout = tunnelClient.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
tunnelClientArgs.Key = tunnelClient.Flag("k", "key same with server").Default("default").String()
//########tunnel-bridge#########
tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode")
tunnelBridgeArgs.CertFile = tunnelBridge.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
tunnelBridgeArgs.KeyFile = tunnelBridge.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
tunnelBridgeArgs.Timeout = tunnelBridge.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
tunnelBridgeArgs.Local = tunnelBridge.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
//########ssh#########
socks := app.Command("socks", "proxy on ssh mode")
socksArgs.Parent = socks.Flag("parent", "parent ssh address, such as: \"23.32.32.19:22\"").Default("").Short('P').String()
socksArgs.ParentType = socks.Flag("parent-type", "parent protocol type <tls|tcp|kcp|ssh>").Default("tcp").Short('T').Enum("tls", "tcp", "kcp", "ssh")
socksArgs.LocalType = socks.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
socksArgs.Local = socks.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
socksArgs.UDPParent = socks.Flag("udp-parent", "udp parent address, such as: \"23.32.32.19:33090\"").Default("").Short('X').String()
socksArgs.UDPLocal = socks.Flag("udp-local", "udp local ip:port to listen").Short('x').Default(":33090").String()
socksArgs.CertFile = socks.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
socksArgs.CaCertFile = socks.Flag("ca", "ca cert file for tls").Default("").String()
socksArgs.KeyFile = socks.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
socksArgs.SSHUser = socks.Flag("ssh-user", "user for ssh").Short('u').Default("").String()
socksArgs.SSHKeyFile = socks.Flag("ssh-key", "private key file for ssh").Short('S').Default("").String()
socksArgs.SSHKeyFileSalt = socks.Flag("ssh-keysalt", "salt of ssh private key").Short('s').Default("").String()
socksArgs.SSHPassword = socks.Flag("ssh-password", "password for ssh").Short('A').Default("").String()
socksArgs.Always = socks.Flag("always", "always use parent proxy").Default("false").Bool()
socksArgs.Timeout = socks.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Default("5000").Int()
socksArgs.Interval = socks.Flag("interval", "check domain if blocked every interval seconds").Default("10").Int()
socksArgs.Blocked = socks.Flag("blocked", "blocked domain file , one domain each line").Default("blocked").Short('b').String()
socksArgs.Direct = socks.Flag("direct", "direct domain file , one domain each line").Default("direct").Short('d').String()
socksArgs.AuthFile = socks.Flag("auth-file", "http basic auth file,\"username:password\" each line in file").Short('F').String()
socksArgs.Auth = socks.Flag("auth", "socks auth username and password, mutiple user repeat -a ,such as: -a user1:pass1 -a user2:pass2").Short('a').Strings()
socksArgs.LocalIPS = socks.Flag("local bind ips", "if your host behind a nat,set your public ip here avoid dead loop").Short('g').Strings()
socksArgs.AuthURL = socks.Flag("auth-url", "auth username and password will send to this url,response http code equal to 'auth-code' means ok,others means fail.").Default("").String()
socksArgs.AuthURLTimeout = socks.Flag("auth-timeout", "access 'auth-url' timeout milliseconds").Default("3000").Int()
socksArgs.AuthURLOkCode = socks.Flag("auth-code", "access 'auth-url' success http code").Default("204").Int()
socksArgs.AuthURLRetry = socks.Flag("auth-retry", "access 'auth-url' fail and retry count").Default("0").Int()
socksArgs.DNSAddress = socks.Flag("dns-address", "if set this, proxy will use this dns for resolve doamin").Short('q').Default("").String()
socksArgs.DNSTTL = socks.Flag("dns-ttl", "caching seconds of dns query result").Short('e').Default("300").Int()
//########socks+http(s)#########
sps := app.Command("sps", "proxy on socks+http(s) mode")
spsArgs.Parent = sps.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
spsArgs.CertFile = sps.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
spsArgs.KeyFile = sps.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
spsArgs.CaCertFile = sps.Flag("ca", "ca cert file for tls").Default("").String()
spsArgs.Timeout = sps.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('i').Default("2000").Int()
spsArgs.ParentType = sps.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Short('T').Enum("tls", "tcp", "kcp")
spsArgs.LocalType = sps.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
spsArgs.Local = sps.Flag("local", "local ip:port to listen,multiple address use comma split,such as: 0.0.0.0:80,0.0.0.0:443").Short('p').Default(":33080").String()
spsArgs.ParentServiceType = sps.Flag("parent-service-type", "parent service type <http|socks>").Short('S').Enum("http", "socks")
spsArgs.DNSAddress = sps.Flag("dns-address", "if set this, proxy will use this dns for resolve doamin").Short('q').Default("").String()
spsArgs.DNSTTL = sps.Flag("dns-ttl", "caching seconds of dns query result").Short('e').Default("300").Int()
spsArgs.AuthFile = sps.Flag("auth-file", "http basic auth file,\"username:password\" each line in file").Short('F').String()
spsArgs.Auth = sps.Flag("auth", "socks auth username and password, mutiple user repeat -a ,such as: -a user1:pass1 -a user2:pass2").Short('a').Strings()
spsArgs.LocalIPS = sps.Flag("local bind ips", "if your host behind a nat,set your public ip here avoid dead loop").Short('g').Strings()
spsArgs.AuthURL = sps.Flag("auth-url", "auth username and password will send to this url,response http code equal to 'auth-code' means ok,others means fail.").Default("").String()
spsArgs.AuthURLTimeout = sps.Flag("auth-timeout", "access 'auth-url' timeout milliseconds").Default("3000").Int()
spsArgs.AuthURLOkCode = sps.Flag("auth-code", "access 'auth-url' success http code").Default("204").Int()
spsArgs.AuthURLRetry = sps.Flag("auth-retry", "access 'auth-url' fail and retry count").Default("0").Int()
spsArgs.ParentAuth = sps.Flag("parent-auth", "parent socks auth username and password, such as: -A user1:pass1").Short('A').String()
//parse args
args := strings.Fields(strings.Trim(argsStr, " "))
serviceName, err := app.Parse(args)
if err != nil {
return fmt.Sprintf("parse args fail,err: %s", err)
}
//set kcp config
switch *kcpArgs.Mode {
case "normal":
*kcpArgs.NoDelay, *kcpArgs.Interval, *kcpArgs.Resend, *kcpArgs.NoCongestion = 0, 40, 2, 1
case "fast":
*kcpArgs.NoDelay, *kcpArgs.Interval, *kcpArgs.Resend, *kcpArgs.NoCongestion = 0, 30, 2, 1
case "fast2":
*kcpArgs.NoDelay, *kcpArgs.Interval, *kcpArgs.Resend, *kcpArgs.NoCongestion = 1, 20, 2, 1
case "fast3":
*kcpArgs.NoDelay, *kcpArgs.Interval, *kcpArgs.Resend, *kcpArgs.NoCongestion = 1, 10, 2, 1
}
pass := pbkdf2.Key([]byte(*kcpArgs.Key), []byte("snail007-goproxy"), 4096, 32, sha1.New)
switch *kcpArgs.Crypt {
case "sm4":
kcpArgs.Block, _ = kcp.NewSM4BlockCrypt(pass[:16])
case "tea":
kcpArgs.Block, _ = kcp.NewTEABlockCrypt(pass[:16])
case "xor":
kcpArgs.Block, _ = kcp.NewSimpleXORBlockCrypt(pass)
case "none":
kcpArgs.Block, _ = kcp.NewNoneBlockCrypt(pass)
case "aes-128":
kcpArgs.Block, _ = kcp.NewAESBlockCrypt(pass[:16])
case "aes-192":
kcpArgs.Block, _ = kcp.NewAESBlockCrypt(pass[:24])
case "blowfish":
kcpArgs.Block, _ = kcp.NewBlowfishBlockCrypt(pass)
case "twofish":
kcpArgs.Block, _ = kcp.NewTwofishBlockCrypt(pass)
case "cast5":
kcpArgs.Block, _ = kcp.NewCast5BlockCrypt(pass[:16])
case "3des":
kcpArgs.Block, _ = kcp.NewTripleDESBlockCrypt(pass[:24])
case "xtea":
kcpArgs.Block, _ = kcp.NewXTEABlockCrypt(pass[:16])
case "salsa20":
kcpArgs.Block, _ = kcp.NewSalsa20BlockCrypt(pass)
default:
*kcpArgs.Crypt = "aes"
kcpArgs.Block, _ = kcp.NewAESBlockCrypt(pass)
}
//attach kcp config
tcpArgs.KCP = kcpArgs
httpArgs.KCP = kcpArgs
socksArgs.KCP = kcpArgs
spsArgs.KCP = kcpArgs
muxBridgeArgs.KCP = kcpArgs
muxServerArgs.KCP = kcpArgs
muxClientArgs.KCP = kcpArgs
flags := log.Ldate
if *debug {
flags |= log.Lshortfile | log.Lmicroseconds
} else {
flags |= log.Ltime
}
log.SetFlags(flags)
if *logfile != "" {
f, e := os.OpenFile(*logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
if e != nil {
log.Fatal(e)
}
log.SetOutput(f)
}
//regist services and run service
services.Regist("http", services.NewHTTP(), httpArgs)
services.Regist("tcp", services.NewTCP(), tcpArgs)
services.Regist("udp", services.NewUDP(), udpArgs)
services.Regist("tserver", services.NewTunnelServerManager(), tunnelServerArgs)
services.Regist("tclient", services.NewTunnelClient(), tunnelClientArgs)
services.Regist("tbridge", services.NewTunnelBridge(), tunnelBridgeArgs)
services.Regist("server", services.NewMuxServerManager(), muxServerArgs)
services.Regist("client", services.NewMuxClient(), muxClientArgs)
services.Regist("bridge", services.NewMuxBridge(), muxBridgeArgs)
services.Regist("socks", services.NewSocks(), socksArgs)
services.Regist("sps", services.NewSPS(), spsArgs)
service, err = services.Run(serviceName)
if err != nil {
return fmt.Sprintf("run service [%s] fail, ERR:%s", serviceName, err)
}
return
}
func Stop() {
if service != nil && service.S != nil {
service.S.Clean()
}
}

View File

@ -34,26 +34,32 @@ func NewHTTP() Service {
lockChn: make(chan bool, 1),
}
}
func (s *HTTP) CheckArgs() {
var err error
func (s *HTTP) CheckArgs() (err error) {
if *s.cfg.Parent != "" && *s.cfg.ParentType == "" {
log.Fatalf("parent type unkown,use -T <tls|tcp|ssh|kcp>")
err = fmt.Errorf("parent type unkown,use -T <tls|tcp|ssh|kcp>")
return
}
if *s.cfg.ParentType == "tls" || *s.cfg.LocalType == "tls" {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if err != nil {
return
}
if *s.cfg.CaCertFile != "" {
s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile)
if err != nil {
log.Fatalf("read ca file error,ERR:%s", err)
err = fmt.Errorf("read ca file error,ERR:%s", err)
return
}
}
}
if *s.cfg.ParentType == "ssh" {
if *s.cfg.SSHUser == "" {
log.Fatalf("ssh user required")
err = fmt.Errorf("ssh user required")
return
}
if *s.cfg.SSHKeyFile == "" && *s.cfg.SSHPassword == "" {
log.Fatalf("ssh password or key required")
err = fmt.Errorf("ssh password or key required")
return
}
if *s.cfg.SSHPassword != "" {
@ -62,7 +68,8 @@ func (s *HTTP) CheckArgs() {
var SSHSigner ssh.Signer
s.cfg.SSHKeyBytes, err = ioutil.ReadFile(*s.cfg.SSHKeyFile)
if err != nil {
log.Fatalf("read key file ERR: %s", err)
err = fmt.Errorf("read key file ERR: %s", err)
return
}
if *s.cfg.SSHKeyFileSalt != "" {
SSHSigner, err = ssh.ParsePrivateKeyWithPassphrase(s.cfg.SSHKeyBytes, []byte(*s.cfg.SSHKeyFileSalt))
@ -70,13 +77,15 @@ func (s *HTTP) CheckArgs() {
SSHSigner, err = ssh.ParsePrivateKey(s.cfg.SSHKeyBytes)
}
if err != nil {
log.Fatalf("parse ssh private key fail,ERR: %s", err)
err = fmt.Errorf("parse ssh private key fail,ERR: %s", err)
return
}
s.cfg.SSHAuthMethod = ssh.PublicKeys(SSHSigner)
}
}
return
}
func (s *HTTP) InitService() {
func (s *HTTP) InitService() (err error) {
s.InitBasicAuth()
if *s.cfg.Parent != "" {
s.checker = utils.NewChecker(*s.cfg.HTTPTimeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct)
@ -85,9 +94,10 @@ func (s *HTTP) InitService() {
(*s).domainResolver = utils.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL)
}
if *s.cfg.ParentType == "ssh" {
err := s.ConnectSSH()
err = s.ConnectSSH()
if err != nil {
log.Fatalf("init service fail, ERR: %s", err)
err = fmt.Errorf("init service fail, ERR: %s", err)
return
}
go func() {
//循环检查ssh网络连通性
@ -114,6 +124,7 @@ func (s *HTTP) InitService() {
}
}()
}
return
}
func (s *HTTP) StopService() {
if s.outPool.Pool != nil {
@ -122,12 +133,16 @@ func (s *HTTP) StopService() {
}
func (s *HTTP) Start(args interface{}) (err error) {
s.cfg = args.(HTTPArgs)
s.CheckArgs()
if err = s.CheckArgs(); err != nil {
return
}
if *s.cfg.Parent != "" {
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
s.InitOutConnPool()
}
s.InitService()
if err = s.InitService(); err != nil {
return
}
for _, addr := range strings.Split(*s.cfg.Local, ",") {
if addr != "" {
host, port, _ := net.SplitHostPort(addr)

View File

@ -2,6 +2,7 @@ package services
import (
"bufio"
"fmt"
"io"
"log"
"math/rand"
@ -32,24 +33,34 @@ func NewMuxBridge() Service {
return b
}
func (s *MuxBridge) InitService() {
func (s *MuxBridge) InitService() (err error) {
return
}
func (s *MuxBridge) CheckArgs() {
func (s *MuxBridge) CheckArgs() (err error) {
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
log.Fatalf("cert and key file required")
err = fmt.Errorf("cert and key file required")
return
}
if *s.cfg.LocalType == TYPE_TLS {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if err != nil {
return
}
}
return
}
func (s *MuxBridge) StopService() {
}
func (s *MuxBridge) Start(args interface{}) (err error) {
s.cfg = args.(MuxBridgeArgs)
s.CheckArgs()
s.InitService()
if err = s.CheckArgs(); err != nil {
return
}
if err = s.InitService(); err != nil {
return
}
host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p)

View File

@ -23,30 +23,40 @@ func NewMuxClient() Service {
}
}
func (s *MuxClient) InitService() {
func (s *MuxClient) InitService() (err error) {
return
}
func (s *MuxClient) CheckArgs() {
func (s *MuxClient) CheckArgs() (err error) {
if *s.cfg.Parent != "" {
log.Printf("use tls parent %s", *s.cfg.Parent)
} else {
log.Fatalf("parent required")
err = fmt.Errorf("parent required")
return
}
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
log.Fatalf("cert and key file required")
err = fmt.Errorf("cert and key file required")
return
}
if *s.cfg.ParentType == "tls" {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if err != nil {
return
}
}
return
}
func (s *MuxClient) StopService() {
}
func (s *MuxClient) Start(args interface{}) (err error) {
s.cfg = args.(MuxClientArgs)
s.CheckArgs()
s.InitService()
if err = s.CheckArgs(); err != nil {
return
}
if err = s.InitService(); err != nil {
return
}
log.Printf("client started")
count := 1
if *s.cfg.SessionCount > 0 {
@ -119,7 +129,6 @@ func (s *MuxClient) Start(args interface{}) (err error) {
}()
}
}
}(i)
}
return

View File

@ -41,14 +41,19 @@ func NewMuxServerManager() Service {
}
func (s *MuxServerManager) Start(args interface{}) (err error) {
s.cfg = args.(MuxServerArgs)
s.CheckArgs()
if err = s.CheckArgs(); err != nil {
return
}
if *s.cfg.Parent != "" {
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
} else {
log.Fatalf("parent required")
err = fmt.Errorf("parent required")
return
}
s.InitService()
if err = s.InitService(); err != nil {
return
}
log.Printf("server id: %s", s.serverID)
//log.Printf("route:%v", *s.cfg.Route)
@ -103,15 +108,21 @@ func (s *MuxServerManager) Clean() {
}
func (s *MuxServerManager) StopService() {
}
func (s *MuxServerManager) CheckArgs() {
func (s *MuxServerManager) CheckArgs() (err error) {
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
log.Fatalf("cert and key file required")
err = fmt.Errorf("cert and key file required")
return
}
if *s.cfg.ParentType == "tls" {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if err != nil {
return
}
}
func (s *MuxServerManager) InitService() {
return
}
func (s *MuxServerManager) InitService() (err error) {
return
}
func NewMuxServer() Service {
@ -129,19 +140,26 @@ type MuxUDPItem struct {
srcAddr *net.UDPAddr
}
func (s *MuxServer) InitService() {
func (s *MuxServer) InitService() (err error) {
s.UDPConnDeamon()
return
}
func (s *MuxServer) CheckArgs() {
func (s *MuxServer) CheckArgs() (err error) {
if *s.cfg.Remote == "" {
log.Fatalf("remote required")
err = fmt.Errorf("remote required")
return
}
return
}
func (s *MuxServer) Start(args interface{}) (err error) {
s.cfg = args.(MuxServerArgs)
s.CheckArgs()
s.InitService()
if err = s.CheckArgs(); err != nil {
return
}
if err = s.InitService(); err != nil {
return
}
host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port)
s.sc = utils.NewServerChannel(host, p)

View File

@ -2,7 +2,6 @@ package services
import (
"fmt"
"log"
"runtime/debug"
)
@ -28,11 +27,10 @@ func Regist(name string, s Service, args interface{}) {
func Run(name string, args ...interface{}) (service *ServiceItem, err error) {
service, ok := servicesMap[name]
if ok {
go func() {
defer func() {
err := recover()
if err != nil {
log.Fatalf("%s servcie crashed, ERR: %s\ntrace:%s", name, err, string(debug.Stack()))
e := recover()
if e != nil {
err = fmt.Errorf("%s servcie crashed, ERR: %s\ntrace:%s", name, e, string(debug.Stack()))
}
}()
if len(args) == 1 {
@ -41,11 +39,9 @@ func Run(name string, args ...interface{}) (service *ServiceItem, err error) {
err = service.S.Start(service.Args)
}
if err != nil {
log.Fatalf("%s servcie fail, ERR: %s", name, err)
err = fmt.Errorf("%s servcie fail, ERR: %s", name, err)
}
}()
}
if !ok {
} else {
err = fmt.Errorf("service %s not found", name)
}
return

View File

@ -35,36 +35,34 @@ func NewSocks() Service {
}
}
func (s *Socks) CheckArgs() {
var err error
func (s *Socks) CheckArgs() (err error) {
if *s.cfg.LocalType == "tls" || (*s.cfg.Parent != "" && *s.cfg.ParentType == "tls") {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if err != nil {
return
}
if *s.cfg.CaCertFile != "" {
s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile)
if err != nil {
log.Fatalf("read ca file error,ERR:%s", err)
err = fmt.Errorf("read ca file error,ERR:%s", err)
return
}
}
}
if *s.cfg.Parent != "" {
if *s.cfg.ParentType == "" {
log.Fatalf("parent type unkown,use -T <tls|tcp|ssh|kcp>")
err = fmt.Errorf("parent type unkown,use -T <tls|tcp|ssh|kcp>")
return
}
// if *s.cfg.ParentType == "tls" {
// s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
// if *s.cfg.CaCertFile != "" {
// s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile)
// if err != nil {
// log.Fatalf("read ca file error,ERR:%s", err)
// }
// }
// }
if *s.cfg.ParentType == "ssh" {
if *s.cfg.SSHUser == "" {
log.Fatalf("ssh user required")
err = fmt.Errorf("ssh user required")
return
}
if *s.cfg.SSHKeyFile == "" && *s.cfg.SSHPassword == "" {
log.Fatalf("ssh password or key required")
err = fmt.Errorf("ssh password or key required")
return
}
if *s.cfg.SSHPassword != "" {
s.cfg.SSHAuthMethod = ssh.Password(*s.cfg.SSHPassword)
@ -72,7 +70,8 @@ func (s *Socks) CheckArgs() {
var SSHSigner ssh.Signer
s.cfg.SSHKeyBytes, err = ioutil.ReadFile(*s.cfg.SSHKeyFile)
if err != nil {
log.Fatalf("read key file ERR: %s", err)
err = fmt.Errorf("read key file ERR: %s", err)
return
}
if *s.cfg.SSHKeyFileSalt != "" {
SSHSigner, err = ssh.ParsePrivateKeyWithPassphrase(s.cfg.SSHKeyBytes, []byte(*s.cfg.SSHKeyFileSalt))
@ -80,24 +79,26 @@ func (s *Socks) CheckArgs() {
SSHSigner, err = ssh.ParsePrivateKey(s.cfg.SSHKeyBytes)
}
if err != nil {
log.Fatalf("parse ssh private key fail,ERR: %s", err)
err = fmt.Errorf("parse ssh private key fail,ERR: %s", err)
return
}
s.cfg.SSHAuthMethod = ssh.PublicKeys(SSHSigner)
}
}
}
return
}
func (s *Socks) InitService() {
func (s *Socks) InitService() (err error) {
s.InitBasicAuth()
if *s.cfg.DNSAddress != "" {
(*s).domainResolver = utils.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL)
}
s.checker = utils.NewChecker(*s.cfg.Timeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct)
if *s.cfg.ParentType == "ssh" {
err := s.ConnectSSH()
if err != nil {
log.Fatalf("init service fail, ERR: %s", err)
e := s.ConnectSSH()
if e != nil {
err = fmt.Errorf("init service fail, ERR: %s", e)
return
}
go func() {
//循环检查ssh网络连通性
@ -125,12 +126,14 @@ func (s *Socks) InitService() {
log.Println("warn: socks udp not suppored for ssh")
} else {
s.udpSC = utils.NewServerChannelHost(*s.cfg.UDPLocal)
err := s.udpSC.ListenUDP(s.udpCallback)
if err != nil {
log.Fatalf("init udp service fail, ERR: %s", err)
e := s.udpSC.ListenUDP(s.udpCallback)
if e != nil {
err = fmt.Errorf("init udp service fail, ERR: %s", e)
return
}
log.Printf("udp socks proxy on %s", s.udpSC.UDPListener.LocalAddr())
}
return
}
func (s *Socks) StopService() {
if s.sshClient != nil {
@ -143,8 +146,12 @@ func (s *Socks) StopService() {
func (s *Socks) Start(args interface{}) (err error) {
//start()
s.cfg = args.(SocksArgs)
s.CheckArgs()
if err = s.CheckArgs(); err != nil {
return
}
if err = s.InitService(); err != nil {
s.InitService()
}
if *s.cfg.Parent != "" {
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
}

View File

@ -30,30 +30,37 @@ func NewSPS() Service {
basicAuth: utils.BasicAuth{},
}
}
func (s *SPS) CheckArgs() {
func (s *SPS) CheckArgs() (err error) {
if *s.cfg.Parent == "" {
log.Fatalf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local)
err = fmt.Errorf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local)
return
}
if *s.cfg.ParentType == "" {
log.Fatalf("parent type unkown,use -T <tls|tcp|kcp>")
err = fmt.Errorf("parent type unkown,use -T <tls|tcp|kcp>")
return
}
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.LocalType == TYPE_TLS {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if err != nil {
return
}
if *s.cfg.CaCertFile != "" {
var err error
s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile)
if err != nil {
log.Fatalf("read ca file error,ERR:%s", err)
err = fmt.Errorf("read ca file error,ERR:%s", err)
return
}
}
}
return
}
func (s *SPS) InitService() {
func (s *SPS) InitService() (err error) {
s.InitOutConnPool()
if *s.cfg.DNSAddress != "" {
(*s).domainResolver = utils.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL)
}
s.InitBasicAuth()
err = s.InitBasicAuth()
return
}
func (s *SPS) InitOutConnPool() {
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP || *s.cfg.ParentType == TYPE_KCP {
@ -79,10 +86,13 @@ func (s *SPS) StopService() {
}
func (s *SPS) Start(args interface{}) (err error) {
s.cfg = args.(SPSArgs)
s.CheckArgs()
if err = s.CheckArgs(); err != nil {
return
}
if err = s.InitService(); err != nil {
return
}
log.Printf("use %s %s parent %s", *s.cfg.ParentType, *s.cfg.ParentServiceType, *s.cfg.Parent)
s.InitService()
for _, addr := range strings.Split(*s.cfg.Local, ",") {
if addr != "" {
host, port, _ := net.SplitHostPort(*s.cfg.Local)

View File

@ -24,19 +24,26 @@ func NewTCP() Service {
cfg: TCPArgs{},
}
}
func (s *TCP) CheckArgs() {
func (s *TCP) CheckArgs() (err error) {
if *s.cfg.Parent == "" {
log.Fatalf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local)
err = fmt.Errorf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local)
return
}
if *s.cfg.ParentType == "" {
log.Fatalf("parent type unkown,use -T <tls|tcp|kcp|udp>")
err = fmt.Errorf("parent type unkown,use -T <tls|tcp|kcp|udp>")
return
}
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.LocalType == TYPE_TLS {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if err != nil {
return
}
}
func (s *TCP) InitService() {
return
}
func (s *TCP) InitService() (err error) {
s.InitOutConnPool()
return
}
func (s *TCP) StopService() {
if s.outPool.Pool != nil {
@ -45,10 +52,13 @@ func (s *TCP) StopService() {
}
func (s *TCP) Start(args interface{}) (err error) {
s.cfg = args.(TCPArgs)
s.CheckArgs()
if err = s.CheckArgs(); err != nil {
return
}
if err = s.InitService(); err != nil {
return
}
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
s.InitService()
host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p)

View File

@ -2,6 +2,7 @@ package services
import (
"bufio"
"fmt"
"log"
"net"
"snail007/proxy/utils"
@ -31,22 +32,28 @@ func NewTunnelBridge() Service {
}
}
func (s *TunnelBridge) InitService() {
func (s *TunnelBridge) InitService() (err error) {
return
}
func (s *TunnelBridge) CheckArgs() {
func (s *TunnelBridge) CheckArgs() (err error) {
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
log.Fatalf("cert and key file required")
err = fmt.Errorf("cert and key file required")
return
}
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
return
}
func (s *TunnelBridge) StopService() {
}
func (s *TunnelBridge) Start(args interface{}) (err error) {
s.cfg = args.(TunnelBridgeArgs)
s.CheckArgs()
s.InitService()
if err = s.CheckArgs(); err != nil {
return
}
if err = s.InitService(); err != nil {
return
}
host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p)
@ -135,102 +142,6 @@ func (s *TunnelBridge) Start(args interface{}) (err error) {
}
s.clientControlConns.Set(key, &inConn)
log.Printf("set client %s control conn", key)
// case CONN_SERVER_HEARBEAT:
// var serverID string
// err = utils.ReadPacketData(reader, &serverID)
// if err != nil {
// log.Printf("read error,ERR:%s", err)
// return
// }
// log.Printf("server heartbeat connection, id: %s", serverID)
// writeDie := make(chan bool)
// readDie := make(chan bool)
// go func() {
// for {
// inConn.SetWriteDeadline(time.Now().Add(time.Second * 3))
// _, err = inConn.Write([]byte{0x00})
// inConn.SetWriteDeadline(time.Time{})
// if err != nil {
// log.Printf("server heartbeat connection write err %s", err)
// break
// }
// time.Sleep(time.Second * 3)
// }
// close(writeDie)
// }()
// go func() {
// for {
// signal := make([]byte, 1)
// inConn.SetReadDeadline(time.Now().Add(time.Second * 6))
// _, err := inConn.Read(signal)
// inConn.SetReadDeadline(time.Time{})
// if err != nil {
// log.Printf("server heartbeat connection read err: %s", err)
// break
// } else {
// // log.Printf("heartbeat from server ,id:%s", serverID)
// }
// }
// close(readDie)
// }()
// select {
// case <-readDie:
// case <-writeDie:
// }
// utils.CloseConn(&inConn)
// s.cmServer.Remove(serverID)
// log.Printf("server heartbeat conn %s released", serverID)
// case CONN_CLIENT_HEARBEAT:
// var clientID string
// err = utils.ReadPacketData(reader, &clientID)
// if err != nil {
// log.Printf("read error,ERR:%s", err)
// return
// }
// log.Printf("client heartbeat connection, id: %s", clientID)
// writeDie := make(chan bool)
// readDie := make(chan bool)
// go func() {
// for {
// inConn.SetWriteDeadline(time.Now().Add(time.Second * 3))
// _, err = inConn.Write([]byte{0x00})
// inConn.SetWriteDeadline(time.Time{})
// if err != nil {
// log.Printf("client heartbeat connection write err %s", err)
// break
// }
// time.Sleep(time.Second * 3)
// }
// close(writeDie)
// }()
// go func() {
// for {
// signal := make([]byte, 1)
// inConn.SetReadDeadline(time.Now().Add(time.Second * 6))
// _, err := inConn.Read(signal)
// inConn.SetReadDeadline(time.Time{})
// if err != nil {
// log.Printf("client control connection read err: %s", err)
// break
// } else {
// // log.Printf("heartbeat from client ,id:%s", clientID)
// }
// }
// close(readDie)
// }()
// select {
// case <-readDie:
// case <-writeDie:
// }
// utils.CloseConn(&inConn)
// s.cmClient.Remove(clientID)
// if s.clientControlConns.Has(clientID) {
// item, _ := s.clientControlConns.Get(clientID)
// (*item.(*net.Conn)).Close()
// }
// s.clientControlConns.Remove(clientID)
// log.Printf("client heartbeat conn %s released", clientID)
}
})
if err != nil {

View File

@ -23,86 +23,35 @@ func NewTunnelClient() Service {
}
}
func (s *TunnelClient) InitService() {
// s.InitHeartbeatDeamon()
func (s *TunnelClient) InitService() (err error) {
return
}
// func (s *TunnelClient) InitHeartbeatDeamon() {
// log.Printf("heartbeat started")
// go func() {
// var heartbeatConn net.Conn
// var ID = *s.cfg.Key
// for {
// //close all connection
// s.cm.RemoveAll()
// if s.ctrlConn != nil {
// s.ctrlConn.Close()
// }
// utils.CloseConn(&heartbeatConn)
// heartbeatConn, err := s.GetInConn(CONN_CLIENT_HEARBEAT, ID)
// if err != nil {
// log.Printf("heartbeat connection err: %s, retrying...", err)
// time.Sleep(time.Second * 3)
// utils.CloseConn(&heartbeatConn)
// continue
// }
// log.Printf("heartbeat connection created,id:%s", ID)
// writeDie := make(chan bool)
// readDie := make(chan bool)
// go func() {
// for {
// heartbeatConn.SetWriteDeadline(time.Now().Add(time.Second * 3))
// _, err = heartbeatConn.Write([]byte{0x00})
// heartbeatConn.SetWriteDeadline(time.Time{})
// if err != nil {
// log.Printf("heartbeat connection write err %s", err)
// break
// }
// time.Sleep(time.Second * 3)
// }
// close(writeDie)
// }()
// go func() {
// for {
// signal := make([]byte, 1)
// heartbeatConn.SetReadDeadline(time.Now().Add(time.Second * 6))
// _, err := heartbeatConn.Read(signal)
// heartbeatConn.SetReadDeadline(time.Time{})
// if err != nil {
// log.Printf("heartbeat connection read err: %s", err)
// break
// } else {
// //log.Printf("heartbeat from bridge")
// }
// }
// close(readDie)
// }()
// select {
// case <-readDie:
// case <-writeDie:
// }
// }
// }()
// }
func (s *TunnelClient) CheckArgs() {
func (s *TunnelClient) CheckArgs() (err error) {
if *s.cfg.Parent != "" {
log.Printf("use tls parent %s", *s.cfg.Parent)
} else {
log.Fatalf("parent required")
err = fmt.Errorf("parent required")
return
}
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
log.Fatalf("cert and key file required")
err = fmt.Errorf("cert and key file required")
return
}
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
return
}
func (s *TunnelClient) StopService() {
// s.cm.RemoveAll()
}
func (s *TunnelClient) Start(args interface{}) (err error) {
s.cfg = args.(TunnelClientArgs)
s.CheckArgs()
s.InitService()
if err = s.CheckArgs(); err != nil {
return
}
if err = s.InitService(); err != nil {
return
}
log.Printf("proxy on tunnel client mode")
for {

View File

@ -37,14 +37,19 @@ func NewTunnelServerManager() Service {
}
func (s *TunnelServerManager) Start(args interface{}) (err error) {
s.cfg = args.(TunnelServerArgs)
s.CheckArgs()
if err = s.CheckArgs(); err != nil {
return
}
if *s.cfg.Parent != "" {
log.Printf("use tls parent %s", *s.cfg.Parent)
} else {
log.Fatalf("parent required")
err = fmt.Errorf("parent required")
return
}
s.InitService()
if err = s.InitService(); err != nil {
return
}
log.Printf("server id: %s", s.serverID)
//log.Printf("route:%v", *s.cfg.Route)
@ -93,70 +98,18 @@ func (s *TunnelServerManager) Clean() {
func (s *TunnelServerManager) StopService() {
// s.cm.RemoveAll()
}
func (s *TunnelServerManager) CheckArgs() {
func (s *TunnelServerManager) CheckArgs() (err error) {
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
log.Fatalf("cert and key file required")
err = fmt.Errorf("cert and key file required")
return
}
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
return
}
func (s *TunnelServerManager) InitService() {
// s.InitHeartbeatDeamon()
func (s *TunnelServerManager) InitService() (err error) {
return
}
// func (s *TunnelServerManager) InitHeartbeatDeamon() {
// log.Printf("heartbeat started")
// go func() {
// var heartbeatConn net.Conn
// var ID string
// for {
// //close all connection
// s.cm.Remove(ID)
// utils.CloseConn(&heartbeatConn)
// heartbeatConn, ID, err := s.GetOutConn(CONN_SERVER_HEARBEAT)
// if err != nil {
// log.Printf("heartbeat connection err: %s, retrying...", err)
// time.Sleep(time.Second * 3)
// utils.CloseConn(&heartbeatConn)
// continue
// }
// log.Printf("heartbeat connection created,id:%s", ID)
// writeDie := make(chan bool)
// readDie := make(chan bool)
// go func() {
// for {
// heartbeatConn.SetWriteDeadline(time.Now().Add(time.Second * 3))
// _, err = heartbeatConn.Write([]byte{0x00})
// heartbeatConn.SetWriteDeadline(time.Time{})
// if err != nil {
// log.Printf("heartbeat connection write err %s", err)
// break
// }
// time.Sleep(time.Second * 3)
// }
// close(writeDie)
// }()
// go func() {
// for {
// signal := make([]byte, 1)
// heartbeatConn.SetReadDeadline(time.Now().Add(time.Second * 6))
// _, err := heartbeatConn.Read(signal)
// heartbeatConn.SetReadDeadline(time.Time{})
// if err != nil {
// log.Printf("heartbeat connection read err: %s", err)
// break
// } else {
// // log.Printf("heartbeat from bridge")
// }
// }
// close(readDie)
// }()
// select {
// case <-readDie:
// case <-writeDie:
// }
// }
// }()
// }
func (s *TunnelServerManager) GetOutConn(typ uint8) (outConn net.Conn, ID string, err error) {
outConn, err = s.GetConn()
if err != nil {
@ -193,19 +146,26 @@ type UDPItem struct {
srcAddr *net.UDPAddr
}
func (s *TunnelServer) InitService() {
func (s *TunnelServer) InitService() (err error) {
s.UDPConnDeamon()
return
}
func (s *TunnelServer) CheckArgs() {
func (s *TunnelServer) CheckArgs() (err error) {
if *s.cfg.Remote == "" {
log.Fatalf("remote required")
err = fmt.Errorf("remote required")
return
}
return
}
func (s *TunnelServer) Start(args interface{}) (err error) {
s.cfg = args.(TunnelServerArgs)
s.CheckArgs()
s.InitService()
if err = s.CheckArgs(); err != nil {
return
}
if err = s.InitService(); err != nil {
return
}
host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port)
s.sc = utils.NewServerChannel(host, p)

View File

@ -28,21 +28,28 @@ func NewUDP() Service {
p: utils.NewConcurrentMap(),
}
}
func (s *UDP) CheckArgs() {
func (s *UDP) CheckArgs() (err error) {
if *s.cfg.Parent == "" {
log.Fatalf("parent required for udp %s", *s.cfg.Local)
err = fmt.Errorf("parent required for udp %s", *s.cfg.Local)
return
}
if *s.cfg.ParentType == "" {
log.Fatalf("parent type unkown,use -T <tls|tcp>")
err = fmt.Errorf("parent type unkown,use -T <tls|tcp>")
return
}
if *s.cfg.ParentType == "tls" {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if err != nil {
return
}
}
func (s *UDP) InitService() {
return
}
func (s *UDP) InitService() (err error) {
if *s.cfg.ParentType != TYPE_UDP {
s.InitOutConnPool()
}
return
}
func (s *UDP) StopService() {
if s.outPool.Pool != nil {
@ -51,10 +58,13 @@ func (s *UDP) StopService() {
}
func (s *UDP) Start(args interface{}) (err error) {
s.cfg = args.(UDPArgs)
s.CheckArgs()
if err = s.CheckArgs(); err != nil {
return
}
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
s.InitService()
if err = s.InitService(); err != nil {
return
}
host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p)

View File

@ -524,15 +524,15 @@ func SubBytes(bytes []byte, start, end int) []byte {
}
return bytes[start:end]
}
func TlsBytes(cert, key string) (certBytes, keyBytes []byte) {
certBytes, err := ioutil.ReadFile(cert)
func TlsBytes(cert, key string) (certBytes, keyBytes []byte, err error) {
certBytes, err = ioutil.ReadFile(cert)
if err != nil {
log.Fatalf("err : %s", err)
err = fmt.Errorf("err : %s", err)
return
}
keyBytes, err = ioutil.ReadFile(key)
if err != nil {
log.Fatalf("err : %s", err)
err = fmt.Errorf("err : %s", err)
return
}
return