sps代理增加了对单个上级认证信息的支持,如果没有单独设置,就使用全局-A设置.

现在上级格式: YTpi#2.2.2.2:33080@1
  说明:
  YTpi 是经过base64编码的认证信息,比如是http(s)/socks原始认证信息a:b,用户是a密码是b,base64编码之后是:YTpi
     如果是ss,那么a就是加密方法,b是密码,比如:aes-192-cfb:your_pass,base64编码之后是:YWVzLTE5Mi1jZmI6eW91cl9wYXNz
  # 是间隔符号,如果有认证信息,必须有#,没有认证信息可以省略#.
  2.2.2.2:33080 是上级地址
  @1 是设置权重,可以参考手册权重部分.
This commit is contained in:
arraykeys@gmail.com
2019-01-21 12:15:54 +08:00
parent 87322c335e
commit 0b347b7f8d
6 changed files with 127 additions and 14 deletions

View File

@ -3,6 +3,14 @@ proxy更新日志
v6.9 v6.9
1.修复了sps的start潜在的crash问题. 1.修复了sps的start潜在的crash问题.
2.sps代理增加了--parent-tls-single参数用来支持单向tls上级。 2.sps代理增加了--parent-tls-single参数用来支持单向tls上级。
3.sps代理增加了对单个上级认证信息的支持,如果没有单独设置,就使用全局-A设置.
现在上级格式: YTpi#2.2.2.2:33080@1
说明:
YTpi 是经过base64编码的认证信息,比如是http(s)/socks原始认证信息a:b,用户是a密码是b,base64编码之后是:YTpi
如果是ss,那么a就是加密方法,b是密码,比如:aes-192-cfb:your_pass,base64编码之后是:YWVzLTE5Mi1jZmI6eW91cl9wYXNz
# 是间隔符号,如果有认证信息,必须有#,没有认证信息可以省略#.
2.2.2.2:33080 是上级地址
@1 是设置权重,可以参考手册权重部分.
v6.8 v6.8
1.HTTP(S)\SOCKS5代理,API认证功能,发送给认证接口的参数增加了本地IP,local_ip字段, 1.HTTP(S)\SOCKS5代理,API认证功能,发送给认证接口的参数增加了本地IP,local_ip字段,

View File

@ -1157,6 +1157,18 @@ target:如果客户端是http(s)代理请求,这里代表的是请求的完整ur
如果没有-a或-F或--auth-url参数,就是关闭本地认证. 如果没有-a或-F或--auth-url参数,就是关闭本地认证.
如果没有-A参数,连接上级不使用认证. 如果没有-A参数,连接上级不使用认证.
**设置单独认证信息**
如果存在多个不同上级,而且他们的密码有的一样有的不一样,那么可以针对每个上级设置认证信息,
同时还可以用-A参数设置一个全局认证信息,如果某个上级没有单独设置认证信息就使用全局设置的认证信息.
认证信息和上级写在一起.
格式是: YTpi#2.2.2.2:33080@1
说明:
YTpi 是经过base64编码的认证信息,比如是http(s)/socks原始认证信息a:b,用户是a密码是b,base64编码之后是:YTpi
如果是ss,那么a就是加密方法,b是密码,比如:aes-192-cfb:your_pass,base64编码之后是:YWVzLTE5Mi1jZmI6eW91cl9wYXNz
# 是间隔符号,如果有认证信息,必须有#,没有认证信息可以省略#
2.2.2.2:33080 是上级地址
@1 是设置权重,没有可以省略,详细说明可以参考手册***权重部分***
#### **6.8 自定义加密** #### **6.8 自定义加密**
proxy的sps代理在tcp之上可以通过tls标准加密以及kcp协议加密tcp数据,除此之外还支持在tls和kcp之后进行 proxy的sps代理在tcp之上可以通过tls标准加密以及kcp协议加密tcp数据,除此之外还支持在tls和kcp之后进行

View File

