Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replacing crc32 by sha256 hash sum and making sure it doesn't use negative checksum #42

Merged
merged 1 commit into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions masquerade.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package fronted

import (
"crypto/sha256"
"encoding/json"
"fmt"
"hash/crc32"
"net"
"net/http"
"sort"
Expand Down Expand Up @@ -125,18 +125,29 @@ func NewProvider(hosts map[string]string, testURL string, masquerades []*Masquer
}

for _, m := range masquerades {
var sni string
if d.SNIConfig != nil && d.SNIConfig.UseArbitrarySNIs {
// Ensure that we use a consistent SNI for a given combination of IP address and SNI set
crc32Hash := int(crc32.ChecksumIEEE([]byte(m.IpAddress)))
sni = d.SNIConfig.ArbitrarySNIs[crc32Hash%len(d.SNIConfig.ArbitrarySNIs)]
}
sni := generateSNI(d.SNIConfig, m)
d.Masquerades = append(d.Masquerades, &Masquerade{Domain: m.Domain, IpAddress: m.IpAddress, SNI: sni})
}
d.PassthroughPatterns = append(d.PassthroughPatterns, passthrough...)
return d
}

// generateSNI generates a SNI for the given domain and ip address
func generateSNI(config *SNIConfig, m *Masquerade) string {
if config != nil && m != nil && config.UseArbitrarySNIs && len(config.ArbitrarySNIs) > 0 {
// Ensure that we use a consistent SNI for a given combination of IP address and SNI set
hash := sha256.New()
hash.Write([]byte(m.IpAddress))
checksum := int(hash.Sum(nil)[0])
// making sure checksum is positive
if checksum < 0 {
checksum = -checksum
}
return config.ArbitrarySNIs[checksum%len(config.ArbitrarySNIs)]
}
return ""
}

// Lookup the host alias for the given hostname for this provider
func (p *Provider) Lookup(hostname string) string {
// only consider the host porition if given a port as well.
Expand Down
70 changes: 70 additions & 0 deletions masquerade_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package fronted

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestGenerateSNI(t *testing.T) {
emptyMasquerade := new(Masquerade)
var tests = []struct {
name string
assert func(t *testing.T, actual string)
givenConfig *SNIConfig
givenMasquerade *Masquerade
}{
{
name: "should return a empty string when given SNI config is nil",
givenConfig: nil,
givenMasquerade: emptyMasquerade,
assert: func(t *testing.T, actual string) {
assert.Empty(t, actual)
},
},
{
name: "should return a empty string when given SNI config is not nil and UseArbitrarySNIs is false",
givenConfig: &SNIConfig{
UseArbitrarySNIs: false,
},
givenMasquerade: emptyMasquerade,
assert: func(t *testing.T, actual string) {
assert.Empty(t, actual)
},
},
{
name: "should return a empty SNI when the list of arbitrary SNIs is empty",
givenConfig: &SNIConfig{
UseArbitrarySNIs: true,
ArbitrarySNIs: []string{},
},
givenMasquerade: &Masquerade{
IpAddress: "1.1.1.1",
Domain: "randomdomain.net",
},
assert: func(t *testing.T, actual string) {
assert.Empty(t, actual)
},
},
{
name: "should return a SNI when given SNI config is not nil and UseArbitrarySNIs is true",
givenConfig: &SNIConfig{
UseArbitrarySNIs: true,
ArbitrarySNIs: []string{"sni1.com", "sni2.com"},
},
givenMasquerade: &Masquerade{
IpAddress: "1.1.1.1",
Domain: "randomdomain.net",
},
assert: func(t *testing.T, actual string) {
assert.NotEmpty(t, actual)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actual := generateSNI(tt.givenConfig, tt.givenMasquerade)
tt.assert(t, actual)
})
}
}
Loading