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

Adding SNI config #40

Merged
merged 17 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
3062fd0
feat: adding SNIConfig to provider and load it
WendelHime Jul 17, 2024
0cebc16
feat: check if there's a SNIConfig available for the provider and use…
WendelHime Jul 17, 2024
4a5c36e
feat: updating go version to 1.22.3; go mod tidy and updating workflo…
WendelHime Jul 17, 2024
547471b
chore: updating workflow for using actions/setup-go@v4
WendelHime Jul 17, 2024
878cb7b
fix: replacing IntN old reference, reverting expected argument type t…
WendelHime Jul 17, 2024
bf437da
fix: removing deprecated references and updating NewProvider referenc…
WendelHime Jul 17, 2024
36cf77f
chore: updating some old domains
WendelHime Jul 19, 2024
df00536
chore: updating default masquerade IPs
WendelHime Jul 22, 2024
c5f6958
chore: returning custom errors when verifying peer certificates
WendelHime Jul 22, 2024
4b8fdd6
fix: updating old test URLs and references so tests can work
WendelHime Jul 22, 2024
9ba01d0
chore: adding more test certificates and akamai default masquerades u…
WendelHime Jul 23, 2024
b26777e
feat: adding feat for sending the provided SNI verify the domain if i…
WendelHime Jul 23, 2024
0e20465
chore: adding note about default_masquerades.go with old IP addresses
WendelHime Jul 23, 2024
1385d8c
fix: updating SNIConfig comment
WendelHime Jul 26, 2024
5ecdafa
fix: hashing IP addresses and setting SNI to masquerades
WendelHime Jul 26, 2024
58b3171
fix: removing unused verifiedChains parameter, replacing fmt errors %…
WendelHime Jul 29, 2024
3da002e
fix: adding comment suggestion explaining about ensuring the use of h…
WendelHime Jul 30, 2024
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
6 changes: 3 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v4
with:
go-version: 1.18
go-version-file: "go.mod"
WendelHime marked this conversation as resolved.
Show resolved Hide resolved
- name: Granting private modules access
run: |
git config --global url."https://${{ secrets.GH_TOKEN }}:[email protected]/".insteadOf "https://github.com/"
Expand All @@ -24,4 +24,4 @@ jobs:
- name: Send coverage
env:
COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: goveralls -coverprofile=profile.cov -service=github
run: goveralls -coverprofile=profile.cov -service=github
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ For docs:
`godoc github.com/getlantern/fronted`

