Skip to content

Commit

Permalink
add multi grsc and grsu
Browse files Browse the repository at this point in the history
  • Loading branch information
howmp committed Oct 17, 2024
1 parent 9bb9c6d commit e9162c8
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 99 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ grs是一个反向socks5代理,其中grss和grsc和grsu是通过REALITY协议通

若SNIAddr或ServerAddr不指定,则尝试加载已有配置文件

默认生成3个不同id文件名的客户端,可通过`-c`参数指定

```txt
Usage:
grss [OPTIONS] gen [gen-OPTIONS] [SNIAddr] [ServerAddr]
Expand All @@ -40,6 +42,7 @@ Help Options:
-f=[chrome|firefox|safari|ios|android|edge|360|qq] client finger print (default: chrome)
-e= expire second (default: 30)
-o= server config output path (default: config.json)
-c= client count (default: 3)
--dir= client output directory (default: .)
[gen command arguments]
Expand All @@ -66,14 +69,20 @@ Help Options:

### 启动客户端

`grsc`
`grscX`

**X表示id**

### 启动用户端

`grsu`
`grsu -id 0`

**这里id参数对应了grsc的id,不同id会连接不同的grsc**

```txt
Usage of grsu:
-i uint
id
-l string
socks5 listen address (default "127.0.0.1:61080")
```
Expand Down
15 changes: 8 additions & 7 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ type ClientConfig struct {
SNI string `json:"sni_name"`
PublicKeyECDH string `json:"public_key_ecdh"`
PublicKeyVerify string `json:"public_key_verify"`
FingerPrint string `json:"finger_print,omitempty"`
ExpireSecond uint32 `json:"expire_second,omitempty"`
Debug bool `json:"debug,omitempty"`
FingerPrint string `json:"finger_print"`
ExpireSecond uint32 `json:"expire_second"`
Debug bool `json:"debug"`
OverlayData byte `json:"overlay_data"`

fingerPrint *utls.ClientHelloID // 客户端的TLS指纹
publicKeyECDH *ecdh.PublicKey // 用于密钥协商
Expand Down Expand Up @@ -133,7 +134,7 @@ func UnmarshalClientConfig(configData []byte) (*ClientConfig, error) {
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 {
return nil, err
}
Expand Down Expand Up @@ -213,10 +214,10 @@ func NewClient(ctx context.Context, config *ClientConfig, overlayData byte) (net
is12 := state.Version == versionTLS12
if is12 {
// 进行我们私有握手,客户端发送附加数据,服务端回复64字节签名数据
logger.Debugf("overlayData: %x", overlayData)
logger.Debugf("overlayData: %x", config.OverlayData)
// record数据前缀模仿seq
data := generateRandomData(seqNumerOne[:])
data[len(data)-1] = overlayData
data[len(data)-1] = config.OverlayData
record := newTLSRecord(recordTypeApplicationData, versionTLS12, data)
if _, err := record.writeTo(uconn.GetUnderlyingConn()); err != nil {
uconn.Close()
Expand Down Expand Up @@ -247,7 +248,7 @@ func NewClient(ctx context.Context, config *ClientConfig, overlayData byte) (net
}
// 服务端回复验证通过
logger.Debugln("verify ok")
return newWarpConn(uconn.GetUnderlyingConn(), aead, overlayData, seqNumerOne), nil
return newWarpConn(uconn.GetUnderlyingConn(), aead, config.OverlayData, seqNumerOne), nil
}
uconn.Close()
return nil, ErrVerifyFailed
Expand Down
4 changes: 2 additions & 2 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestClient(t *testing.T) {
}
t.Log(string(d))

_, err = reality.NewClient(context.Background(), config, 0)
_, err = reality.NewClient(context.Background(), config)
if err == nil {
t.Fatal("should error")
}
Expand All @@ -48,7 +48,7 @@ func TestClientConfig(t *testing.T) {
if err != nil {
t.Fatal(err)
}
config := configServer.ToClientConfig()
config := configServer.ToClientConfig(0)
configData, err := config.Marshal()
if err != nil {
t.Fatal(err)
Expand Down
20 changes: 16 additions & 4 deletions cmd/common.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
package cmd

const (
OverlayGRSC = byte(0x95)
OverlayGRSU = byte(0x27)
)
func NewShortID(isGRSC bool, id byte) byte {
if id > 0x80 {
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}
2 changes: 1 addition & 1 deletion cmd/grsc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ type client struct {

func (c *client) serve() error {
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 {
return err
}
Expand Down
32 changes: 31 additions & 1 deletion cmd/grss/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"bytes"
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
"strings"

utls "github.com/refraction-networking/utls"

Expand All @@ -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"`
ExpireSecond uint32 `short:"e" default:"30" description:"expire second"`
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"`
Positional struct {
SNIAddr string `description:"tls server address, e.g. example.com:443"`
Expand All @@ -32,6 +35,11 @@ func (c *gen) Execute(args []string) error {
c.logger = reality.GetLogger(c.Debug)
var config *reality.ServerConfig
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 == "" {
c.logger.Infof("try loading config, path %s", c.ConfigPath)
config, err = loadConfig(c.ConfigPath)
Expand All @@ -52,7 +60,7 @@ func (c *gen) Execute(args []string) error {
if err := c.check(); err != nil {
return err
}
return c.genClient(config.ToClientConfig())
return c.genClient(config.ToClientConfig(0))

}

Expand Down Expand Up @@ -118,6 +126,28 @@ func (c *gen) genClient(clientConfig *reality.ClientConfig) error {
}

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)
ClientBin, err := replaceClientTemplate(MustAsset(name), configData)
if err != nil {
Expand Down
Loading

0 comments on commit e9162c8

Please sign in to comment.