[strelaysrv] connects to relays.st.net via host interface

I’m trying to set up a strelaysrv on a fixed IP and keep getting

https://relays.syncthing.net/endpoint failed to join due to IP address not matching external address. Aborting

My setup is: some linux machine, default ip address ( hostname/ip ‘argh’ ).

I’ve set up IPtables to add with portmapping 43443 to 443 on hosts network device ( hostname/ip ‘srs’ ), pinched a hole into the fw, got a signed tls-cert for ‘srs’ and start up strelaysrv (master) with

home/go/src/github.com/syncthing/syncthing/bin/strelaysrv \
        -ext-address=srs.molgen.mpg.de:443 \
        -status-srv= \
        -listen=srs.molgen.mpg.de:43443 \
        -keys=keys \
        -provided-by='molgen.mpg.de' \

This fails with

2018/02/08 13:21:39 pool.go:17: Joining https://relays.syncthing.net/endpoint
2018/02/08 13:21:40 pool.go:46: https://relays.syncthing.net/endpoint failed to join due to IP address not matching external address. Aborting

Now I hook onto our gateway running tcpdump host relays.syncthing.net -s 2000 -A and see the following (unexepected) packets:

first packet:

13:41:11.541457 IP argh.molgen.mpg.de.45510 > web.syncthing.net.https: Flags [S], seq 2056789667, win 29200, options [mss 1460,sackOK,TS val 1097373193 ecr 0,nop,wscale 9], length 0

That’s ‘argh’ not ‘srs’ who is trying to set up TLS handshake. So web.syncthing.net is answering:

13:41:11.555848 IP web.syncthing.net.https > argh.molgen.mpg.de.45510: Flags [S.], seq 2645348148, ack 2056789668, win 28960, options [mss 1460,sackOK,TS val 329229677 ecr 1097373193,nop,wscale 6], length 0
E..<..@.7....e.............4z.....q 1..........

Anyways, it should be srs and not argh talking there. Maybe this is the reason why the later http.Post(pool, "application/json", relay : // ) fails with “IP address not matching external address”

I tried to trick it by changing transport.Dial in main.go to transport.DialTLS ( forgive me my noobish golang, I’m new to it ).

--- a/cmd/strelaysrv/main.go
+++ b/cmd/strelaysrv/main.go
@@ -133,7 +133,7 @@ func main() {
                laddr.Port = 0
                transport, ok := http.DefaultTransport.(*http.Transport)
                if ok {
-                       transport.Dial = (&net.Dialer{
+                       transport.DialTLS = (&net.Dialer{
                                Timeout:   30 * time.Second,
                                LocalAddr: laddr,

Yeah! Now the first packet uses srs as source:

13:57:52.092738 IP srs.molgen.mpg.de.51250 > web.syncthing.net.https : Flags [S], seq 1348153206, win 29200, options [mss 1460,sackOK,TS val 1098373744 ecr 0,nop,wscale 9], length 0

But now http.Post from pool.go does the following:

13:57:52.108068 IP srs.molgen.mpg.de.51250 > web.syncthing.net.https: Flags [P.], seq 1:408, ack 1, win 58, options [nop,nop,TS val 1098373760 ecr 329479815], length 407
Aw....v.POST /endpoint HTTP/1.1
Host: relays.syncthing.net
User-Agent: Go-http-client/1.1
Content-Length: 244
Content-Type: application/json
Accept-Encoding: gzip


and relays.syncthing.net happily answers:

13:57:52.124061 IP web.syncthing.net.https > srs.molgen.mpg.de.51250: Flags [P.], seq 1:442, ack 408, win 470, options [nop,nop,TS val 329479819 ecr 1098373760], length 441
E.....@.7.      ..e.....d...2....P[1............
..v.Aw..HTTP/1.1 400 Bad Request
Server: nginx/1.10.3 (Ubuntu)
Date: Thu, 08 Feb 2018 12:57:52 GMT
Content-Type: text/html
Content-Length: 280
Connection: close

<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
<hr><center>nginx/1.10.3 (Ubuntu)</center>

Since I don’t have a clue about golang maybe someone could have a look at this ? I found a couple of ‘slighlty’ related posts, maybe their issues will be fixed also ?

Or do I get something completely wrong ? ( that would be normal :sunglasses: )

Not sure why it would help, as if DialTLS is nil, it should use Dial.

yes, that’s what I also found out, but as proofed, the behavior is different.

Well the dial function you have attached returns a tcp connection not tls, so you probably need to wrap that, yet I’d go digging to understand why Dial is not used correctly. Perhaps we need to set DialContext rather than Dial from the dialer.

I think the problem is that we’re doing something unsupported. We’re essentially monkeypatching the default HTTP transport, which we should not. It probably worked at some point, but since then the DialTLS hook has been added, and I think if that’s set the ordinary Dial isn’t called. Probably the default transport has DialTLS set.

The correct solution is to create a local http.Client with a transport, in the relay server, and use that.

I’d file this as a github issue, but I fear I wouldn’t be able to be clear about it. Or should I just copy my post there ?

A pull request fixing this is always better than an issue.

Nonetheless, an issue is fine to begin with. Following up with a PR that resolves the issue is :heart:.

I actually prefer that - a pull request that doesn’t resolve an existing issue is just sort of random code and won’t show up in the release notes, etc.

An issue doesn’t have to fully specify the technical issue and solution. Just noting that the relay server doesn’t make outgoing HTTPS requests from it’s bind address, like it’s supposed to, is fine.

ok, I ‘issued’.

1 Like

Solved with https://github.com/syncthing/syncthing/pull/4769 applied to v0.14.45-rc.3

thanks again!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.