mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 20:11:19 -04:00
Forward bridge fingerprint
gitlab 28651
This commit is contained in:
parent
281d917beb
commit
b563141c6a
7 changed files with 41 additions and 11 deletions
|
@ -139,10 +139,11 @@ func (ctx *BrokerContext) AddSnowflake(id string, proxyType string, natType stri
|
|||
return snowflake
|
||||
}
|
||||
|
||||
// Client offer contains an SDP and the NAT type of the client
|
||||
// Client offer contains an SDP, bridge fingerprint and the NAT type of the client
|
||||
type ClientOffer struct {
|
||||
natType string
|
||||
sdp []byte
|
||||
fingerprint string
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -132,6 +132,7 @@ func (i *IPC) ClientOffers(arg messages.Arg, response *[]byte) error {
|
|||
offer := &ClientOffer{
|
||||
natType: req.NAT,
|
||||
sdp: []byte(req.Offer),
|
||||
fingerprint: req.Fingerprint,
|
||||
}
|
||||
|
||||
// Only hand out known restricted snowflakes to unrestricted clients
|
||||
|
|
|
@ -43,6 +43,7 @@ type BrokerChannel struct {
|
|||
keepLocalAddresses bool
|
||||
natType string
|
||||
lock sync.Mutex
|
||||
BridgeFingerprint string
|
||||
}
|
||||
|
||||
// We make a copy of DefaultTransport because we want the default Dial
|
||||
|
@ -92,6 +93,7 @@ func newBrokerChannelFromConfig(config ClientConfig) (*BrokerChannel, error) {
|
|||
Rendezvous: rendezvous,
|
||||
keepLocalAddresses: config.KeepLocalAddresses,
|
||||
natType: nat.NATUnknown,
|
||||
BridgeFingerprint: config.BridgeFingerprint,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -118,6 +120,7 @@ func (bc *BrokerChannel) Negotiate(offer *webrtc.SessionDescription) (
|
|||
req := &messages.ClientPollRequest{
|
||||
Offer: offerSDP,
|
||||
NAT: bc.natType,
|
||||
Fingerprint: bc.BridgeFingerprint,
|
||||
}
|
||||
encReq, err := req.EncodeClientPollRequest()
|
||||
bc.lock.Unlock()
|
||||
|
|
|
@ -103,6 +103,9 @@ type ClientConfig struct {
|
|||
// UTLSRemoveSNI is the flag to control whether SNI should be removed from Client Hello
|
||||
// when uTLS is used.
|
||||
UTLSRemoveSNI bool
|
||||
// BridgeFingerprint is the fingerprint of the bridge that the client will eventually
|
||||
// connect to, as specified in the Bridge line of the torrc.
|
||||
BridgeFingerprint string
|
||||
}
|
||||
|
||||
// NewSnowflakeClient creates a new Snowflake transport client that can spawn multiple
|
||||
|
|
|
@ -95,6 +95,9 @@ func socksAcceptLoop(ln *pt.SocksListener, config sf.ClientConfig, shutdown chan
|
|||
if arg, ok := conn.Req.Args.Get("utls-imitate"); ok {
|
||||
config.UTLSClientID = arg
|
||||
}
|
||||
if arg, ok := conn.Req.Args.Get("fingerprint"); ok {
|
||||
config.BridgeFingerprint = arg
|
||||
}
|
||||
transport, err := sf.NewSnowflakeClient(config)
|
||||
if err != nil {
|
||||
conn.Reject()
|
||||
|
|
|
@ -3,6 +3,6 @@ DataDirectory datadir
|
|||
|
||||
ClientTransportPlugin snowflake exec ./client -log snowflake.log
|
||||
|
||||
Bridge snowflake 192.0.2.3:1 url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ front=cdn.sstatic.net ice=stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478
|
||||
Bridge snowflake 192.0.2.3:1 2B280B23E1107BB62ABFC40DDCC8824814F80A72 fingerprint=2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ front=cdn.sstatic.net ice=stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478
|
||||
|
||||
SocksPort auto
|
||||
|
|
|
@ -29,10 +29,13 @@ each encoded in JSON format
|
|||
{
|
||||
offer: <sdp offer>
|
||||
[nat: (unknown|restricted|unrestricted)]
|
||||
[fingerprint: <fingerprint string>]
|
||||
}
|
||||
|
||||
The NAT field is optional, and if it is missing a
|
||||
value of "unknown" will be assumed.
|
||||
value of "unknown" will be assumed. The fingerprint
|
||||
is also optional and, if absent, will be assigned the
|
||||
fingerprint of the default bridge.
|
||||
|
||||
== ClientPollResponse ==
|
||||
<poll response> :=
|
||||
|
@ -49,13 +52,25 @@ for the error.
|
|||
|
||||
*/
|
||||
|
||||
// The bridge fingerprint to assume, for client poll requests that do not
|
||||
// specify a fingerprint. Before #28651, there was only one bridge with one
|
||||
// fingerprint, which all clients expected to be connected to implicitly.
|
||||
// If a client is old enough that it does not specify a fingerprint, this is
|
||||
// the fingerprint it expects. Clients that do set a fingerprint in the
|
||||
// SOCKS params will also be assumed to want to connect to the default bridge.
|
||||
const defaultBridgeFingerprint = "2B280B23E1107BB62ABFC40DDCC8824814F80A72"
|
||||
|
||||
type ClientPollRequest struct {
|
||||
Offer string `json:"offer"`
|
||||
NAT string `json:"nat"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
}
|
||||
|
||||
// Encodes a poll message from a snowflake client
|
||||
func (req *ClientPollRequest) EncodeClientPollRequest() ([]byte, error) {
|
||||
if req.Fingerprint == "" {
|
||||
req.Fingerprint = defaultBridgeFingerprint
|
||||
}
|
||||
body, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -87,6 +102,10 @@ func DecodeClientPollRequest(data []byte) (*ClientPollRequest, error) {
|
|||
return nil, fmt.Errorf("no supplied offer")
|
||||
}
|
||||
|
||||
if message.Fingerprint == "" {
|
||||
message.Fingerprint = defaultBridgeFingerprint
|
||||
}
|
||||
|
||||
switch message.NAT {
|
||||
case "":
|
||||
message.NAT = nat.NATUnknown
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue