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

group client config requests #1395

Merged
merged 63 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
c77d8e7
group config requests, make config/bypass services
garmr-ulfr Jul 16, 2024
458393b
renamed fetcher.go to http.go
garmr-ulfr Jul 16, 2024
7b8362a
specify interval/jitter instead of min/max waitSeconds
garmr-ulfr Jul 17, 2024
caa7830
use lc apipb types instead of re-defining them
garmr-ulfr Jul 19, 2024
bdf1d04
fix: double close on done chan, stop actually stops service
garmr-ulfr Jul 23, 2024
0220c2d
use new bypass service and config service for proxies
garmr-ulfr Jul 23, 2024
7ac64ab
convert configService to singleton
garmr-ulfr Jul 25, 2024
0cf7c5d
register listeners for config changes
garmr-ulfr Jul 25, 2024
537e9a1
add config handler to service, use new config service for geolocation
garmr-ulfr Jul 30, 2024
754652e
remove lantern-cloud dependency
garmr-ulfr Jul 31, 2024
7f8e54c
address comments on PR
garmr-ulfr Aug 2, 2024
ac9f67b
don't start configService if sticky is true
garmr-ulfr Aug 5, 2024
168b5f5
add config/proxy and services package descriptions
garmr-ulfr Aug 7, 2024
b3a06f5
add exponential backoff on post error
garmr-ulfr Aug 7, 2024
01036ba
add tests
garmr-ulfr Aug 12, 2024
e85c2b9
use status code to check if there are config chagnes
garmr-ulfr Aug 13, 2024
2217773
add http tests
garmr-ulfr Aug 13, 2024
84c5362
add configservice tests
garmr-ulfr Aug 14, 2024
342bf35
use temp dir in tests
garmr-ulfr Aug 14, 2024
2fbb05a
remove goto and create a func instead
garmr-ulfr Aug 15, 2024
cb6891a
pass http.Request to post/doPost
garmr-ulfr Aug 16, 2024
6d9a0eb
pass ctx to GetConfig instead of a timeout
garmr-ulfr Aug 16, 2024
2811f3d
make jitter constant and no longer configurable
garmr-ulfr Aug 16, 2024
d52c170
rename proxyconfig to userconfig
garmr-ulfr Aug 19, 2024
bd1e22a
update config filename and logger
garmr-ulfr Aug 19, 2024
d9a45ab
rename ConfigRequest.Proxy.Ids to ConfigRequest.Proxy.Names
garmr-ulfr Aug 20, 2024
d7a78ce
mod tidy
garmr-ulfr Aug 27, 2024
b266d73
fix infinite wait when starting config service
garmr-ulfr Aug 27, 2024
3cad8f2
using proxy.conf temporarily for lantern-client github tests
garmr-ulfr Aug 28, 2024
ecde33a
log if no existing config found
garmr-ulfr Aug 29, 2024
df62522
revert config filename
garmr-ulfr Aug 29, 2024
f949567
use new userconfig in test helper
garmr-ulfr Sep 5, 2024
f83132b
fix: create temp dir
garmr-ulfr Sep 5, 2024
8d10c86
separate proto listener addr and port
garmr-ulfr Sep 10, 2024
f87926b
use protobuf in test helper
garmr-ulfr Sep 13, 2024
50dabf0
un-deprecate http(s) server addrs, fix nil configHandler
garmr-ulfr Sep 16, 2024
135b93b
removed depricated helper fields
garmr-ulfr Sep 26, 2024
008ad9e
return error if country/ip haven't been set yet
garmr-ulfr Sep 26, 2024
08c69d5
update config endpoint url
garmr-ulfr Sep 30, 2024
66d4c15
don't log user config
garmr-ulfr Oct 2, 2024
0910899
Merge branch 'main' into group-client-reqs
garmr-ulfr Oct 30, 2024
cdb743d
register config listener before initializing userconfig
garmr-ulfr Nov 12, 2024
4e85451
Merge branch 'main' into group-client-reqs
garmr-ulfr Nov 12, 2024
b8c67d8
retry fetch if failed, actually using backoff
garmr-ulfr Nov 13, 2024
acc3ce1
add service name to callRandomly for logging
garmr-ulfr Nov 13, 2024
d5b39cb
fix: user config requests failing if a stale config already exists on…
garmr-ulfr Nov 13, 2024
7ef0caf
fix TestNotifyOnChange failing
garmr-ulfr Nov 13, 2024
455de42
fix TestStagingSetup failing, use new /config endpoint
garmr-ulfr Nov 13, 2024
2612e45
use multiplex addrs in integrationtest
garmr-ulfr Nov 14, 2024
b11f96c
Merge branch 'main' into group-client-reqs
garmr-ulfr Nov 15, 2024
9806b67
remove leftover bandit.go from merge
garmr-ulfr Nov 15, 2024
a40af6a
get country/ip from config directly instead of storing locally on new…
garmr-ulfr Nov 18, 2024
9ffbb9c
update api url
garmr-ulfr Nov 18, 2024
d7f8705
init userconfig in New to load existing config immediately
garmr-ulfr Nov 18, 2024
153a5aa
wait for fastconnect dialer to set topDialer
garmr-ulfr Nov 18, 2024
63b6043
use Fronted rt
garmr-ulfr Nov 19, 2024
fb0b3b8
more logging
garmr-ulfr Nov 19, 2024
edfbffc
check for empty client info before assigning
garmr-ulfr Nov 19, 2024
ff487ae
Merge branch 'main' into group-client-reqs
garmr-ulfr Nov 19, 2024
e01b110
switch back to chainedthenfronted
garmr-ulfr Nov 22, 2024
7372114
more logging
garmr-ulfr Nov 22, 2024
ee02a2b
add routing rule for iantem.io
garmr-ulfr Nov 22, 2024
be1c965
Merge branch 'main' into group-client-reqs
garmr-ulfr Nov 22, 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
220 changes: 220 additions & 0 deletions apipb/legacy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
// Copied from lantern-cloud: e57d588aa976ca9d1a8531c92972e20a7d1640f9
garmr-ulfr marked this conversation as resolved.
Show resolved Hide resolved
//
// This file should be kept in sync with lantern-cloud
package apipb

