@@ -9,13 +9,12 @@ import (
99
1010 "github.com/refraction-networking/conjure/pkg/registrars/lib"
1111 pb "github.com/refraction-networking/conjure/proto"
12- "github.com/refraction-networking/gotapdance/tapdance "
12+ tls "github.com/refraction-networking/utls "
1313
14- // td imports assets/
14+ // td imports assets/RegError/generateHTTPRequestBeginning
1515 td "github.com/refraction-networking/gotapdance/tapdance"
16- tls "github.com/refraction-networking/utls"
16+
1717 "github.com/sirupsen/logrus"
18- "google.golang.org/protobuf/proto"
1918)
2019
2120/**
@@ -30,6 +29,21 @@ const deadlineConnectTDStationMax = 14231
3029const deadlineTCPtoDecoyMin = deadlineConnectTDStationMin
3130const deadlineTCPtoDecoyMax = deadlineConnectTDStationMax
3231
32+ // Fixed-Size-Payload has a 1 byte flags field.
33+ // bit 0 (1 << 7) determines if flow is bidirectional(0) or upload-only(1)
34+ // bit 1 (1 << 6) enables dark-decoys
35+ // bits 2-5 are unassigned
36+ // bit 6 determines whether PROXY-protocol-formatted string will be sent
37+ // bit 7 (1 << 0) signals to use TypeLen outer proto
38+ var (
39+ tdFlagUploadOnly = uint8 (1 << 7 )
40+ // tdFlagDarkDecoy = uint8(1 << 6)
41+ tdFlagProxyHeader = uint8 (1 << 1 )
42+ tdFlagUseTIL = uint8 (1 << 0 )
43+ )
44+
45+ var default_flags = tdFlagUseTIL
46+
3347type DialFunc = func (ctx context.Context , network , addr string ) (net.Conn , error )
3448
3549type DecoyRegistrar struct {
@@ -41,10 +55,8 @@ type DecoyRegistrar struct {
4155 logger logrus.FieldLogger
4256
4357 // Fields taken from ConjureReg struct
44- m sync.Mutex
45- stats * pb.SessionStats
46- sessionIDStr string
47- covertAddress string
58+ m sync.Mutex
59+ stats * pb.SessionStats
4860}
4961
5062// CurrentClientLibraryVersion returns the current client library version used
@@ -71,61 +83,6 @@ func currentClientLibraryVersion() uint32 {
7183 // return 0
7284}
7385
74- // RegError - Registration Error passed during registration to indicate failure mode
75- type RegError struct {
76- code uint
77- msg string
78- }
79-
80- func NewRegError (code uint , msg string ) RegError {
81- return RegError {code : code , msg : msg }
82- }
83-
84- func (err RegError ) Error () string {
85- return fmt .Sprintf ("Registration Error [%v]: %v" , err .CodeStr (), err .msg )
86- }
87-
88- func (err RegError ) Code () uint {
89- return err .code
90- }
91-
92- // CodeStr - Get desctriptor associated with error code
93- func (err RegError ) CodeStr () string {
94- switch err .code {
95- case Unreachable :
96- return "UNREACHABLE"
97- case DialFailure :
98- return "DIAL_FAILURE"
99- case NotImplemented :
100- return "NOT_IMPLEMENTED"
101- case TLSError :
102- return "TLS_ERROR"
103- default :
104- return "UNKNOWN"
105- }
106- }
107-
108- const (
109- // Unreachable -Dial Error Unreachable -- likely network unavailable (i.e. ipv6 error)
110- Unreachable = iota
111-
112- // DialFailure - Dial Error Other than unreachable
113- DialFailure
114-
115- // NotImplemented - Related Function Not Implemented
116- NotImplemented
117-
118- // TLSError (Expired, Wrong-Host, Untrusted-Root, ...)
119- TLSError
120-
121- // Unknown - Error occurred without obvious explanation
122- Unknown
123- )
124-
125- func (r * DecoyRegistrar ) getPbTransport () pb.TransportType {
126- return r .Transport .ID ()
127- }
128-
12986func (r * DecoyRegistrar ) setTCPToDecoy (tcprtt * uint32 ) {
13087 r .m .Lock ()
13188 defer r .m .Unlock ()
@@ -136,76 +93,49 @@ func (r *DecoyRegistrar) setTCPToDecoy(tcprtt *uint32) {
13693 r .stats .TcpToDecoy = tcprtt
13794}
13895
139- func (reg * DecoyRegistrar ) setTLSToDecoy (tlsrtt * uint32 ) {
140- reg .m .Lock ()
141- defer reg .m .Unlock ()
96+ func (r * DecoyRegistrar ) setTLSToDecoy (tlsrtt * uint32 ) {
97+ r .m .Lock ()
98+ defer r .m .Unlock ()
14299
143- if reg .stats == nil {
144- reg .stats = & pb.SessionStats {}
100+ if r .stats == nil {
101+ r .stats = & pb.SessionStats {}
145102 }
146- reg .stats .TlsToDecoy = tlsrtt
103+ r .stats .TlsToDecoy = tlsrtt
147104}
148105
149- func (r * DecoyRegistrar ) generateClientToStation () (* pb.ClientToStation , error ) {
150- var covert * string
151- if len (r .covertAddress ) > 0 {
152- //[TODO]{priority:medium} this isn't the correct place to deal with signaling to the station
153- //transition = pb.C2S_Transition_C2S_SESSION_COVERT_INIT
154- covert = & r .covertAddress
155- }
156-
157- //[reference] Generate ClientToStation protobuf
158- // transition := pb.C2S_Transition_C2S_SESSION_INIT
159- currentGen := td .Assets ().GetGeneration ()
160- currentLibVer := currentClientLibraryVersion ()
161- transport := reg .getPbTransport ()
162- transportParams , err := reg .getPbTransportParams ()
163- if err != nil {
164- // Logger().Debugf("%s failed to marshal transport parameters ", reg.sessionIDStr)
165- }
166-
167- // remove type url to save space for DNS registration
168- // for server side changes see https://github.com/refraction-networking/conjure/pull/163
169- transportParams .TypeUrl = ""
170-
171- initProto := & pb.ClientToStation {
172- ClientLibVersion : & currentLibVer ,
173- CovertAddress : covert ,
174- DecoyListGeneration : & currentGen ,
175- V6Support : reg .getV6Support (),
176- V4Support : reg .getV4Support (),
177- Transport : & transport ,
178- Flags : reg .generateFlags (),
179- TransportParams : transportParams ,
180-
181- DisableRegistrarOverrides : & reg .ConjureSession .DisableRegistrarOverrides ,
182-
183- //[TODO]{priority:medium} specify width in C2S because different width might
184- // be useful in different regions (constant for now.)
185- }
106+ func (r * DecoyRegistrar ) GetRandomDuration (base , min , max int ) time.Duration {
107+ addon := getRandInt (min , max ) / 1000 // why this min and max???
108+ rtt := rttInt (r .getTcpToDecoy ())
109+ return time .Millisecond * time .Duration (base + rtt * addon )
110+ }
186111
187- if len (reg .phantomSNI ) > 0 {
188- initProto .MaskedDecoyServerName = & reg .phantomSNI
112+ func (r * DecoyRegistrar ) getTcpToDecoy () uint32 {
113+ r .m .Lock ()
114+ defer r .m .Unlock ()
115+ if r != nil {
116+ if r .stats != nil {
117+ return r .stats .GetTcpToDecoy ()
118+ }
189119 }
120+ return 0
121+ }
190122
191- for (proto .Size (initProto )+ AES_GCM_TAG_SIZE )% 3 != 0 {
192- initProto .Padding = append (initProto .Padding , byte (0 ))
123+ func generateFlags (cjSession * td.ConjureSession ) * pb.RegistrationFlags {
124+ flags := & pb.RegistrationFlags {}
125+ mask := default_flags
126+ if cjSession .UseProxyHeader {
127+ mask |= tdFlagProxyHeader
193128 }
194129
195- return initProto , nil
196- }
130+ uploadOnly := mask & tdFlagUploadOnly == tdFlagUploadOnly
131+ proxy := mask & tdFlagProxyHeader == tdFlagProxyHeader
132+ til := mask & tdFlagUseTIL == tdFlagUseTIL
197133
198- func NewDecoyRegistrar () * DecoyRegistrar {
199- return & DecoyRegistrar {
200- logger : tapdance .Logger (),
201- }
202- }
134+ flags .UploadOnly = & uploadOnly
135+ flags .ProxyHeader = & proxy
136+ flags .Use_TIL = & til
203137
204- func NewDecoyRegistrarWithDialer (dialer DialFunc ) * DecoyRegistrar {
205- return & DecoyRegistrar {
206- dialContex : dialer ,
207- logger : tapdance .Logger (),
208- }
138+ return flags
209139}
210140
211141func (r DecoyRegistrar ) createTLSConn (dialConn net.Conn , address string , hostname string , deadline time.Time ) (* tls.UConn , error ) {
@@ -241,39 +171,31 @@ func (r DecoyRegistrar) createTLSConn(dialConn net.Conn, address string, hostnam
241171 return tlsConn , nil
242172}
243173
244- func generateVSP () ([]byte , error ) {
245- c2s , err := reg .generateClientToStation ()
246- if err != nil {
247- return nil , err
248- }
249-
250- //[reference] Marshal ClientToStation protobuf
251- return proto .Marshal (c2s )
252- }
174+ // Register -> Send -> createRequest -> generateVSP -> generateClientToStation
253175
254- func (r * DecoyRegistrar ) createRequest (tlsConn * tls.UConn , decoy * pb.TLSDecoySpec ) ([]byte , error ) {
176+ func (r * DecoyRegistrar ) createRequest (tlsConn * tls.UConn , decoy * pb.TLSDecoySpec , cjSession * td. ConjureSession ) ([]byte , error ) {
255177 //[reference] generate and encrypt variable size payload
256- vsp , err := reg . generateVSP ()
178+ vsp , err := generateVSP (cjSession )
257179 if err != nil {
258180 return nil , err
259181 }
260182 if len (vsp ) > int (^ uint16 (0 )) {
261183 return nil , fmt .Errorf ("Variable-Size Payload exceeds %v" , ^ uint16 (0 ))
262184 }
263- encryptedVsp , err := aesGcmEncrypt (vsp , reg . keys .VspKey , reg . keys .VspIv )
185+ encryptedVsp , err := aesGcmEncrypt (vsp , cjSession . Keys .VspKey , cjSession . Keys .VspIv )
264186 if err != nil {
265187 return nil , err
266188 }
267189
268190 //[reference] generate and encrypt fixed size payload
269- fsp := reg . generateFSP (uint16 (len (encryptedVsp )))
270- encryptedFsp , err := aesGcmEncrypt (fsp , reg . keys .FspKey , reg . keys .FspIv )
191+ fsp := generateFSP (uint16 (len (encryptedVsp )))
192+ encryptedFsp , err := aesGcmEncrypt (fsp , cjSession . Keys .FspKey , cjSession . Keys .FspIv )
271193 if err != nil {
272194 return nil , err
273195 }
274196
275197 var tag []byte // tag will be base-64 style encoded
276- tag = append (encryptedVsp , reg . keys .Representative ... )
198+ tag = append (encryptedVsp , cjSession . Keys .Representative ... )
277199 tag = append (tag , encryptedFsp ... )
278200
279201 httpRequest := generateHTTPRequestBeginning (decoy .GetHostname ())
@@ -289,7 +211,7 @@ func (r *DecoyRegistrar) createRequest(tlsConn *tls.UConn, decoy *pb.TLSDecoySpe
289211 return httpRequest , nil
290212}
291213
292- func (r DecoyRegistrar ) Register (cjSession * tapdance .ConjureSession , ctx context.Context ) (* tapdance .ConjureReg , error ) {
214+ func (r DecoyRegistrar ) Register (cjSession * td .ConjureSession , ctx context.Context ) (* td .ConjureReg , error ) {
293215 logger := r .logger .WithFields (logrus.Fields {"type" : "unidirectional" , "sessionID" : cjSession .IDString ()})
294216
295217 logger .Debugf ("Registering V4 and V6 via DecoyRegistrar" )
@@ -326,15 +248,15 @@ func (r DecoyRegistrar) Register(cjSession *tapdance.ConjureSession, ctx context
326248 for _ , decoy := range decoys {
327249 logger .Debugf ("Sending Reg: %v, %v" , decoy .GetHostname (), decoy .GetIpAddrStr ())
328250 //decoyAddr := decoy.GetIpAddrStr()
329- go r .Send (ctx , reg , decoy , dialErrors )
251+ go r .Send (ctx , cjSession , decoy , dialErrors )
330252 }
331253
332254 //[reference] Dial errors happen immediately so block until all N dials complete
333255 var unreachableCount uint = 0
334256 for err := range dialErrors {
335257 if err != nil {
336258 logger .Debugf ("%v" , err )
337- if dialErr , ok := err .(tapdance .RegError ); ok && dialErr .Code () == tapdance .Unreachable {
259+ if dialErr , ok := err .(td .RegError ); ok && dialErr .Code () == td .Unreachable {
338260 // If we failed because ipv6 network was unreachable try v4 only.
339261 unreachableCount ++
340262 if unreachableCount < width {
@@ -351,18 +273,19 @@ func (r DecoyRegistrar) Register(cjSession *tapdance.ConjureSession, ctx context
351273 //[reference] if ALL fail to dial return error (retry in parent if ipv6 unreachable)
352274 if unreachableCount == width {
353275 logger .Debugf ("NETWORK UNREACHABLE" )
354- return nil , tapdance .NewRegError (tapdance .Unreachable , "All decoys failed to register -- Dial Unreachable" )
276+ return nil , td .NewRegError (td .Unreachable , "All decoys failed to register -- Dial Unreachable" )
355277 }
356278
357279 // randomized sleeping here to break the intraflow signal
358- toSleep := reg .GetRandomDuration (3000 , 212 , 3449 )
280+ // TODO: is this okay?
281+ toSleep := r .GetRandomDuration (3000 , 212 , 3449 )
359282 logger .Debugf ("Successfully sent registrations, sleeping for: %v" , toSleep )
360283 lib .SleepWithContext (ctx , toSleep )
361284
362285 return reg , nil
363286}
364287
365- func (r * DecoyRegistrar ) Send (ctx context.Context , reg * tapdance. ConjureReg , decoy * pb.TLSDecoySpec , dialError chan error ) {
288+ func (r * DecoyRegistrar ) Send (ctx context.Context , cjSession * td. ConjureSession , decoy * pb.TLSDecoySpec , dialError chan error ) {
366289
367290 deadline , deadlineAlreadySet := ctx .Deadline ()
368291 if ! deadlineAlreadySet {
@@ -380,7 +303,7 @@ func (r *DecoyRegistrar) Send(ctx context.Context, reg *tapdance.ConjureReg, dec
380303 r .setTCPToDecoy (durationToU32ptrMs (time .Since (tcpToDecoyStartTs )))
381304 if err != nil {
382305 if opErr , ok := err .(* net.OpError ); ok && opErr .Err .Error () == "connect: network is unreachable" {
383- dialError <- RegError { msg : err .Error (), code : Unreachable }
306+ dialError <- td . NewRegError ( td . Unreachable , err .Error ())
384307 return
385308 }
386309 dialError <- err
@@ -397,16 +320,16 @@ func (r *DecoyRegistrar) Send(ctx context.Context, reg *tapdance.ConjureReg, dec
397320 if err != nil {
398321 dialConn .Close ()
399322 msg := fmt .Sprintf ("%v - %v createConn: %v" , decoy .GetHostname (), decoy .GetIpAddrStr (), err .Error ())
400- dialError <- RegError { msg : msg , code : TLSError }
323+ dialError <- td . NewRegError ( td . TLSError , msg )
401324 return
402325 }
403326 r .setTLSToDecoy (durationToU32ptrMs (time .Since (tlsToDecoyStartTs )))
404327
405328 //[reference] Create the HTTP request for the registration
406- httpRequest , err := reg .createRequest (tlsConn , decoy )
329+ httpRequest , err := r .createRequest (tlsConn , decoy , cjSession )
407330 if err != nil {
408331 msg := fmt .Sprintf ("%v - %v createReq: %v" , decoy .GetHostname (), decoy .GetIpAddrStr (), err .Error ())
409- dialError <- RegError { msg : msg , code : TLSError }
332+ dialError <- td . NewRegError ( td . TLSError , msg )
410333 return
411334 }
412335
@@ -417,17 +340,10 @@ func (r *DecoyRegistrar) Send(ctx context.Context, reg *tapdance.ConjureReg, dec
417340 // Logger().Errorf("%v - %v Could not send Conjure registration request, error: %v", decoy.GetHostname(), decoy.GetIpAddrStr(), err.Error())
418341 tlsConn .Close ()
419342 msg := fmt .Sprintf ("%v - %v Write: %v" , decoy .GetHostname (), decoy .GetIpAddrStr (), err .Error ())
420- dialError <- RegError { msg : msg , code : TLSError }
343+ dialError <- td . NewRegError ( td . TLSError , msg )
421344 return
422345 }
423346
424347 dialError <- nil
425348 readAndClose (dialConn , time .Second * 15 )
426349}
427-
428- // Move to other file eventually?
429- func GetRandomDuration (base , min , max int ) time.Duration {
430- addon := getRandInt (min , max ) / 1000 // why this min and max???
431- rtt := rttInt (reg .getTcpToDecoy ())
432- return time .Millisecond * time .Duration (base + rtt * addon )
433- }
0 commit comments