mirror of
https://github.com/howmp/reality
synced 2025-02-23 10:32:18 +08:00
add multi grsc and grsu
This commit is contained in:
parent
9bb9c6d084
commit
e9162c84b2
13
README.md
13
README.md
@ -26,6 +26,8 @@ grs是一个反向socks5代理,其中grss和grsc和grsu是通过REALITY协议通
|
|||||||
|
|
||||||
若SNIAddr或ServerAddr不指定,则尝试加载已有配置文件
|
若SNIAddr或ServerAddr不指定,则尝试加载已有配置文件
|
||||||
|
|
||||||
|
默认生成3个不同id文件名的客户端,可通过`-c`参数指定
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
Usage:
|
Usage:
|
||||||
grss [OPTIONS] gen [gen-OPTIONS] [SNIAddr] [ServerAddr]
|
grss [OPTIONS] gen [gen-OPTIONS] [SNIAddr] [ServerAddr]
|
||||||
@ -40,6 +42,7 @@ Help Options:
|
|||||||
-f=[chrome|firefox|safari|ios|android|edge|360|qq] client finger print (default: chrome)
|
-f=[chrome|firefox|safari|ios|android|edge|360|qq] client finger print (default: chrome)
|
||||||
-e= expire second (default: 30)
|
-e= expire second (default: 30)
|
||||||
-o= server config output path (default: config.json)
|
-o= server config output path (default: config.json)
|
||||||
|
-c= client count (default: 3)
|
||||||
--dir= client output directory (default: .)
|
--dir= client output directory (default: .)
|
||||||
|
|
||||||
[gen command arguments]
|
[gen command arguments]
|
||||||
@ -66,14 +69,20 @@ Help Options:
|
|||||||
|
|
||||||
### 启动客户端
|
### 启动客户端
|
||||||
|
|
||||||
`grsc`
|
`grscX`
|
||||||
|
|
||||||
|
**X表示id**
|
||||||
|
|
||||||
### 启动用户端
|
### 启动用户端
|
||||||
|
|
||||||
`grsu`
|
`grsu -id 0`
|
||||||
|
|
||||||
|
**这里id参数对应了grsc的id,不同id会连接不同的grsc**
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
Usage of grsu:
|
Usage of grsu:
|
||||||
|
-i uint
|
||||||
|
id
|
||||||
-l string
|
-l string
|
||||||
socks5 listen address (default "127.0.0.1:61080")
|
socks5 listen address (default "127.0.0.1:61080")
|
||||||
```
|
```
|
||||||
|
15
client.go
15
client.go
@ -23,9 +23,10 @@ type ClientConfig struct {
|
|||||||
SNI string `json:"sni_name"`
|
SNI string `json:"sni_name"`
|
||||||
PublicKeyECDH string `json:"public_key_ecdh"`
|
PublicKeyECDH string `json:"public_key_ecdh"`
|
||||||
PublicKeyVerify string `json:"public_key_verify"`
|
PublicKeyVerify string `json:"public_key_verify"`
|
||||||
FingerPrint string `json:"finger_print,omitempty"`
|
FingerPrint string `json:"finger_print"`
|
||||||
ExpireSecond uint32 `json:"expire_second,omitempty"`
|
ExpireSecond uint32 `json:"expire_second"`
|
||||||
Debug bool `json:"debug,omitempty"`
|
Debug bool `json:"debug"`
|
||||||
|
OverlayData byte `json:"overlay_data"`
|
||||||
|
|
||||||
fingerPrint *utls.ClientHelloID // 客户端的TLS指纹
|
fingerPrint *utls.ClientHelloID // 客户端的TLS指纹
|
||||||
publicKeyECDH *ecdh.PublicKey // 用于密钥协商
|
publicKeyECDH *ecdh.PublicKey // 用于密钥协商
|
||||||
@ -133,7 +134,7 @@ func UnmarshalClientConfig(configData []byte) (*ClientConfig, error) {
|
|||||||
return &config, nil
|
return &config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(ctx context.Context, config *ClientConfig, overlayData byte) (net.Conn, error) {
|
func NewClient(ctx context.Context, config *ClientConfig) (net.Conn, error) {
|
||||||
if err := config.Validate(); err != nil {
|
if err := config.Validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -213,10 +214,10 @@ func NewClient(ctx context.Context, config *ClientConfig, overlayData byte) (net
|
|||||||
is12 := state.Version == versionTLS12
|
is12 := state.Version == versionTLS12
|
||||||
if is12 {
|
if is12 {
|
||||||
// 进行我们私有握手,客户端发送附加数据,服务端回复64字节签名数据
|
// 进行我们私有握手,客户端发送附加数据,服务端回复64字节签名数据
|
||||||
logger.Debugf("overlayData: %x", overlayData)
|
logger.Debugf("overlayData: %x", config.OverlayData)
|
||||||
// record数据前缀模仿seq
|
// record数据前缀模仿seq
|
||||||
data := generateRandomData(seqNumerOne[:])
|
data := generateRandomData(seqNumerOne[:])
|
||||||
data[len(data)-1] = overlayData
|
data[len(data)-1] = config.OverlayData
|
||||||
record := newTLSRecord(recordTypeApplicationData, versionTLS12, data)
|
record := newTLSRecord(recordTypeApplicationData, versionTLS12, data)
|
||||||
if _, err := record.writeTo(uconn.GetUnderlyingConn()); err != nil {
|
if _, err := record.writeTo(uconn.GetUnderlyingConn()); err != nil {
|
||||||
uconn.Close()
|
uconn.Close()
|
||||||
@ -247,7 +248,7 @@ func NewClient(ctx context.Context, config *ClientConfig, overlayData byte) (net
|
|||||||
}
|
}
|
||||||
// 服务端回复验证通过
|
// 服务端回复验证通过
|
||||||
logger.Debugln("verify ok")
|
logger.Debugln("verify ok")
|
||||||
return newWarpConn(uconn.GetUnderlyingConn(), aead, overlayData, seqNumerOne), nil
|
return newWarpConn(uconn.GetUnderlyingConn(), aead, config.OverlayData, seqNumerOne), nil
|
||||||
}
|
}
|
||||||
uconn.Close()
|
uconn.Close()
|
||||||
return nil, ErrVerifyFailed
|
return nil, ErrVerifyFailed
|
||||||
|
@ -36,7 +36,7 @@ func TestClient(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Log(string(d))
|
t.Log(string(d))
|
||||||
|
|
||||||
_, err = reality.NewClient(context.Background(), config, 0)
|
_, err = reality.NewClient(context.Background(), config)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("should error")
|
t.Fatal("should error")
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ func TestClientConfig(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
config := configServer.ToClientConfig()
|
config := configServer.ToClientConfig(0)
|
||||||
configData, err := config.Marshal()
|
configData, err := config.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -1,8 +1,20 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
const (
|
func NewShortID(isGRSC bool, id byte) byte {
|
||||||
OverlayGRSC = byte(0x95)
|
if id > 0x80 {
|
||||||
OverlayGRSU = byte(0x27)
|
panic("id should be less than 128")
|
||||||
)
|
}
|
||||||
|
if isGRSC {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
return 0x80 | id
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseShortID(shortID byte) (isGRSC bool, id byte) {
|
||||||
|
if shortID >= 0x80 {
|
||||||
|
return false, shortID & 0x7f
|
||||||
|
}
|
||||||
|
return true, shortID
|
||||||
|
}
|
||||||
|
|
||||||
var ConfigDataPlaceholder = []byte{0xff, 0xff, 'g', 'r', 's', 'c', 'o', 'n', 'f', 'i', 'g', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
var ConfigDataPlaceholder = []byte{0xff, 0xff, 'g', 'r', 's', 'c', 'o', 'n', 'f', 'i', 'g', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
@ -45,7 +45,7 @@ type client struct {
|
|||||||
|
|
||||||
func (c *client) serve() error {
|
func (c *client) serve() error {
|
||||||
c.logger.Infoln("try connect to server")
|
c.logger.Infoln("try connect to server")
|
||||||
client, err := reality.NewClient(context.Background(), c.config, cmd.OverlayGRSC)
|
client, err := reality.NewClient(context.Background(), c.config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
utls "github.com/refraction-networking/utls"
|
utls "github.com/refraction-networking/utls"
|
||||||
|
|
||||||
@ -19,6 +21,7 @@ type gen struct {
|
|||||||
FingerPrint string `short:"f" default:"chrome" description:"client finger print" choice:"chrome" choice:"firefox" choice:"safari" choice:"ios" choice:"android" choice:"edge" choice:"360" choice:"qq"`
|
FingerPrint string `short:"f" default:"chrome" description:"client finger print" choice:"chrome" choice:"firefox" choice:"safari" choice:"ios" choice:"android" choice:"edge" choice:"360" choice:"qq"`
|
||||||
ExpireSecond uint32 `short:"e" default:"30" description:"expire second"`
|
ExpireSecond uint32 `short:"e" default:"30" description:"expire second"`
|
||||||
ConfigPath string `short:"o" default:"config.json" description:"server config output path"`
|
ConfigPath string `short:"o" default:"config.json" description:"server config output path"`
|
||||||
|
ClientCount byte `short:"c" default:"3" description:"client count"`
|
||||||
ClientOutputDir string `long:"dir" default:"." description:"client output directory"`
|
ClientOutputDir string `long:"dir" default:"." description:"client output directory"`
|
||||||
Positional struct {
|
Positional struct {
|
||||||
SNIAddr string `description:"tls server address, e.g. example.com:443"`
|
SNIAddr string `description:"tls server address, e.g. example.com:443"`
|
||||||
@ -32,6 +35,11 @@ func (c *gen) Execute(args []string) error {
|
|||||||
c.logger = reality.GetLogger(c.Debug)
|
c.logger = reality.GetLogger(c.Debug)
|
||||||
var config *reality.ServerConfig
|
var config *reality.ServerConfig
|
||||||
var err error
|
var err error
|
||||||
|
if c.ClientCount > 128 {
|
||||||
|
return errors.New("client count must less than 128")
|
||||||
|
} else if c.ClientCount == 0 {
|
||||||
|
c.ClientCount = 1
|
||||||
|
}
|
||||||
if c.Positional.SNIAddr == "" || c.Positional.ServerAddr == "" {
|
if c.Positional.SNIAddr == "" || c.Positional.ServerAddr == "" {
|
||||||
c.logger.Infof("try loading config, path %s", c.ConfigPath)
|
c.logger.Infof("try loading config, path %s", c.ConfigPath)
|
||||||
config, err = loadConfig(c.ConfigPath)
|
config, err = loadConfig(c.ConfigPath)
|
||||||
@ -52,7 +60,7 @@ func (c *gen) Execute(args []string) error {
|
|||||||
if err := c.check(); err != nil {
|
if err := c.check(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return c.genClient(config.ToClientConfig())
|
return c.genClient(config.ToClientConfig(0))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +126,28 @@ func (c *gen) genClient(clientConfig *reality.ClientConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range AssetNames() {
|
for _, name := range AssetNames() {
|
||||||
|
if strings.HasPrefix(name, "grsc") {
|
||||||
|
// 根据客户端数量生成多个客户端
|
||||||
|
for i := 0; i < int(c.ClientCount); i++ {
|
||||||
|
path := filepath.Join(c.ClientOutputDir, fmt.Sprintf("grsc%d%s", i, name[4:]))
|
||||||
|
clientConfig.OverlayData = cmd.NewShortID(true, byte(i))
|
||||||
|
clientConfigData, err := clientConfig.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientBin, err := replaceClientTemplate(MustAsset(name), clientConfigData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.WriteFile(path, ClientBin, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.logger.Infof("generated %s", path)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
path := filepath.Join(c.ClientOutputDir, name)
|
path := filepath.Join(c.ClientOutputDir, name)
|
||||||
ClientBin, err := replaceClientTemplate(MustAsset(name), configData)
|
ClientBin, err := replaceClientTemplate(MustAsset(name), configData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
155
cmd/grss/serv.go
155
cmd/grss/serv.go
@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@ -27,19 +26,81 @@ func (s *serv) Execute(args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sessionManager struct {
|
||||||
|
logger logrus.FieldLogger
|
||||||
|
sessions [128]*yamux.Session
|
||||||
|
sessionsLock [128]sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sessionManager) createSession(conn net.Conn, id byte) {
|
||||||
|
if s.isSessionOpen(id) {
|
||||||
|
s.logger.Errorf("client(id:%d) session already open, close %s", id, conn.RemoteAddr())
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.sessionsLock[id].Lock()
|
||||||
|
defer s.sessionsLock[id].Unlock()
|
||||||
|
session, err := yamux.Server(conn, nil)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error(err)
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
go s.checkSession(id, session)
|
||||||
|
s.sessions[id] = session
|
||||||
|
s.logger.Infof("client(id:%d) session opened %s", id, conn.RemoteAddr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sessionManager) isSessionOpen(id byte) bool {
|
||||||
|
s.sessionsLock[id].Lock()
|
||||||
|
defer s.sessionsLock[id].Unlock()
|
||||||
|
session := s.sessions[id]
|
||||||
|
if session != nil {
|
||||||
|
return !session.IsClosed()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sessionManager) openClientSessionStream(id byte) (*yamux.Stream, error) {
|
||||||
|
s.sessionsLock[id].Lock()
|
||||||
|
defer s.sessionsLock[id].Unlock()
|
||||||
|
session := s.sessions[id]
|
||||||
|
if session != nil {
|
||||||
|
stream, err := session.OpenStream()
|
||||||
|
if err != nil {
|
||||||
|
session.Close()
|
||||||
|
s.sessions[id] = nil
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return stream, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("client(id:%d) session not open", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sessionManager) checkSession(id byte, session *yamux.Session) {
|
||||||
|
<-session.CloseChan()
|
||||||
|
s.logger.Infof("client session closed %s", session.RemoteAddr())
|
||||||
|
s.sessionsLock[id].Lock()
|
||||||
|
defer s.sessionsLock[id].Unlock()
|
||||||
|
if s.sessions[id] == session {
|
||||||
|
s.sessions[id] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Server 反向socks5代理服务端
|
// Server 反向socks5代理服务端
|
||||||
type Server struct {
|
type Server struct {
|
||||||
config *reality.ServerConfig
|
config *reality.ServerConfig
|
||||||
logger logrus.FieldLogger
|
logger logrus.FieldLogger
|
||||||
session *yamux.Session
|
sm *sessionManager
|
||||||
sessionLock *sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(config *reality.ServerConfig) *Server {
|
func NewServer(config *reality.ServerConfig) *Server {
|
||||||
|
logger := reality.GetLogger(config.Debug)
|
||||||
return &Server{
|
return &Server{
|
||||||
config: config,
|
config: config,
|
||||||
logger: reality.GetLogger(config.Debug),
|
logger: logger,
|
||||||
sessionLock: &sync.Mutex{},
|
sm: &sessionManager{
|
||||||
|
logger: logger,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,66 +124,48 @@ func (s *Server) Serve() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if o, ok := conn.(reality.OverlayData); ok {
|
if o, ok := conn.(reality.OverlayData); ok {
|
||||||
overlayData := o.OverlayData()
|
isGRSC, id := cmd.ParseShortID(o.OverlayData())
|
||||||
|
if isGRSC {
|
||||||
|
s.logger.Infof("accept client(id:%d) %s", id, conn.RemoteAddr())
|
||||||
|
|
||||||
if overlayData == cmd.OverlayGRSC {
|
go s.sm.createSession(conn, id)
|
||||||
s.logger.Infof("accept client %s", conn.RemoteAddr())
|
|
||||||
go s.handleClient(conn)
|
|
||||||
continue
|
continue
|
||||||
} else if overlayData == cmd.OverlayGRSU {
|
} else {
|
||||||
s.logger.Infof("accept user %s", conn.RemoteAddr())
|
s.logger.Infof("accept user(id:%d) %s", id, conn.RemoteAddr())
|
||||||
go s.handleUser(conn)
|
go s.handleUser(conn, id)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.logger.Warnf("accept %s, but overlay wrong", conn.RemoteAddr())
|
s.logger.Warnf("accept %s, but no overlay data", conn.RemoteAddr())
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handleClient(conn net.Conn) {
|
func (s *Server) handleUser(conn net.Conn, id byte) {
|
||||||
if s.isSessionOpen() {
|
|
||||||
s.logger.Errorf("client session already open, close %s", conn.RemoteAddr())
|
|
||||||
conn.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.sessionLock.Lock()
|
|
||||||
defer s.sessionLock.Unlock()
|
|
||||||
session, err := yamux.Server(conn, nil)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Error(err)
|
|
||||||
conn.Close()
|
|
||||||
}
|
|
||||||
go s.checkSession(session)
|
|
||||||
s.session = session
|
|
||||||
s.logger.Infof("session opened %s", conn.RemoteAddr())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) handleUser(conn net.Conn) {
|
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
session, err := yamux.Client(conn, nil)
|
session, err := yamux.Client(conn, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Errorf("yamux: %v", err)
|
s.logger.Errorf("user(id:%d) yamux: %v", id, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
for {
|
for {
|
||||||
stream, err := session.Accept()
|
stream, err := session.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Errorf("user session accept: %v", err)
|
s.logger.Errorf("user(id:%d) session accept: %v", id, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.logger.Infof("user stream accept %s", stream.RemoteAddr())
|
s.logger.Infof("user(id:%d) stream accept %s", id, stream.RemoteAddr())
|
||||||
go s.handleUserStream(stream)
|
go s.handleUserStream(stream, id)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (s *Server) handleUserStream(stream net.Conn) {
|
func (s *Server) handleUserStream(stream net.Conn, id byte) {
|
||||||
defer stream.Close()
|
defer stream.Close()
|
||||||
conn, err := s.openClientSessionStream()
|
conn, err := s.sm.openClientSessionStream(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Errorf("open client session stream: %v", err)
|
s.logger.Errorf("open client(id:%d) session stream: %v", id, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
@ -130,37 +173,3 @@ func (s *Server) handleUserStream(stream net.Conn) {
|
|||||||
io.Copy(stream, conn)
|
io.Copy(stream, conn)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) isSessionOpen() bool {
|
|
||||||
s.sessionLock.Lock()
|
|
||||||
defer s.sessionLock.Unlock()
|
|
||||||
if s.session != nil {
|
|
||||||
return !s.session.IsClosed()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) openClientSessionStream() (*yamux.Stream, error) {
|
|
||||||
s.sessionLock.Lock()
|
|
||||||
defer s.sessionLock.Unlock()
|
|
||||||
if s.session != nil {
|
|
||||||
stream, err := s.session.OpenStream()
|
|
||||||
if err != nil {
|
|
||||||
s.session.Close()
|
|
||||||
s.session = nil
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return stream, nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("client session not open")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) checkSession(session *yamux.Session) {
|
|
||||||
<-session.CloseChan()
|
|
||||||
s.logger.Infof("client session closed %s", session.RemoteAddr())
|
|
||||||
s.sessionLock.Lock()
|
|
||||||
defer s.sessionLock.Unlock()
|
|
||||||
if s.session == session {
|
|
||||||
s.session = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -38,7 +38,7 @@ func (s *serverSession) connectForever() {
|
|||||||
}
|
}
|
||||||
func (s *serverSession) connect() {
|
func (s *serverSession) connect() {
|
||||||
logger := s.logger
|
logger := s.logger
|
||||||
client, err := reality.NewClient(context.Background(), s.config, cmd.OverlayGRSU)
|
client, err := reality.NewClient(context.Background(), s.config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("connect server: %v", err)
|
logger.Errorf("connect server: %v", err)
|
||||||
return
|
return
|
||||||
@ -76,10 +76,12 @@ func main() {
|
|||||||
println(err.Error())
|
println(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := flag.String("l", "127.0.0.1:61080", "socks5 listen address")
|
|
||||||
flag.Parse()
|
|
||||||
logger := reality.GetLogger(config.Debug)
|
logger := reality.GetLogger(config.Debug)
|
||||||
|
addr := flag.String("l", "127.0.0.1:61080", "socks5 listen address")
|
||||||
|
id := flag.Uint("i", 0, "id")
|
||||||
|
flag.Parse()
|
||||||
|
logger.Infof("server addr: %s, sni: %s, id: %d", config.ServerAddr, config.SNI, byte(*id))
|
||||||
|
config.OverlayData = cmd.NewShortID(false, byte(*id))
|
||||||
l, err := net.Listen("tcp", *addr)
|
l, err := net.Listen("tcp", *addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Panic(err)
|
logger.Panic(err)
|
||||||
|
@ -27,7 +27,7 @@ func main() {
|
|||||||
logger.Panic(err)
|
logger.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := reality.NewClient(context.Background(), &config, 0)
|
client, err := reality.NewClient(context.Background(), &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Panic(err)
|
logger.Panic(err)
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ func main() {
|
|||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
config.Debug = true
|
config.Debug = true
|
||||||
jsonData, err := json.MarshalIndent(config.ToClientConfig(), "", " ")
|
jsonData, err := json.MarshalIndent(config.ToClientConfig(0), "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ func (c *ServerConfig) SNIHost() string {
|
|||||||
func (c *ServerConfig) SNIPort() string {
|
func (c *ServerConfig) SNIPort() string {
|
||||||
return c.sniPort
|
return c.sniPort
|
||||||
}
|
}
|
||||||
func (s *ServerConfig) ToClientConfig() *ClientConfig {
|
func (s *ServerConfig) ToClientConfig(overlayData byte) *ClientConfig {
|
||||||
|
|
||||||
return &ClientConfig{
|
return &ClientConfig{
|
||||||
SNI: s.sniHost,
|
SNI: s.sniHost,
|
||||||
@ -116,6 +116,7 @@ func (s *ServerConfig) ToClientConfig() *ClientConfig {
|
|||||||
ExpireSecond: s.ExpireSecond,
|
ExpireSecond: s.ExpireSecond,
|
||||||
Debug: s.Debug,
|
Debug: s.Debug,
|
||||||
FingerPrint: s.ClientFingerPrint,
|
FingerPrint: s.ClientFingerPrint,
|
||||||
|
OverlayData: overlayData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user