|
1 | | -package registration |
| 1 | +package decoy |
2 | 2 |
|
3 | 3 | import ( |
4 | 4 | "context" |
| 5 | + "errors" |
| 6 | + "fmt" |
5 | 7 | "net" |
| 8 | + "time" |
6 | 9 |
|
7 | 10 | pb "github.com/refraction-networking/conjure/proto" |
8 | 11 | "github.com/refraction-networking/gotapdance/tapdance" |
9 | 12 | "github.com/sirupsen/logrus" |
10 | 13 | ) |
11 | 14 |
|
| 15 | +// Copied from dns-registrar |
| 16 | +var ( |
| 17 | + ErrRegFailed = errors.New("registration failed") |
| 18 | +) |
| 19 | + |
12 | 20 | type DialFunc func(ctx context.Context, network, addr string) (net.Conn, error) |
13 | 21 |
|
14 | 22 | type DecoyRegistrar struct { |
@@ -70,6 +78,7 @@ func (r DecoyRegistrar) Register(cjSession *tapdance.ConjureSession, ctx context |
70 | 78 | for _, decoy := range decoys { |
71 | 79 | logger.Debugf("Sending Reg: %v, %v", decoy.GetHostname(), decoy.GetIpAddrStr()) |
72 | 80 | //decoyAddr := decoy.GetIpAddrStr() |
| 81 | + // r.Send() |
73 | 82 | go reg.Send(ctx, decoy, dialErrors) |
74 | 83 | } |
75 | 84 |
|
@@ -105,3 +114,74 @@ func (r DecoyRegistrar) Register(cjSession *tapdance.ConjureSession, ctx context |
105 | 114 |
|
106 | 115 | return reg, nil |
107 | 116 | } |
| 117 | + |
| 118 | +func (r DecoyRegistrar) Send(ctx context.Context, decoy *pb.TLSDecoySpec, dialErrors chan error) { |
| 119 | + deadline, deadlineAlreadySet := ctx.Deadline() |
| 120 | + |
| 121 | + if !deadlineAlreadySet { |
| 122 | + deadline = time.Now().Add(tapdance.GetRandomDuration(tapdance.deadlineTCPtoDecoyMin, tapdance.deadlineTCPtoDecoyMax)) |
| 123 | + } |
| 124 | + |
| 125 | + childCtx, childCancelFunc := context.WithDeadline(ctx, deadline) |
| 126 | + defer childCancelFunc() |
| 127 | + |
| 128 | + //[reference] TCP to decoy |
| 129 | + tcpToDecoyStartTs := time.Now() |
| 130 | + |
| 131 | + //[Note] decoy.GetIpAddrStr() will get only v4 addr if a decoy has both |
| 132 | + dialConn, err := r.dialContex(childCtx, "tcp", decoy.GetIpAddrStr()) |
| 133 | + |
| 134 | + reg.setTCPToDecoy(tapdance.durationToU32ptrMs(time.Since(tcpToDecoyStartTs))) |
| 135 | + if err != nil { |
| 136 | + if opErr, ok := err.(*net.OpError); ok && opErr.Err.Error() == "connect: network is unreachable" { |
| 137 | + dialError <- RegError{msg: err.Error(), code: Unreachable} |
| 138 | + return |
| 139 | + } |
| 140 | + dialError <- err |
| 141 | + return |
| 142 | + } |
| 143 | + |
| 144 | + //[reference] connection stats tracking |
| 145 | + rtt := rttInt(uint32(time.Since(tcpToDecoyStartTs).Milliseconds())) |
| 146 | + delay := getRandomDuration(1061*rtt*2, 1953*rtt*3) //[TODO]{priority:@sfrolov} why these values?? |
| 147 | + TLSDeadline := time.Now().Add(delay) |
| 148 | + |
| 149 | + tlsToDecoyStartTs := time.Now() |
| 150 | + tlsConn, err := reg.createTLSConn(dialConn, decoy.GetIpAddrStr(), decoy.GetHostname(), TLSDeadline) |
| 151 | + if err != nil { |
| 152 | + dialConn.Close() |
| 153 | + msg := fmt.Sprintf("%v - %v createConn: %v", decoy.GetHostname(), decoy.GetIpAddrStr(), err.Error()) |
| 154 | + dialError <- RegError{msg: msg, code: TLSError} |
| 155 | + return |
| 156 | + } |
| 157 | + reg.setTLSToDecoy(durationToU32ptrMs(time.Since(tlsToDecoyStartTs))) |
| 158 | + |
| 159 | + //[reference] Create the HTTP request for the registration |
| 160 | + httpRequest, err := reg.createRequest(tlsConn, decoy) |
| 161 | + if err != nil { |
| 162 | + msg := fmt.Sprintf("%v - %v createReq: %v", decoy.GetHostname(), decoy.GetIpAddrStr(), err.Error()) |
| 163 | + dialError <- RegError{msg: msg, code: TLSError} |
| 164 | + return |
| 165 | + } |
| 166 | + |
| 167 | + //[reference] Write reg into conn |
| 168 | + _, err = tlsConn.Write(httpRequest) |
| 169 | + if err != nil { |
| 170 | + // // This will not get printed because it is executed in a goroutine. |
| 171 | + // Logger().Errorf("%v - %v Could not send Conjure registration request, error: %v", decoy.GetHostname(), decoy.GetIpAddrStr(), err.Error()) |
| 172 | + tlsConn.Close() |
| 173 | + msg := fmt.Sprintf("%v - %v Write: %v", decoy.GetHostname(), decoy.GetIpAddrStr(), err.Error()) |
| 174 | + dialError <- RegError{msg: msg, code: TLSError} |
| 175 | + return |
| 176 | + } |
| 177 | + |
| 178 | + dialError <- nil |
| 179 | + readAndClose(dialConn, time.Second*15) |
| 180 | +} |
| 181 | + |
| 182 | +// Move to other file eventually? |
| 183 | +func GetRandomDuration(base, min, max int) time.Duration { |
| 184 | + addon := getRandInt(min, max) / 1000 // why this min and max??? |
| 185 | + rtt := rttInt(reg.getTcpToDecoy()) |
| 186 | + return time.Millisecond * time.Duration(base+rtt*addon) |
| 187 | +} |
0 commit comments