mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2025-12-20 00:50:06 +08:00
update. add customized byte style
This commit is contained in:
parent
40863d248d
commit
14c4fb484d
@ -30,6 +30,7 @@ type SudokuOption struct {
|
|||||||
TableType string `proxy:"table-type,omitempty"` // "prefer_ascii" or "prefer_entropy"
|
TableType string `proxy:"table-type,omitempty"` // "prefer_ascii" or "prefer_entropy"
|
||||||
EnablePureDownlink *bool `proxy:"enable-pure-downlink,omitempty"`
|
EnablePureDownlink *bool `proxy:"enable-pure-downlink,omitempty"`
|
||||||
HTTPMask bool `proxy:"http-mask,omitempty"`
|
HTTPMask bool `proxy:"http-mask,omitempty"`
|
||||||
|
CustomTable string `proxy:"custom-table,omitempty"` // optional custom byte layout, e.g. xpxvvpvv
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
@ -178,13 +179,17 @@ func NewSudoku(option SudokuOption) (*Sudoku, error) {
|
|||||||
ServerAddress: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
ServerAddress: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
|
||||||
Key: option.Key,
|
Key: option.Key,
|
||||||
AEADMethod: defaultConf.AEADMethod,
|
AEADMethod: defaultConf.AEADMethod,
|
||||||
Table: sudoku.NewTable(sudoku.ClientAEADSeed(option.Key), tableType),
|
|
||||||
PaddingMin: paddingMin,
|
PaddingMin: paddingMin,
|
||||||
PaddingMax: paddingMax,
|
PaddingMax: paddingMax,
|
||||||
EnablePureDownlink: enablePureDownlink,
|
EnablePureDownlink: enablePureDownlink,
|
||||||
HandshakeTimeoutSeconds: defaultConf.HandshakeTimeoutSeconds,
|
HandshakeTimeoutSeconds: defaultConf.HandshakeTimeoutSeconds,
|
||||||
DisableHTTPMask: !option.HTTPMask,
|
DisableHTTPMask: !option.HTTPMask,
|
||||||
}
|
}
|
||||||
|
table, err := sudoku.NewTableWithCustom(sudoku.ClientAEADSeed(option.Key), tableType, option.CustomTable)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("build table failed: %w", err)
|
||||||
|
}
|
||||||
|
baseConf.Table = table
|
||||||
if option.AEADMethod != "" {
|
if option.AEADMethod != "" {
|
||||||
baseConf.AEADMethod = option.AEADMethod
|
baseConf.AEADMethod = option.AEADMethod
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1048,8 +1048,9 @@ proxies: # socks5
|
|||||||
padding-min: 2 # 最小填充字节数
|
padding-min: 2 # 最小填充字节数
|
||||||
padding-max: 7 # 最大填充字节数
|
padding-max: 7 # 最大填充字节数
|
||||||
table-type: prefer_ascii # 可选值:prefer_ascii、prefer_entropy 前者全ascii映射,后者保证熵值(汉明1)低于3
|
table-type: prefer_ascii # 可选值:prefer_ascii、prefer_entropy 前者全ascii映射,后者保证熵值(汉明1)低于3
|
||||||
|
# custom-table: xpxvvpvv # 可选,自定义字节布局,必须包含2个x、2个p、4个v,可随意组合。启用此处则无需配置`table-type`
|
||||||
http-mask: true # 是否启用http掩码
|
http-mask: true # 是否启用http掩码
|
||||||
enable-pure-downlink: false # 是否启用混淆下行,false的情况下能在保证数据安全的前提下极大提升下行速度
|
enable-pure-downlink: false # 是否启用混淆下行,false的情况下能在保证数据安全的前提下极大提升下行速度,与服务端端保持相同(如果此处为false,则要求aead不可为none)
|
||||||
|
|
||||||
# anytls
|
# anytls
|
||||||
- name: anytls
|
- name: anytls
|
||||||
@ -1589,8 +1590,9 @@ listeners:
|
|||||||
padding-min: 1 # 填充最小长度
|
padding-min: 1 # 填充最小长度
|
||||||
padding-max: 15 # 填充最大长度,均不建议过大
|
padding-max: 15 # 填充最大长度,均不建议过大
|
||||||
table-type: prefer_ascii # 可选值:prefer_ascii、prefer_entropy 前者全ascii映射,后者保证熵值(汉明1)低于3
|
table-type: prefer_ascii # 可选值:prefer_ascii、prefer_entropy 前者全ascii映射,后者保证熵值(汉明1)低于3
|
||||||
|
# custom-table: xpxvvpvv # 可选,自定义字节布局,必须包含2个x、2个p、4个v
|
||||||
handshake-timeout: 5 # optional
|
handshake-timeout: 5 # optional
|
||||||
enable-pure-downlink: false # 是否启用混淆下行,false的情况下能在保证数据安全的前提下极大提升下行速度,与客户端保持相同
|
enable-pure-downlink: false # 是否启用混淆下行,false的情况下能在保证数据安全的前提下极大提升下行速度,与客户端保持相同(如果此处为false,则要求aead不可为none)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1742,4 +1744,3 @@ listeners:
|
|||||||
# alpn:
|
# alpn:
|
||||||
# - h3
|
# - h3
|
||||||
# max-udp-relay-packet-size: 1500
|
# max-udp-relay-packet-size: 1500
|
||||||
|
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -43,7 +43,7 @@ require (
|
|||||||
github.com/mroth/weightedrand/v2 v2.1.0
|
github.com/mroth/weightedrand/v2 v2.1.0
|
||||||
github.com/openacid/low v0.1.21
|
github.com/openacid/low v0.1.21
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0 // lastest version compatible with golang1.20
|
github.com/oschwald/maxminddb-golang v1.12.0 // lastest version compatible with golang1.20
|
||||||
github.com/saba-futai/sudoku v0.0.2-b
|
github.com/saba-futai/sudoku v0.0.2-c
|
||||||
github.com/sagernet/cors v1.2.1
|
github.com/sagernet/cors v1.2.1
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a
|
||||||
github.com/samber/lo v1.52.0
|
github.com/samber/lo v1.52.0
|
||||||
|
|||||||
4
go.sum
4
go.sum
@ -171,8 +171,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||||
github.com/saba-futai/sudoku v0.0.2-b h1:IbBjgZe1IzzD4xjaCSAdAy8ZNrwOusT14AwCYm77NwI=
|
github.com/saba-futai/sudoku v0.0.2-c h1:0CaoCKx4Br8UL97fnIxn8Y7rnQpflBza7kfaIrdg2rI=
|
||||||
github.com/saba-futai/sudoku v0.0.2-b/go.mod h1:Rvggsoprp7HQM7bMIZUd1M27bPj8THRsZdY1dGbIAvo=
|
github.com/saba-futai/sudoku v0.0.2-c/go.mod h1:Rvggsoprp7HQM7bMIZUd1M27bPj8THRsZdY1dGbIAvo=
|
||||||
github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
|
github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
|
||||||
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
|
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
|
||||||
|
|||||||
@ -14,6 +14,7 @@ type SudokuServer struct {
|
|||||||
TableType string `json:"table-type,omitempty"`
|
TableType string `json:"table-type,omitempty"`
|
||||||
HandshakeTimeoutSecond *int `json:"handshake-timeout,omitempty"`
|
HandshakeTimeoutSecond *int `json:"handshake-timeout,omitempty"`
|
||||||
EnablePureDownlink *bool `json:"enable-pure-downlink,omitempty"`
|
EnablePureDownlink *bool `json:"enable-pure-downlink,omitempty"`
|
||||||
|
CustomTable string `json:"custom-table,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SudokuServer) String() string {
|
func (s SudokuServer) String() string {
|
||||||
|
|||||||
@ -20,6 +20,7 @@ type SudokuOption struct {
|
|||||||
TableType string `inbound:"table-type,omitempty"` // "prefer_ascii" or "prefer_entropy"
|
TableType string `inbound:"table-type,omitempty"` // "prefer_ascii" or "prefer_entropy"
|
||||||
HandshakeTimeoutSecond *int `inbound:"handshake-timeout,omitempty"`
|
HandshakeTimeoutSecond *int `inbound:"handshake-timeout,omitempty"`
|
||||||
EnablePureDownlink *bool `inbound:"enable-pure-downlink,omitempty"`
|
EnablePureDownlink *bool `inbound:"enable-pure-downlink,omitempty"`
|
||||||
|
CustomTable string `inbound:"custom-table,omitempty"` // optional custom byte layout, e.g. xpxvvpvv
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o SudokuOption) Equal(config C.InboundConfig) bool {
|
func (o SudokuOption) Equal(config C.InboundConfig) bool {
|
||||||
@ -52,6 +53,7 @@ func NewSudoku(options *SudokuOption) (*Sudoku, error) {
|
|||||||
TableType: options.TableType,
|
TableType: options.TableType,
|
||||||
HandshakeTimeoutSecond: options.HandshakeTimeoutSecond,
|
HandshakeTimeoutSecond: options.HandshakeTimeoutSecond,
|
||||||
EnablePureDownlink: options.EnablePureDownlink,
|
EnablePureDownlink: options.EnablePureDownlink,
|
||||||
|
CustomTable: options.CustomTable,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Sudoku{
|
return &Sudoku{
|
||||||
|
|||||||
@ -138,3 +138,27 @@ func TestInboundSudoku_PackedDownlink(t *testing.T) {
|
|||||||
testInboundSudoku(t, inboundOptions, outboundOptions)
|
testInboundSudoku(t, inboundOptions, outboundOptions)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInboundSudoku_CustomTable(t *testing.T) {
|
||||||
|
key := "test_key_custom"
|
||||||
|
custom := "xpxvvpvv"
|
||||||
|
inboundOptions := inbound.SudokuOption{
|
||||||
|
Key: key,
|
||||||
|
TableType: "prefer_entropy",
|
||||||
|
CustomTable: custom,
|
||||||
|
}
|
||||||
|
outboundOptions := outbound.SudokuOption{
|
||||||
|
Key: key,
|
||||||
|
TableType: "prefer_entropy",
|
||||||
|
CustomTable: custom,
|
||||||
|
}
|
||||||
|
testInboundSudoku(t, inboundOptions, outboundOptions)
|
||||||
|
|
||||||
|
t.Run("ed25519key", func(t *testing.T) {
|
||||||
|
inboundOptions := inboundOptions
|
||||||
|
outboundOptions := outboundOptions
|
||||||
|
inboundOptions.Key = sudokuPublicKey
|
||||||
|
outboundOptions.Key = sudokuPrivateKey
|
||||||
|
testInboundSudoku(t, inboundOptions, outboundOptions)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -152,6 +152,12 @@ func New(config LC.SudokuServer, tunnel C.Tunnel, additions ...inbound.Addition)
|
|||||||
enablePureDownlink = *config.EnablePureDownlink
|
enablePureDownlink = *config.EnablePureDownlink
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table, err := sudoku.NewTableWithCustom(config.Key, tableType, config.CustomTable)
|
||||||
|
if err != nil {
|
||||||
|
_ = l.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
handshakeTimeout := defaultConf.HandshakeTimeoutSeconds
|
handshakeTimeout := defaultConf.HandshakeTimeoutSeconds
|
||||||
if config.HandshakeTimeoutSecond != nil {
|
if config.HandshakeTimeoutSecond != nil {
|
||||||
handshakeTimeout = *config.HandshakeTimeoutSecond
|
handshakeTimeout = *config.HandshakeTimeoutSecond
|
||||||
@ -160,7 +166,7 @@ func New(config LC.SudokuServer, tunnel C.Tunnel, additions ...inbound.Addition)
|
|||||||
protoConf := sudoku.ProtocolConfig{
|
protoConf := sudoku.ProtocolConfig{
|
||||||
Key: config.Key,
|
Key: config.Key,
|
||||||
AEADMethod: defaultConf.AEADMethod,
|
AEADMethod: defaultConf.AEADMethod,
|
||||||
Table: sudoku.NewTable(config.Key, tableType),
|
Table: table,
|
||||||
PaddingMin: paddingMin,
|
PaddingMin: paddingMin,
|
||||||
PaddingMax: paddingMax,
|
PaddingMax: paddingMax,
|
||||||
EnablePureDownlink: enablePureDownlink,
|
EnablePureDownlink: enablePureDownlink,
|
||||||
|
|||||||
@ -146,12 +146,23 @@ func buildHandshakePayload(key string) [16]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewTable(key string, tableType string) *sudoku.Table {
|
func NewTable(key string, tableType string) *sudoku.Table {
|
||||||
start := time.Now()
|
table, err := NewTableWithCustom(key, tableType, "")
|
||||||
table := sudoku.NewTable(key, tableType)
|
if err != nil {
|
||||||
log.Infoln("[Sudoku] Tables initialized (%s) in %v", tableType, time.Since(start))
|
panic(fmt.Sprintf("[Sudoku] failed to init tables: %v", err))
|
||||||
|
}
|
||||||
return table
|
return table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewTableWithCustom(key string, tableType string, customTable string) (*sudoku.Table, error) {
|
||||||
|
start := time.Now()
|
||||||
|
table, err := sudoku.NewTableWithCustom(key, tableType, customTable)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
log.Infoln("[Sudoku] Tables initialized (%s, custom=%v) in %v", tableType, customTable != "", time.Since(start))
|
||||||
|
return table, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ClientAEADSeed(key string) string {
|
func ClientAEADSeed(key string) string {
|
||||||
if recovered, err := crypto.RecoverPublicKey(key); err == nil {
|
if recovered, err := crypto.RecoverPublicKey(key); err == nil {
|
||||||
return crypto.EncodePoint(recovered)
|
return crypto.EncodePoint(recovered)
|
||||||
|
|||||||
@ -228,3 +228,22 @@ func runPackedUoTSession(id int, cfg *apis.ProtocolConfig, errCh chan<- error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCustomTableHandshake(t *testing.T) {
|
||||||
|
table, err := sudokuobfs.NewTableWithCustom("custom-seed", "prefer_entropy", "xpxvvpvv")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("build custom table: %v", err)
|
||||||
|
}
|
||||||
|
cfg := newPackedConfig(table)
|
||||||
|
errCh := make(chan error, 2)
|
||||||
|
|
||||||
|
runPackedTCPSession(42, cfg, errCh)
|
||||||
|
runPackedUoTSession(43, cfg, errCh)
|
||||||
|
|
||||||
|
close(errCh)
|
||||||
|
for err := range errCh {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("custom table handshake failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user