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:
@ -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字段,
|
||||||
|
|||||||
12
README_ZH.md
12
README_ZH.md
@ -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之后进行
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
38
utils/crypt/misc.go
Normal 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))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user