ccding / go-stun

A go implementation of the STUN client (RFC 3489 and RFC 5389)
Apache License 2.0
663 stars 120 forks source link

Am I insane? #12

Closed AudriusButkevicius closed 8 years ago

AudriusButkevicius commented 8 years ago

Hi,

I am testing this again, and I am hitting a strange issue, where my NAT is reported correctly as a full cone nat, but I believe it hasn't done proper testing.

I've made a small diff just for debugging:

@@ -125,6 +126,7 @@ func (v *packet) xorMappedAddr() *Host {
 // Retransmissions continue with intervals of 1.6s until a response is
 // received, or a total of 9 requests have been sent.
 func (v *packet) send(conn net.PacketConn, addr net.Addr) (*packet, error) {
+       fmt.Println("send to", addr)
        timeout := 100
        for i := 0; i < 9; i++ {
                length, err := conn.WriteTo(v.bytes(), addr)
@@ -142,8 +144,9 @@ func (v *packet) send(conn net.PacketConn, addr net.Addr) (*packet, error) {
                        timeout *= 2
                }
                packetBytes := make([]byte, 1024)
-               length, _, err = conn.ReadFrom(packetBytes)
+               length, raddr, err := conn.ReadFrom(packetBytes)
                if err == nil {
+                       fmt.Println("recv", raddr)
                        return newPacketFromBytes(packetBytes[0:length])
                }
                if !err.(net.Error).Timeout() {

And the verbose output is as follows:

2016/08/05 22:46:58 Do Test1
2016/08/05 22:46:58 Send To: 64.233.165.127:19302
send to 64.233.165.127:19302
recv 64.233.165.127:19302
2016/08/05 22:46:58 Received: {isNil:false}
2016/08/05 22:46:58 Received: {changedAddr:'<nil>', identical:'false', host:'111.189.74.19:55777'}
2016/08/05 22:46:58 Do Test2
2016/08/05 22:46:58 Send To: 64.233.165.127:19302
send to 64.233.165.127:19302
recv 64.233.165.127:19302
2016/08/05 22:46:58 Received: {isNil:false}
Full cone NAT &{1 111.189.74.19 55777} <nil>

Now correct me if I am wrong, but the response in Test2 came from the same address as Test1, hence there is no evidence that it is actually a full cone nat?

I feel that it's the stun server misbehaving, yet perhaps sanity checks should be performed client side too?

Also, I changed my router since I ran the last tests when it actually worked, so perhaps it's my router re-writing the addresses and causing this impression?

As I seem to get the same result with multiple stun servers...

ccding commented 8 years ago

See the figure in discover.go (or in RFC). Test1 received response, and identical==false. Then Test2 responsed. This goes to the Full Cone branch. Response in Test2 always comes from the same address as Test1. ChangedAddr will be used for the second time Test1.

It is a little bit tricky in my code. Since Test2 has to be done no matter IP same (identical==true) or not, I perform Test2 first then check identical etc.

AudriusButkevicius commented 8 years ago

As far as I understood from the diagram ChangeAddr only applies when you want to verify if the same local listening port, when sending to a different address, causes you to get a different external port.

This is different than some random IP on the internet being able to send you a packet over a connection which it never received a packet from you.

How else are you verifying if your connection is Full Cone, if you only ever receive packets from the same ip, port pair?

ccding commented 8 years ago

I see. It is a bug in the server side, and also in my side. I am debugging it with another STUN server.

ccding commented 8 years ago

Fixed a bug in xorMappedAddr

Still cannot figure out if the behavior is correct. It looks the packet sent is correct, but it's wired the server doesn't change ip or port.

And there is a similar problem in test3: change port is set while change ip is not set, but the recv addr shows both are changed.

I tried servers stun.ekiga.net:3478 and stun1.l.google.com:19302

AudriusButkevicius commented 8 years ago

So I think the server is not behaving correctly, I think I tired a different server and it worked correctly. Yet I don't know how the client ia supposed to behave.

ccding commented 8 years ago

Can I know which server works correctly? I may use it to test

AudriusButkevicius commented 8 years ago

stun.ekiga.net:3478

with pystun I get:

root@audrius:~# pystun -i 178.62.69.157
Send stun.ekiga.net:3478
Received ('217.10.68.152', 3478)
Send stun.ekiga.net:3478
Received ('217.116.122.138', 3479)
NAT Type: Open Internet

yet it doesn't work at home, but as I said, it's a new router, so I am not yet sure where the problem is.

ccding commented 8 years ago

It seems that in test2 the server still sends packet back without changing IP and port. The data the client sends to the server looks correct.

AudriusButkevicius commented 8 years ago

So I think it's the servers fault, but I feel that the library should detect this and potentially return an error.

ccding commented 8 years ago

In some case, it is not server's fault. I fixed this bug in #15