@ -101,7 +101,7 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) {
s.log.Printf("connect %s for udp", serverConn.Target()) s.log.Printf("connect %s for udp", serverConn.Target())
//socks client //socks client
client, err := s.HandshakeSocksParent(&outconn, "udp", serverConn.Target(), serverConn.AuthData(), false) client, err := s.HandshakeSocksParent(s.getParentAuth(lbAddr), &outconn, "udp", serverConn.Target(), serverConn.AuthData(), false)
if err != nil { if err != nil {
clean("handshake fail", fmt.Sprintf("%s", err)) clean("handshake fail", fmt.Sprintf("%s", err))
return return

View File

@ -13,6 +13,7 @@ import (
"runtime/debug" "runtime/debug"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
"github.com/snail007/goproxy/core/cs/server" "github.com/snail007/goproxy/core/cs/server"
@ -20,6 +21,7 @@ import (
"github.com/snail007/goproxy/services" "github.com/snail007/goproxy/services"
"github.com/snail007/goproxy/utils" "github.com/snail007/goproxy/utils"
"github.com/snail007/goproxy/utils/conncrypt" "github.com/snail007/goproxy/utils/conncrypt"
cryptool "github.com/snail007/goproxy/utils/crypt"
"github.com/snail007/goproxy/utils/datasize" "github.com/snail007/goproxy/utils/datasize"
"github.com/snail007/goproxy/utils/dnsx" "github.com/snail007/goproxy/utils/dnsx"
"github.com/snail007/goproxy/utils/iolimiter" "github.com/snail007/goproxy/utils/iolimiter"
@ -92,6 +94,8 @@ type SPS struct {
udpLocalKey []byte udpLocalKey []byte
udpParentKey []byte udpParentKey []byte
jumper *jumper.Jumper jumper *jumper.Jumper
parentAuthData *sync.Map
parentCipherData *sync.Map
} }
func NewSPS() services.Service { func NewSPS() services.Service {
@ -101,6 +105,8 @@ func NewSPS() services.Service {
serverChannels: []*server.ServerChannel{}, serverChannels: []*server.ServerChannel{},
userConns: mapx.NewConcurrentMap(), userConns: mapx.NewConcurrentMap(),
udpRelatedPacketConns: mapx.NewConcurrentMap(), udpRelatedPacketConns: mapx.NewConcurrentMap(),
parentAuthData: &sync.Map{},
parentCipherData: &sync.Map{},
} }
} }
func (s *SPS) CheckArgs() (err error) { func (s *SPS) CheckArgs() (err error) {
@ -169,7 +175,10 @@ func (s *SPS) InitService() (err error) {
} }
if len(*s.cfg.Parent) > 0 { if len(*s.cfg.Parent) > 0 {
s.InitLB() err = s.InitLB()
if err != nil {
return
}
} }
err = s.InitBasicAuth() err = s.InitBasicAuth()
@ -211,6 +220,8 @@ func (s *SPS) StopService() {
s.udpParentKey = nil s.udpParentKey = nil
s.udpRelatedPacketConns = nil s.udpRelatedPacketConns = nil
s.userConns = nil s.userConns = nil
s.parentAuthData = nil
s.parentCipherData = nil
s = nil s = nil
}() }()
for _, sc := range s.serverChannels { for _, sc := range s.serverChannels {
@ -437,8 +448,8 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
utils.CloseConn(inConn) utils.CloseConn(inConn)
return return
} }
ParentAuth := s.getParentAuth(lbAddr)
if *s.cfg.ParentAuth != "" || *s.cfg.ParentSSKey != "" || s.IsBasicAuth() { if ParentAuth != "" || *s.cfg.ParentSSKey != "" || s.IsBasicAuth() {
forwardBytes = utils.RemoveProxyHeaders(forwardBytes) forwardBytes = utils.RemoveProxyHeaders(forwardBytes)
} }
@ -458,8 +469,8 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
pb.WriteString("Connection: Keep-Alive\r\n") pb.WriteString("Connection: Keep-Alive\r\n")
u := "" u := ""
if *s.cfg.ParentAuth != "" { if ParentAuth != "" {
a := strings.Split(*s.cfg.ParentAuth, ":") a := strings.Split(ParentAuth, ":")
if len(a) != 2 { if len(a) != 2 {
err = fmt.Errorf("parent auth data format error") err = fmt.Errorf("parent auth data format error")
return return
@ -510,7 +521,7 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
s.log.Printf("connect %s", address) s.log.Printf("connect %s", address)
//socks client //socks client
_, err = s.HandshakeSocksParent(&outConn, "tcp", address, auth, false) _, err = s.HandshakeSocksParent(ParentAuth, &outConn, "tcp", address, auth, false)
if err != nil { if err != nil {
s.log.Printf("handshake fail, %s", err) s.log.Printf("handshake fail, %s", err)
return return
@ -523,7 +534,7 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
return return
} }
outConn, err = ss.DialWithRawAddr(&outConn, ra, "", s.parentCipher.Copy()) outConn, err = ss.DialWithRawAddr(&outConn, ra, "", s.getParentCipher(lbAddr))
if err != nil { if err != nil {
err = fmt.Errorf("dial ss parent fail, err : %s", err) err = fmt.Errorf("dial ss parent fail, err : %s", err)
return return
@ -583,10 +594,41 @@ func (s *SPS) InitBasicAuth() (err error) {
} }
return return
} }
func (s *SPS) InitLB() { func (s *SPS) InitLB() (err error) {
configs := lb.BackendsConfig{} configs := lb.BackendsConfig{}
for _, addr := range *s.cfg.Parent { for _, addr := range *s.cfg.Parent {
_addrInfo := strings.Split(addr, "@") var _addrInfo []string
if strings.Contains(addr, "#") {
_s := addr[:strings.Index(addr, "#")]
_auth, err := cryptool.CryptTools.Base64Decode(_s)
if err != nil {
s.log.Printf("decoding parent auth data [ %s ] fail , error : %s", _s, err)
return err
}
_addrInfo = strings.Split(addr[strings.Index(addr, "#")+1:], "@")
if *s.cfg.ParentServiceType == "ss" {
_s := strings.Split(_auth, ":")
m := _s[0]
k := _s[1]
if m == "" {
m = *s.cfg.ParentSSMethod
}
if k == "" {
k = *s.cfg.ParentSSKey
}
cipher, err := ss.NewCipher(m, k)
if err != nil {
s.log.Printf("error generating cipher, ssMethod: %s, ssKey: %s, error : %s", m, k, err)
return err
}
s.parentCipherData.Store(_addrInfo[0], cipher)
} else {
s.parentAuthData.Store(_addrInfo[0], _auth)
}
} else {
_addrInfo = strings.Split(addr, "@")
}
_addr := _addrInfo[0] _addr := _addrInfo[0]
weight := 1 weight := 1
if len(_addrInfo) == 2 { if len(_addrInfo) == 2 {
@ -603,6 +645,19 @@ func (s *SPS) InitLB() {
} }
LB := lb.NewGroup(utils.LBMethod(*s.cfg.LoadBalanceMethod), configs, &s.domainResolver, s.log, *s.cfg.Debug) LB := lb.NewGroup(utils.LBMethod(*s.cfg.LoadBalanceMethod), configs, &s.domainResolver, s.log, *s.cfg.Debug)
s.lb = &LB s.lb = &LB
return
}
func (s *SPS) getParentAuth(lbAddr string) string {
if v, ok := s.parentAuthData.Load(lbAddr); ok {
return v.(string)
}
return *s.cfg.ParentAuth
}
func (s *SPS) getParentCipher(lbAddr string) *ss.Cipher {
if v, ok := s.parentCipherData.Load(lbAddr); ok {
return v.(*ss.Cipher).Copy()
}
return s.parentCipher.Copy()
} }
func (s *SPS) IsBasicAuth() bool { func (s *SPS) IsBasicAuth() bool {
return *s.cfg.AuthFile != "" || len(*s.cfg.Auth) > 0 || *s.cfg.AuthURL != "" return *s.cfg.AuthFile != "" || len(*s.cfg.Auth) > 0 || *s.cfg.AuthURL != ""
@ -706,9 +761,9 @@ func (s *SPS) GetParentConn(address string) (conn net.Conn, err error) {
} }
return return
} }
func (s *SPS) HandshakeSocksParent(outconn *net.Conn, network, dstAddr string, auth socks.Auth, fromSS bool) (client *socks.ClientConn, err error) { func (s *SPS) HandshakeSocksParent(parentAuth string, outconn *net.Conn, network, dstAddr string, auth socks.Auth, fromSS bool) (client *socks.ClientConn, err error) {
if *s.cfg.ParentAuth != "" { if parentAuth != "" {
a := strings.Split(*s.cfg.ParentAuth, ":") a := strings.Split(parentAuth, ":")
if len(a) != 2 { if len(a) != 2 {
err = fmt.Errorf("parent auth data format error") err = fmt.Errorf("parent auth data format error")
return return

View File

@ -88,7 +88,7 @@ func (s *SPS) RunSSUDP(addr string) (err error) {
return return
} }
client, err := s.HandshakeSocksParent(&outconn, "udp", socksPacket.Addr(), socks.Auth{}, true) client, err := s.HandshakeSocksParent(s.getParentAuth(lbAddr), &outconn, "udp", socksPacket.Addr(), socks.Auth{}, true)
if err != nil { if err != nil {
clean("handshake fail", fmt.Sprintf("%s", err)) clean("handshake fail", fmt.Sprintf("%s", err))
return return

38
utils/crypt/misc.go Normal file
View File

@ -0,0 +1,38 @@
package utils
import (
"crypto/md5"
"encoding/base64"
"encoding/hex"
)
type CryptTool struct{}
var CryptTools = NewCryptTool()
func NewCryptTool() *CryptTool {
return &CryptTool{}
}
func (encrypt *CryptTool) Base64Encode(str string) string {
return string([]byte(base64.StdEncoding.EncodeToString([]byte(str))))
}
func (encrypt *CryptTool) Base64EncodeBytes(bytes []byte) []byte {
return []byte(base64.StdEncoding.EncodeToString(bytes))
}
func (encrypt *CryptTool) Base64Decode(str string) (string, error) {
by, err := base64.StdEncoding.DecodeString(str)
return string(by), err
}
func (encrypt *CryptTool) Base64DecodeBytes(str string) ([]byte, error) {
return base64.StdEncoding.DecodeString(str)
}
func (encrypt *CryptTool) MD5(str string) string {
hash := md5.New()
hash.Write([]byte(str))
return hex.EncodeToString(hash.Sum(nil))
}