See [ddftool](https://github.com/getlantern/ddftool) for more details on how to generate and tests fronting domains for the supported CDNs.

[!NOTE]
Since the masquerade domains and IP addresses can change, tests might fail and they need to be updated. You can basically ping some of the masquerade domains (from `default_masquerade.go`) and update the IPs accordingly.
WendelHime marked this conversation as resolved.
Show resolved Hide resolved
9 changes: 4 additions & 5 deletions cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package fronted

import (
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"testing"
Expand All @@ -13,7 +12,7 @@ import (
)

func TestCaching(t *testing.T) {
dir, err := ioutil.TempDir("", "direct_test")
dir, err := os.MkdirTemp("", "direct_test")
if !assert.NoError(t, err, "Unable to create temp dir") {
return
}
Expand All @@ -23,8 +22,8 @@ func TestCaching(t *testing.T) {
cloudsackID := "cloudsack"

providers := map[string]*Provider{
testProviderID: NewProvider(nil, "", nil, nil, nil),
cloudsackID: NewProvider(nil, "", nil, nil, nil),
testProviderID: NewProvider(nil, "", nil, nil, nil, nil),
cloudsackID: NewProvider(nil, "", nil, nil, nil, nil),
}

makeDirect := func() *direct {
Expand Down Expand Up @@ -52,7 +51,7 @@ func TestCaching(t *testing.T) {

readCached := func() []*masquerade {
var result []*masquerade
b, err := ioutil.ReadFile(cacheFile)
b, err := os.ReadFile(cacheFile)
require.NoError(t, err, "Unable to read cache file")
err = json.Unmarshal(b, &result)
require.NoError(t, err, "Unable to unmarshal cache file")
Expand Down
2 changes: 1 addition & 1 deletion context.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (fctx *FrontingContext) ConfigureWithHello(pool *x509.CertPool, providers m

// copy providers
for k, p := range providers {
d.providers[k] = NewProvider(p.HostAliases, p.TestURL, p.Masquerades, p.Validator, p.PassthroughPatterns)
d.providers[k] = NewProvider(p.HostAliases, p.TestURL, p.Masquerades, p.Validator, p.PassthroughPatterns, p.SNIConfig)
}

d.loadCandidates(d.providers)
Expand Down
41 changes: 28 additions & 13 deletions default_masquerades.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,31 @@ var DefaultTrustedCAs = []*CA{
CommonName: "USERTrust RSA Certification Authority",
Cert: "-----BEGIN CERTIFICATE-----\nMIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB\niDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\ncnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\nBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw\nMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV\nBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU\naGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy\ndGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\nAoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B\n3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY\ntJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/\nFp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2\nVN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT\n79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6\nc0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT\nYo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l\nc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee\nUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE\nHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd\nBgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G\nA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF\nUp/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO\nVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3\nATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs\n8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR\niQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze\nSf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ\nXHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/\nqS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB\nVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB\nL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG\njjxDah2nGN59PRbxYvnKkKj9\n-----END CERTIFICATE-----\n",
},
{
CommonName: "GlobalSign",
Cert: "-----BEGIN CERTIFICATE-----\nMIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\nA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\nZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\nMTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\nA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\nRgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\ngHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\nKPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\nQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\nXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\nDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\nLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\nRUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\njjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\n6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\nmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\nMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\nWD9f\n-----END CERTIFICATE-----\n",
},
{
CommonName: "ISRG Root X1",
Cert: "-----BEGIN CERTIFICATE-----\nMIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\nTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\ncmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\nWhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\nZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\nMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\nh77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\nA5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\nT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\nB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\nB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\nKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\nOlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\njh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\nqHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\nrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\nHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\nhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\nubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\nNFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\nORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\nTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\njNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\noyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\nmRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\nemyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n-----END CERTIFICATE-----\n",
},
}

var DefaultAkamaiMasquerades = []*Masquerade{
{
Domain: "a248.e.akamai.net",
IpAddress: "23.53.122.84",
},
{
Domain: "a248.e.akamai.net",
IpAddress: "2.19.198.29",
},
}

var DefaultCloudfrontMasquerades = []*Masquerade{
{
Domain: "www.amazon.ae",
IpAddress: "13.224.6.43",
IpAddress: "3.164.6.125",
},
{
Domain: "cloudfront.net",
Expand Down Expand Up @@ -393,8 +412,8 @@ var DefaultCloudfrontMasquerades = []*Masquerade{
IpAddress: "13.224.2.94",
},
{
Domain: "gbf.game-a.mbga.jp",
IpAddress: "13.224.0.132",
Domain: "www.amazon.com",
IpAddress: "23.199.14.80",
},
{
Domain: "cloudfront.net",
Expand Down Expand Up @@ -450,7 +469,7 @@ var DefaultCloudfrontMasquerades = []*Masquerade{
},
{
Domain: "alexa-comms-mobile-service.amazon.com",
IpAddress: "13.224.0.182",
IpAddress: "108.139.184.238",
},
{
Domain: "hkcp08.com",
Expand Down Expand Up @@ -722,7 +741,7 @@ var DefaultCloudfrontMasquerades = []*Masquerade{
},
{
Domain: "datadoghq.com",
IpAddress: "13.249.5.87",
IpAddress: "65.8.214.61",
},
{
Domain: "demandbase.com",
Expand Down Expand Up @@ -782,7 +801,7 @@ var DefaultCloudfrontMasquerades = []*Masquerade{
},
{
Domain: "mobile.mercadopago.com",
IpAddress: "99.86.1.210",
IpAddress: "108.158.166.197",
},
{
Domain: "www.awsapps.com",
Expand Down Expand Up @@ -940,10 +959,6 @@ var DefaultCloudfrontMasquerades = []*Masquerade{
Domain: "cloudfront.net",
IpAddress: "99.84.3.31",
},
{
Domain: "customerfi.com",
IpAddress: "13.224.0.137",
},
{
Domain: "www.linebc.jp",
IpAddress: "54.182.4.177",
Expand Down Expand Up @@ -998,11 +1013,11 @@ var DefaultCloudfrontMasquerades = []*Masquerade{
},
{
Domain: "mercadopago.com",
IpAddress: "13.249.6.109",
IpAddress: "13.227.126.107",
},
{
Domain: "www.stg.misumi-ec.com",
IpAddress: "99.86.2.175",
IpAddress: "52.192.248.133",
},
{
Domain: "cloudfront.net",
Expand All @@ -1014,7 +1029,7 @@ var DefaultCloudfrontMasquerades = []*Masquerade{
},
{
Domain: "www.amazon.sa",
IpAddress: "54.239.130.180",
IpAddress: "18.67.145.124",
},
{
Domain: "workflow-stage.licenses.adobe.com",
Expand Down
82 changes: 75 additions & 7 deletions direct.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"math/rand"
"math/rand/v2"
WendelHime marked this conversation as resolved.
Show resolved Hide resolved
"net"
"net/http"
"net/url"
Expand Down Expand Up @@ -65,7 +64,7 @@ func (d *direct) loadCandidates(initial map[string]*Provider) {
// ('inside-out' Fisher-Yates)
sh := make([]*Masquerade, size)
for i := 0; i < size; i++ {
j := rand.Intn(i + 1) // 0 <= j <= i
j := rand.IntN(i + 1) // 0 <= j <= i
sh[i] = sh[j]
sh[j] = arr[i]
}
Expand Down Expand Up @@ -181,7 +180,7 @@ func doCheck(client *http.Client, method string, expectedStatus int, u string) b
return false
}
if resp.Body != nil {
io.Copy(ioutil.Discard, resp.Body)
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
}
if resp.StatusCode != expectedStatus {
Expand Down Expand Up @@ -219,7 +218,7 @@ func (d *direct) RoundTripHijack(req *http.Request) (*http.Response, net.Conn, e
var err error
if isIdempotent && req.Body != nil {
// store body in-memory to be able to replay it if necessary
body, err = ioutil.ReadAll(req.Body)
body, err = io.ReadAll(req.Body)
if err != nil {
err := fmt.Errorf("unable to read request body: %v", err)
op.FailIf(err)
Expand All @@ -235,7 +234,7 @@ func (d *direct) RoundTripHijack(req *http.Request) (*http.Response, net.Conn, e
if !isIdempotent {
return req.Body
}
return ioutil.NopCloser(bytes.NewReader(body))
return io.NopCloser(bytes.NewReader(body))
}

tries := 1
Expand Down Expand Up @@ -411,10 +410,35 @@ func (d *direct) doDial(m *Masquerade) (conn net.Conn, retriable bool, err error
}

func (d *direct) dialServerWith(m *Masquerade) (net.Conn, error) {
op := ops.Begin("dial_server_with")
defer op.End()

op.Set("masquerade_domain", m.Domain)
op.Set("masquerade_ip", m.IpAddress)

tlsConfig := d.frontingTLSConfig(m)
dialTimeout := 10 * time.Second
sendServerNameExtension := false
addr := m.IpAddress
var sendServerNameExtension bool

// looking for provider and using SNI if enabled
provider := d.findProviderFromMasquerade(m)
if provider != nil && provider.SNIConfig != nil && provider.SNIConfig.UseArbitrarySNIs {
sendServerNameExtension = true

// selecting a random SNI
randomSNIIndex := rand.IntN(len(provider.SNIConfig.ArbitrarySNIs))
sniDomain := provider.SNIConfig.ArbitrarySNIs[randomSNIIndex]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we actually want this to be deterministic - and deterministic across clients too. The ideal scenario IMO is if any two clients in region R both send requests to IP X, they both use the same SNI. So perhaps we hash the masquerade IP and use the result modulo the set of SNIs to choose an SNI. Does that make sense?

A couple of minor points with my scheme: (1) If two clients have different lists, they will not end up with the same SNI. That is okay though; I think clients should only end up with different lists if they're in different regions. In that case, we don't need them to use the same SNI. (2) If the SNI list changes, then SNI-to-IP mappings will change. This is okay too; I don't expect us to change the SNI often.

Sorry, I know this is a new requirement added after the fact. I realize that can be frustrating. This didn't occur to me earlier =/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a crc32.ChecksumIEEE func call for hashing and made some changes for distributing SNIs per masquerade.


op.Set("arbitrary_sni", sniDomain)
tlsConfig.ServerName = sniDomain
tlsConfig.InsecureSkipVerify = true
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
log.Tracef("verifying peer certificate for masquerade domain %s", m.Domain)
return verifyPeerCertificate(rawCerts, verifiedChains, d.certPool, m.Domain)
}

}

_, _, err := net.SplitHostPort(addr)
if err != nil {
Expand All @@ -436,6 +460,50 @@ func (d *direct) dialServerWith(m *Masquerade) (net.Conn, error) {
return conn, err
}

func verifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate, roots *x509.CertPool, domain string) error {
WendelHime marked this conversation as resolved.
Show resolved Hide resolved
if len(rawCerts) == 0 {
return fmt.Errorf("no certificates presented")
}
cert, err := x509.ParseCertificate(rawCerts[0])
if err != nil {
return fmt.Errorf("unable to parse certificate: %v", err)
WendelHime marked this conversation as resolved.
Show resolved Hide resolved
}

masqueradeOpts := x509.VerifyOptions{
Roots: roots,
CurrentTime: time.Now(),
DNSName: domain,
Intermediates: x509.NewCertPool(),
}

for i := range rawCerts {
if i == 0 {
continue
}
crt, err := x509.ParseCertificate(rawCerts[i])
if err != nil {
return fmt.Errorf("unable to parse intermediate certificate: %v", err)
WendelHime marked this conversation as resolved.
Show resolved Hide resolved
}
masqueradeOpts.Intermediates.AddCert(crt)
}

_, masqueradeErr := cert.Verify(masqueradeOpts)
if masqueradeErr != nil {
return fmt.Errorf("certificate verification failed for masquerade: %v", masqueradeErr)
WendelHime marked this conversation as resolved.
Show resolved Hide resolved
}

return nil
}

func (d *direct) findProviderFromMasquerade(m *Masquerade) *Provider {
for _, masquerade := range d.masquerades {
if masquerade.Domain == m.Domain && masquerade.IpAddress == m.IpAddress {
return d.providers[masquerade.ProviderID]
}
}
return nil
}

// frontingTLSConfig builds a tls.Config for dialing the fronting domain. This is to establish the
// initial TCP connection to the CDN.
func (d *direct) frontingTLSConfig(m *Masquerade) *tls.Config {
Expand Down
Loading
Loading