Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
proxy更新日志
|
||||
v3.4
|
||||
1.
|
||||
1.socks5代理新增了用户名密码验证支持.
|
||||
|
||||
v3.3
|
||||
1.修复了socks代理模式对证书文件的判断逻辑.
|
||||
|
||||
13
README.md
13
README.md
@ -31,6 +31,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
|
||||
- [v3.0手册](https://github.com/snail007/goproxy/tree/v3.0)
|
||||
- [v2.x手册](https://github.com/snail007/goproxy/tree/v2.2)
|
||||
|
||||
[TOC]
|
||||
|
||||
### Fast Start
|
||||
提示:所有操作需要root权限.
|
||||
**0.如果你的VPS是linux64位的系统,那么只需要执行下面一句,就可以完成自动安装和配置.**
|
||||
@ -420,11 +422,18 @@ server连接到bridge的时候,如果同时有多个client连接到同一个brid
|
||||
|
||||
那么访问本地的28080端口就是通过VPS访问目标地址.
|
||||
|
||||
**5.7.查看帮助**
|
||||
**5.7.认证**
|
||||
对于socks5代理协议我们可以进行用户名密码认证,认证的用户名和密码可以在命令行指定
|
||||
`./proxy socks -t tcp -p ":33080" -a "user1:pass1" -a "user2:pass2"`
|
||||
多个用户,重复-a参数即可.
|
||||
也可以放在文件中,格式是一行一个"用户名:密码",然后用-F指定.
|
||||
`./proxy socks -t tcp -p ":33080" -F auth-file.txt`
|
||||
如果没有-a或-F参数,就是关闭认证.
|
||||
|
||||
**5.8.查看帮助**
|
||||
`./proxy help socks`
|
||||
|
||||
### TODO
|
||||
- SOCKS5增加用户名密码认证?
|
||||
- http,socks代理多个上级负载均衡?
|
||||
- 内网穿透server<->bridge心跳机制?
|
||||
- 欢迎加群反馈...
|
||||
|
||||
@ -124,6 +124,8 @@ func initConfig() (err error) {
|
||||
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()
|
||||
//parse args
|
||||
serviceName := kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||
flags := log.Ldate
|
||||
|
||||
@ -118,6 +118,8 @@ type SocksArgs struct {
|
||||
Interval *int
|
||||
Blocked *string
|
||||
Direct *string
|
||||
AuthFile *string
|
||||
Auth *[]string
|
||||
}
|
||||
|
||||
func (a *TCPArgs) Protocol() string {
|
||||
|
||||
@ -78,6 +78,7 @@ func (s *Socks) CheckArgs() {
|
||||
|
||||
}
|
||||
func (s *Socks) InitService() {
|
||||
s.InitBasicAuth()
|
||||
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()
|
||||
@ -94,9 +95,6 @@ func (s *Socks) InitService() {
|
||||
if err != nil {
|
||||
if s.sshClient != nil {
|
||||
s.sshClient.Close()
|
||||
if s.sshClient.Conn != nil {
|
||||
s.sshClient.Conn.Close()
|
||||
}
|
||||
}
|
||||
log.Printf("ssh offline, retrying...")
|
||||
s.ConnectSSH()
|
||||
@ -290,18 +288,26 @@ func (s *Socks) socksConnCallback(inConn net.Conn) {
|
||||
}
|
||||
utils.CloseConn(&inConn)
|
||||
}()
|
||||
//协商开始
|
||||
|
||||
//method select request
|
||||
inConn.SetReadDeadline(time.Now().Add(time.Second * 3))
|
||||
methodReq, err := socks.NewMethodsRequest(inConn)
|
||||
if err != nil || !methodReq.Select(socks.Method_NO_AUTH) {
|
||||
inConn.SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
methodReq.Reply(socks.Method_NONE_ACCEPTABLE)
|
||||
utils.CloseConn(&inConn)
|
||||
if err != nil {
|
||||
log.Printf("new methods request fail,ERR: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !s.IsBasicAuth() {
|
||||
if !methodReq.Select(socks.Method_NO_AUTH) {
|
||||
methodReq.Reply(socks.Method_NONE_ACCEPTABLE)
|
||||
utils.CloseConn(&inConn)
|
||||
log.Printf("none method found : Method_NO_AUTH")
|
||||
return
|
||||
}
|
||||
//method select reply
|
||||
err = methodReq.Reply(socks.Method_NO_AUTH)
|
||||
if err != nil {
|
||||
@ -309,8 +315,44 @@ func (s *Socks) socksConnCallback(inConn net.Conn) {
|
||||
utils.CloseConn(&inConn)
|
||||
return
|
||||
}
|
||||
|
||||
// log.Printf("% x", methodReq.Bytes())
|
||||
} else {
|
||||
//auth
|
||||
if !methodReq.Select(socks.Method_USER_PASS) {
|
||||
methodReq.Reply(socks.Method_NONE_ACCEPTABLE)
|
||||
utils.CloseConn(&inConn)
|
||||
log.Printf("none method found : Method_USER_PASS")
|
||||
return
|
||||
}
|
||||
//method reply need auth
|
||||
err = methodReq.Reply(socks.Method_USER_PASS)
|
||||
if err != nil {
|
||||
log.Printf("reply answer data fail,ERR: %s", err)
|
||||
utils.CloseConn(&inConn)
|
||||
return
|
||||
}
|
||||
//read auth
|
||||
buf := make([]byte, 500)
|
||||
inConn.SetReadDeadline(time.Now().Add(time.Second * 3))
|
||||
n, err := inConn.Read(buf)
|
||||
inConn.SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
utils.CloseConn(&inConn)
|
||||
return
|
||||
}
|
||||
r := buf[:n]
|
||||
user := string(r[2 : r[1]+2])
|
||||
pass := string(r[2+r[1]+1:])
|
||||
//log.Printf("user:%s,pass:%s", user, pass)
|
||||
//auth
|
||||
if s.basicAuth.CheckUserPass(user, pass) {
|
||||
inConn.Write([]byte{0x01, 0x00})
|
||||
} else {
|
||||
inConn.Write([]byte{0x01, 0x01})
|
||||
utils.CloseConn(&inConn)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//request detail
|
||||
request, err := socks.NewRequest(inConn)
|
||||
@ -319,6 +361,7 @@ func (s *Socks) socksConnCallback(inConn net.Conn) {
|
||||
utils.CloseConn(&inConn)
|
||||
return
|
||||
}
|
||||
//协商结束
|
||||
|
||||
switch request.CMD() {
|
||||
case socks.CMD_BIND:
|
||||
@ -447,7 +490,7 @@ func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn n
|
||||
return
|
||||
}
|
||||
wait := make(chan bool, 1)
|
||||
func() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if err == nil {
|
||||
err = recover()
|
||||
@ -458,8 +501,9 @@ func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn n
|
||||
}()
|
||||
select {
|
||||
case <-wait:
|
||||
case <-time.After(time.Second * 5):
|
||||
case <-time.After(time.Millisecond * time.Duration(*s.cfg.Timeout) * 2):
|
||||
err = fmt.Errorf("ssh dial %s timeout", host)
|
||||
s.sshClient.Close()
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("connect ssh fail, ERR: %s, retrying...", err)
|
||||
@ -498,3 +542,23 @@ func (s *Socks) ConnectSSH() (err error) {
|
||||
<-s.lockChn
|
||||
return
|
||||
}
|
||||
func (s *Socks) InitBasicAuth() (err error) {
|
||||
s.basicAuth = utils.NewBasicAuth()
|
||||
if *s.cfg.AuthFile != "" {
|
||||
var n = 0
|
||||
n, err = s.basicAuth.AddFromFile(*s.cfg.AuthFile)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("auth-file ERR:%s", err)
|
||||
return
|
||||
}
|
||||
log.Printf("auth data added from file %d , total:%d", n, s.basicAuth.Total())
|
||||
}
|
||||
if len(*s.cfg.Auth) > 0 {
|
||||
n := s.basicAuth.Add(*s.cfg.Auth)
|
||||
log.Printf("auth data added %d, total:%d", n, s.basicAuth.Total())
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *Socks) IsBasicAuth() bool {
|
||||
return *s.cfg.AuthFile != "" || len(*s.cfg.Auth) > 0
|
||||
}
|
||||
|
||||
@ -213,7 +213,12 @@ func (ba *BasicAuth) Add(userpassArr []string) (n int) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (ba *BasicAuth) CheckUserPass(user, pass string) (ok bool) {
|
||||
if p, _ok := ba.data.Get(user); _ok {
|
||||
return p.(string) == pass
|
||||
}
|
||||
return
|
||||
}
|
||||
func (ba *BasicAuth) Check(userpass string) (ok bool) {
|
||||
u := strings.Split(strings.Trim(userpass, " "), ":")
|
||||
if len(u) == 2 {
|
||||
|
||||
Reference in New Issue
Block a user