import (
"crypto/tls"
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"math"
"net"
"strconv"
"strings"

commonconfig "github.com/getlantern/common/config"
)

// Values configured uniformly on all clients. Note that we have no mechanism for updating these
// values for existing client-proxy assignments.
const (
tlsClientHelloSplitting = false
tlsClientHelloID = "HelloBrowser"
)

// For flashlight, since it doesn't accept an empty string.
var defaultTLSSuites string

func init() {
suites := make([]string, 0)
for _, suite := range tls.CipherSuites() {
suites = append(suites, fmt.Sprintf("0x%04x", suite.ID))
}

defaultTLSSuites = strings.Join(suites, ",")
}

// ProxyToLegacyConfig converts a ProxyConnectConfig to the legacy format
func ProxyToLegacyConfig(cfg *ProxyConnectConfig) (*commonconfig.ProxyConfig, error) {
legacy := new(commonconfig.ProxyConfig)

legacy.Name = cfg.Name
legacy.Addr = fmt.Sprintf("%s:%d", cfg.Addr, cfg.Port)
legacy.Cert = string(cfg.CertPem)
legacy.AuthToken = cfg.AuthToken
legacy.Trusted = cfg.Trusted
legacy.Bias = 9 // bias clients towards using lantern-cloud proxies

if cfg.Location != nil {
legacy.Location = &commonconfig.ProxyConfig_ProxyLocation{
City: cfg.Location.City,
Country: cfg.Location.Country,
CountryCode: cfg.Location.CountryCode,
Latitude: cfg.Location.Latitude,
Longitude: cfg.Location.Longitude,
}
}

legacy.Track = cfg.Track
legacy.Region = "platinum" // TODO: is region required?

switch pCfg := cfg.ProtocolConfig.(type) {
case *ProxyConnectConfig_ConnectCfgTls:
legacy.PluggableTransport = "https"
// currently, lantern-cloud uses multiplexing for all https connections so we set the
// multiplexed addr to the same as the addr
legacy.MultiplexedAddr = legacy.Addr

// TLS-level config
legacy.TLSClientHelloSplitting = tlsClientHelloSplitting
legacy.TLSClientHelloID = tlsClientHelloID
legacy.TLSServerNameIndicator = pCfg.ConnectCfgTls.ServerNameIndicator

ss, err := serializeTLSSessionState(pCfg.ConnectCfgTls.SessionState)
if err != nil {
return nil, fmt.Errorf("serialize TLS session error: %w", err)
}

legacy.TLSClientSessionState = ss
legacy.PluggableTransportSettings = map[string]string{}

if pCfg.ConnectCfgTls.TlsFrag != "" {
legacy.PluggableTransportSettings["tlsfrag"] = pCfg.ConnectCfgTls.TlsFrag
}

case *ProxyConnectConfig_ConnectCfgTlsmasq:
legacy.PluggableTransport = "tlsmasq"

// TLS-level config
legacy.TLSClientHelloSplitting = tlsClientHelloSplitting
legacy.TLSClientHelloID = tlsClientHelloID

tlsmasqCfg := pCfg.ConnectCfgTlsmasq

tlsmasqOrigin, _, err := net.SplitHostPort(tlsmasqCfg.OriginAddr)
if err != nil {
return nil, fmt.Errorf("bad tlsmasq origin addr: %w", err)
}

tlsmasqSuites := strings.Join(tlsmasqCfg.TlsSupportedCipherSuites, ",")

// An empty list should indicate the default, but flashlight doesn't
// like that.
if len(tlsmasqCfg.TlsSupportedCipherSuites) == 0 {
tlsmasqSuites = defaultTLSSuites
}

legacy.PluggableTransportSettings = map[string]string{
"tlsmasq_secret": hex.EncodeToString(tlsmasqCfg.Secret),
"tlsmasq_sni": tlsmasqOrigin,
"tlsmasq_tlsminversion": tlsmasqCfg.TlsMinVersion,
"tlsmasq_suites": tlsmasqSuites,
}

if pCfg.ConnectCfgTlsmasq.TlsFrag != "" {
legacy.PluggableTransportSettings["tlsfrag"] = pCfg.ConnectCfgTlsmasq.TlsFrag
}

case *ProxyConnectConfig_ConnectCfgShadowsocks:
legacy.PluggableTransport = "shadowsocks"
legacy.MultiplexedAddr = legacy.Addr

ssCfg := pCfg.ConnectCfgShadowsocks

legacy.PluggableTransportSettings = map[string]string{
"shadowsocks_secret": ssCfg.Secret,
"shadowsocks_cipher": ssCfg.Cipher,
"shadowsocks_prefix_generator": ssCfg.PrefixGenerator,
"shadowsocks_with_tls": strconv.FormatBool(ssCfg.WithTls),
}

case *ProxyConnectConfig_ConnectCfgBroflake:
legacy.PluggableTransport = "broflake"
legacy.Addr = "broflake"

bbCfg := pCfg.ConnectCfgBroflake
legacy.StunServers = bbCfg.StunServers

legacy.PluggableTransportSettings = map[string]string{
"broflake_ctablesize": strconv.Itoa(int(bbCfg.CtableSize)),
"broflake_ptablesize": strconv.Itoa(int(bbCfg.PtableSize)),
"broflake_natfailtimeout": strconv.Itoa(int(bbCfg.NatFailTimeout)),
"broflake_icefailtimeout": strconv.Itoa(int(bbCfg.IceFailTimeout)),
"broflake_discoverysrv": bbCfg.DiscoverySrv,
"broflake_endpoint": bbCfg.Endpoint,
"broflake_egress_server_name": bbCfg.EgressServerName,
"broflake_egress_insecure_skip_verify": strconv.FormatBool(bbCfg.EgressInsecureSkipVerify),
"broflake_egress_ca": bbCfg.EgressCa,
"broflake_stunbatchsize": strconv.Itoa(int(bbCfg.StunBatchSize)),
}

legacy.Bias = 10 // bias clients toward broflake
legacy.AllowedDomains = []string{ // currently, we only send ad traffic through Broflake
"doubleclick.net",
"adservice.google.com",
"adservice.google.com.hk",
"adservice.google.co.jp",
"adservice.google.nl",
"googlesyndication.com",
"googletagservices.com",
"googleadservices.com",
}

case *ProxyConnectConfig_ConnectCfgStarbridge:
legacy.PluggableTransport = "starbridge"

legacy.PluggableTransportSettings = map[string]string{
"starbridge_public_key": pCfg.ConnectCfgStarbridge.PublicKey,
}

case *ProxyConnectConfig_ConnectCfgAlgeneva:
legacy.PluggableTransport = "algeneva"
legacy.PluggableTransportSettings = map[string]string{
"algeneva_strategy": pCfg.ConnectCfgAlgeneva.Strategy,
}
case *ProxyConnectConfig_ConnectCfgWater:
legacy.PluggableTransport = "water"
legacy.PluggableTransportSettings = map[string]string{
"water_wasm": base64.StdEncoding.EncodeToString(pCfg.ConnectCfgWater.Wasm),
"water_transport": pCfg.ConnectCfgWater.Transport,
}

default:
return nil, fmt.Errorf("unsupported protocol config: %T", cfg.ProtocolConfig)
}

return legacy, nil
}

// serializeTLSSessionState serializes the input TLS session state. This format is the one expected
// by clients in the legacy config. When we move away from the legacy config, clients can just read
// the session state out of the protcol buffers message.
func serializeTLSSessionState(ss *ProxyConnectConfig_TLSConfig_SessionState) (string, error) {
type sessionState struct {
SessionTicket []uint8
Vers uint16
CipherSuite uint16
MasterSecret []byte
}

if ss.Version > math.MaxUint16 {
return "", errors.New("invalid version")
} else if ss.CipherSuite > math.MaxUint16 {
return "", errors.New("invalid cipher suite")
}

b, err := json.Marshal(sessionState{
SessionTicket: ss.SessionTicket,
Vers: uint16(ss.Version),
CipherSuite: uint16(ss.CipherSuite),
MasterSecret: ss.MasterSecret,
})
if err != nil {
return "", fmt.Errorf("marshal error: %w", err)
}

return base64.StdEncoding.EncodeToString(b), nil
}
Loading
Loading