From 726240e66957e48ea2094dea65f51a7897b2a6fa Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Thu, 28 Jun 2018 16:02:40 +0800 Subject: [PATCH] v5.1 Signed-off-by: arraykeys@gmail.com --- CHANGELOG | 1 + README_ZH.md | 16 +++++-- config.go | 25 ++++++----- release.sh | 2 +- sdk/android-ios/sdk.go | 2 +- services/http/http.go | 2 +- services/keygen/keygen.go | 71 ++++++++++++++++++++++++++++++++ services/socks/socks.go | 2 +- services/sps/sps.go | 2 +- services/tcp/tcp.go | 2 +- services/tunnel/tunnel_bridge.go | 2 +- services/tunnel/tunnel_client.go | 2 +- services/tunnel/tunnel_server.go | 2 +- services/udp/udp.go | 2 +- 14 files changed, 108 insertions(+), 25 deletions(-) create mode 100644 services/keygen/keygen.go diff --git a/CHANGELOG b/CHANGELOG index 9902d8c..a241863 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,7 @@ v5.1 2.优化了HTTP(S)\SOCKS5代理智能判断,更加精确。 3.fix #97 , 修复了RemoveProxyHeaders方法忽略了第一行的bug。 4.修复了-g参数长格式没有连接符号的bug. +5.重构了证书生成功能,不再有任何外部依赖,任何平台都可以独立生成证书. v5.0 1.修复了SPS多端口无效的bug. diff --git a/README_ZH.md b/README_ZH.md index 03224fc..07b2ebc 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -217,10 +217,18 @@ http ### **生成加密通讯需要的证书文件** http,tcp,udp代理过程会和上级通讯,为了安全我们采用加密通讯,当然可以选择不加密通信通讯,本教程所有和上级通讯都采用加密,需要证书文件. -在linux上并安装了openssl命令,可以直接通过下面的命令生成证书和key文件. -`./proxy keygen` -默认会在当前程序目录下面生成证书文件proxy.crt和key文件proxy.key。 -更多用法:`proxy keygen usage`。 + +1.通过下面的命令生成自签名的证书和key文件. +`./proxy keygen -C proxy` +会在当前程序目录下面生成证书文件proxy.crt和key文件proxy.key。 + +2.通过下面的命令生,使用自签名证书proxy.crt和key文件proxy.key签发新证书:goproxy.crt和goproxy.key. +`./proxy keygen -s -C proxy -c goproxy` +会在当前程序目录下面生成证书文件goproxy.crt和key文件goproxy.key。 + +3.默认情况下证书的里面的域名是随机的,可以使用`-n test.com`参数指定. + +4.更多用法:`proxy keygen --help`。 ### **后台运行** 默认执行proxy之后,如果要保持proxy运行,不能关闭命令行. diff --git a/config.go b/config.go index 149306d..cd3a64b 100755 --- a/config.go +++ b/config.go @@ -15,9 +15,9 @@ import ( sdk "github.com/snail007/goproxy/sdk/android-ios" "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/services/kcpcfg" - "github.com/snail007/goproxy/utils" httpx "github.com/snail007/goproxy/services/http" + keygenx "github.com/snail007/goproxy/services/keygen" mux "github.com/snail007/goproxy/services/mux" socksx "github.com/snail007/goproxy/services/socks" spsx "github.com/snail007/goproxy/services/sps" @@ -39,14 +39,6 @@ var ( ) func initConfig() (err error) { - //keygen - if len(os.Args) > 1 { - if os.Args[1] == "keygen" { - utils.Keygen() - os.Exit(0) - } - } - //define args tcpArgs := tcpx.TCPArgs{} httpArgs := httpx.HTTPArgs{} @@ -60,6 +52,7 @@ func initConfig() (err error) { socksArgs := socksx.SocksArgs{} spsArgs := spsx.SPSArgs{} dnsArgs := sdk.DNSArgs{} + keygenArgs := keygenx.KeygenArgs{} kcpArgs := kcpcfg.KCPConfigArgs{} //build srvice args @@ -109,7 +102,7 @@ func initConfig() (err error) { 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.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() @@ -221,7 +214,7 @@ func initConfig() (err error) { 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.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() @@ -279,6 +272,14 @@ func initConfig() (err error) { dnsArgs.CacheFile = dns.Flag("cache-file", "dns result cached file").Short('f').Default(filepath.Join(path.Dir(os.Args[0]), "cache.dat")).String() dnsArgs.LocalSocks5Port = dns.Flag("socks-port", "local socks5 port").Short('s').Default("65501").String() + //########tunnel-bridge######### + keygen := app.Command("keygen", "create certificate for proxy") + keygenArgs.CommonName = keygen.Flag("cn", "common name").Short('n').Default("").String() + keygenArgs.CaName = keygen.Flag("ca", "ca name").Short('C').Default("").String() + keygenArgs.CertName = keygen.Flag("cert", "cert name of sign to create").Short('c').Default("").String() + keygenArgs.SignDays = keygen.Flag("days", "days of sign").Short('d').Default("365").Int() + keygenArgs.Sign = keygen.Flag("sign", "cert is to signin").Short('s').Default("false").Bool() + //parse args serviceName := kingpin.MustParse(app.Parse(os.Args[1:])) @@ -464,6 +465,8 @@ func initConfig() (err error) { services.Regist(serviceName, spsx.NewSPS(), spsArgs, log) case "dns": services.Regist(serviceName, sdk.NewDNS(), dnsArgs, log) + case "keygen": + services.Regist(serviceName, keygenx.NewKeygen(), keygenArgs, log) } service, err = services.Run(serviceName, nil) diff --git a/release.sh b/release.sh index 4170eff..2c505c5 100755 --- a/release.sh +++ b/release.sh @@ -5,7 +5,7 @@ rm -rf .cert mkdir .cert go build -o proxy cd .cert -../proxy keygen +../proxy keygen -C proxy cd .. rm -rf ${RELEASE} mkdir ${RELEASE} diff --git a/sdk/android-ios/sdk.go b/sdk/android-ios/sdk.go index 0913a51..1033d62 100644 --- a/sdk/android-ios/sdk.go +++ b/sdk/android-ios/sdk.go @@ -210,7 +210,7 @@ func Start(serviceID, serviceArgsStr string) (errStr 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.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() diff --git a/services/http/http.go b/services/http/http.go index bc8d1e1..16d41a3 100644 --- a/services/http/http.go +++ b/services/http/http.go @@ -1,4 +1,4 @@ -package services +package http import ( "fmt" diff --git a/services/keygen/keygen.go b/services/keygen/keygen.go new file mode 100644 index 0000000..ed6e04b --- /dev/null +++ b/services/keygen/keygen.go @@ -0,0 +1,71 @@ +package keygen + +import ( + "fmt" + logger "log" + "os" + "strings" + + "github.com/snail007/goproxy/services" + "github.com/snail007/goproxy/utils/cert" + "src/github.com/snail007/goproxy/utils" +) + +type KeygenArgs struct { + CaName *string + CertName *string + Sign *bool + SignDays *int + CommonName *string +} + +type Keygen struct { + cfg KeygenArgs + log *logger.Logger +} + +func NewKeygen() services.Service { + return &Keygen{} +} +func (s *Keygen) CheckArgs() (err error) { + if *s.cfg.Sign && (*s.cfg.CertName == "" || *s.cfg.CaName == "") { + err = fmt.Errorf("ca name and cert name required for signin") + return + } + if !*s.cfg.Sign && *s.cfg.CaName == "" { + err = fmt.Errorf("ca name required") + return + } + if *s.cfg.CommonName == "" { + domainSubfixList := []string{".com", ".edu", ".gov", ".int", ".mil", ".net", ".org", ".biz", ".info", ".pro", ".name", ".museum", ".coop", ".aero", ".xxx", ".idv", ".ac", ".ad", ".ae", ".af", ".ag", ".ai", ".al", ".am", ".an", ".ao", ".aq", ".ar", ".as", ".at", ".au", ".aw", ".az", ".ba", ".bb", ".bd", ".be", ".bf", ".bg", ".bh", ".bi", ".bj", ".bm", ".bn", ".bo", ".br", ".bs", ".bt", ".bv", ".bw", ".by", ".bz", ".ca", ".cc", ".cd", ".cf", ".cg", ".ch", ".ci", ".ck", ".cl", ".cm", ".cn", ".co", ".cr", ".cu", ".cv", ".cx", ".cy", ".cz", ".de", ".dj", ".dk", ".dm", ".do", ".dz", ".ec", ".ee", ".eg", ".eh", ".er", ".es", ".et", ".eu", ".fi", ".fj", ".fk", ".fm", ".fo", ".fr", ".ga", ".gd", ".ge", ".gf", ".gg", ".gh", ".gi", ".gl", ".gm", ".gn", ".gp", ".gq", ".gr", ".gs", ".gt", ".gu", ".gw", ".gy", ".hk", ".hm", ".hn", ".hr", ".ht", ".hu", ".id", ".ie", ".il", ".im", ".in", ".io", ".iq", ".ir", ".is", ".it", ".je", ".jm", ".jo", ".jp", ".ke", ".kg", ".kh", ".ki", ".km", ".kn", ".kp", ".kr", ".kw", ".ky", ".kz", ".la", ".lb", ".lc", ".li", ".lk", ".lr", ".ls", ".lt", ".lu", ".lv", ".ly", ".ma", ".mc", ".md", ".mg", ".mh", ".mk", ".ml", ".mm", ".mn", ".mo", ".mp", ".mq", ".mr", ".ms", ".mt", ".mu", ".mv", ".mw", ".mx", ".my", ".mz", ".na", ".nc", ".ne", ".nf", ".ng", ".ni", ".nl", ".no", ".np", ".nr", ".nu", ".nz", ".om", ".pa", ".pe", ".pf", ".pg", ".ph", ".pk", ".pl", ".pm", ".pn", ".pr", ".ps", ".pt", ".pw", ".py", ".qa", ".re", ".ro", ".ru", ".rw", ".sa", ".sb", ".sc", ".sd", ".se", ".sg", ".sh", ".si", ".sj", ".sk", ".sl", ".sm", ".sn", ".so", ".sr", ".st", ".sv", ".sy", ".sz", ".tc", ".td", ".tf", ".tg", ".th", ".tj", ".tk", ".tl", ".tm", ".tn", ".to", ".tp", ".tr", ".tt", ".tv", ".tw", ".tz", ".ua", ".ug", ".uk", ".um", ".us", ".uy", ".uz", ".va", ".vc", ".ve", ".vg", ".vi", ".vn", ".vu", ".wf", ".ws", ".ye", ".yt", ".yu", ".yr", ".za", ".zm", ".zw"} + CN := strings.ToLower(utils.RandString(int(utils.RandInt(4)%10)) + domainSubfixList[int(utils.RandInt(4))%len(domainSubfixList)]) + *s.cfg.CommonName = CN + } + return +} +func (s *Keygen) Start(args interface{}, log *logger.Logger) (err error) { + s.log = log + s.cfg = args.(KeygenArgs) + if err = s.CheckArgs(); err != nil { + return + } + if *s.cfg.Sign { + caCert, caKey, err := cert.ParseCertAndKey(*s.cfg.CaName+".crt", *s.cfg.CaName+".key") + if err != nil { + return err + } + err = cert.CreateSignCertToFile(caCert, caKey, *s.cfg.CommonName, *s.cfg.SignDays, *s.cfg.CertName) + } else { + err = cert.CreateCaToFile(*s.cfg.CaName, *s.cfg.CommonName, *s.cfg.SignDays) + } + if err != nil { + return + } + s.log.Println("success") + os.Exit(0) + return +} + +func (s *Keygen) Clean() { + +} diff --git a/services/socks/socks.go b/services/socks/socks.go index cd7c217..b740966 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -1,4 +1,4 @@ -package services +package socks import ( "crypto/tls" diff --git a/services/sps/sps.go b/services/sps/sps.go index 40f75ce..68591c7 100644 --- a/services/sps/sps.go +++ b/services/sps/sps.go @@ -1,4 +1,4 @@ -package services +package sps import ( "bytes" diff --git a/services/tcp/tcp.go b/services/tcp/tcp.go index 43e612d..652b539 100644 --- a/services/tcp/tcp.go +++ b/services/tcp/tcp.go @@ -1,4 +1,4 @@ -package services +package tcp import ( "bufio" diff --git a/services/tunnel/tunnel_bridge.go b/services/tunnel/tunnel_bridge.go index ccb7564..8f27284 100644 --- a/services/tunnel/tunnel_bridge.go +++ b/services/tunnel/tunnel_bridge.go @@ -1,4 +1,4 @@ -package services +package tunnel import ( "bytes" diff --git a/services/tunnel/tunnel_client.go b/services/tunnel/tunnel_client.go index 5fdabef..6e80dfd 100644 --- a/services/tunnel/tunnel_client.go +++ b/services/tunnel/tunnel_client.go @@ -1,4 +1,4 @@ -package services +package tunnel import ( "crypto/tls" diff --git a/services/tunnel/tunnel_server.go b/services/tunnel/tunnel_server.go index eac5cc6..594033e 100644 --- a/services/tunnel/tunnel_server.go +++ b/services/tunnel/tunnel_server.go @@ -1,4 +1,4 @@ -package services +package tunnel import ( "crypto/tls" diff --git a/services/udp/udp.go b/services/udp/udp.go index 7bd309d..a9388e2 100644 --- a/services/udp/udp.go +++ b/services/udp/udp.go @@ -1,4 +1,4 @@ -package services +package udp import ( "bufio"