Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.

Cost more than two minutes to find NAT gateway in some Network structure #21

Closed
alx696 opened this issue Nov 12, 2019 · 6 comments
Closed
Labels
kind/bug A bug in existing code (including security flaws)

Comments

@alx696
Copy link

alx696 commented Nov 12, 2019

I tested go-libp2p-nat and go-nat at the company and at home.

Company:

Network structure: PC > switch > router

No firewall.

go-libp2p-nat.DiscoverNAT(ctx) and go-nat.DiscoverGateway() cost more than 2 minutes.

go-nat.DiscoverNATs(ctx) cost about 2 seconds.

Home:

Network structure: PC(DMZ) > router

No firewall.

go-libp2p-nat.DiscoverNAT(ctx) and go-nat.DiscoverGateway() cost about 5 seconds.

go-nat.DiscoverNATs(ctx) cost less than 1 seconds.

Code: https://github.com/alx696/libp2p/blob/master/go-nat-example/main.go

@Stebalien Stebalien added the kind/bug A bug in existing code (including security flaws) label Nov 12, 2019
@Stebalien
Copy link
Member

When you say go-nat.DiscoverNATs takes "2 seconds", are you waiting to read the entire channel? That function should return immediately.

Beyond that, this could be a DNS issue. DiscoverGateway calls GetDeviceAddress which may need to do a DNS lookup (which may time out?).

Unfortunately, this issue is likely very specific to your network. We'll need more timing information to figure out where the problem lies.

@alx696
Copy link
Author

alx696 commented Nov 12, 2019

@Stebalien I do not doing anything else. Just get NAT and print external IP address.

Code:

...
			natChan := gonat.DiscoverNATs(ctx)
			select {
			case natGateway := <-natChan:
				natExternalAddress, e := natGateway.GetExternalAddress()
				if e != nil {
					log.Fatalln(e)
				}
				log.Println("NAT网关公网IP:", natExternalAddress.String())

				mappedExternalPort, e := natGateway.AddPortMapping("udp", port, "P2P测试", time.Minute)
				if e != nil {
					log.Fatalln(e)
				}
				log.Println("NAT映射端口:", port, mappedExternalPort)

				_ = natGateway.DeletePortMapping("udp", port)
			}
...

Console:

2019/11/12 13:40:59 NAT示例
2019/11/12 13:40:59 使用go-nat
2019/11/12 13:41:01 NAT网关公网IP: x.x.x.x
2019/11/12 13:41:01 NAT映射端口: 60000 22378

DNS is the same: 8.8.8.8. The company's network structure should be the simplest one.

What information do you need to collect? I am happy to help you debug.

build code as nat application, runing at home:
d@debian:~$ ./nat --type=libp2p
2019/11/12 14:00:44 NAT示例
2019/11/12 14:00:44 使用go-libp2p-nat
2019/11/12 14:00:49 已有NAT映射: []
2019/11/12 14:00:49 NAT公网地址: 59.172.149.246:11266
d@debian:~$ ./nat --type=gateway
2019/11/12 14:01:07 NAT示例
2019/11/12 14:01:07 使用go-nat
2019/11/12 14:01:12 NAT网关公网IP: 59.172.149.246
2019/11/12 14:01:12 NAT映射端口: 60000 19941
d@debian:~$ ./nat --type=
2019/11/12 14:01:19 NAT示例
2019/11/12 14:01:19 使用go-nat
2019/11/12 14:01:19 NAT网关公网IP: 59.172.149.246
2019/11/12 14:01:19 NAT映射端口: 60000 52292

@Stebalien
Copy link
Member

Looking at your code, you're only waiting for it to discovery the first gateway. go-libp2p-nat.DiscoverNAT checks all possible protocols and then tries to pick the best gateway.

  • What happens when you read the channel returned by go-nat.DiscoverNATs until it closes?
  • How long does calling GetDeviceAddress on each returned "NAT" instance take?

@alx696
Copy link
Author

alx696 commented Nov 22, 2019

Looking at your code, you're only waiting for it to discovery the first gateway. go-libp2p-nat.DiscoverNAT checks all possible protocols and then tries to pick the best gateway.

  • What happens when you read the channel returned by go-nat.DiscoverNATs until it closes?
  • How long does calling GetDeviceAddress on each returned "NAT" instance take?
  1. Nothing happened.
  2. Cost same time as GetExternalAddress(), Looking for a gateway take long time.

When I tested go-nat.DiscoverNATs(ctx) on a cloud server, chan pass <nil> if no NAT found. Why not close chan? Or add a notice to doc. go-libp2p-nat.DiscoverNAT(ctx) works fine, return error: no NAT found.

Supplemental NAT type information:

  1. Company: UPNP (IG1-IP1)
  2. Home: NAT-PMP

@Stebalien
Copy link
Member

Could you try libp2p/go-nat#13? It looks like we weren't properly obeying timeouts.

Nothing happened.

Ah, sorry. I should have asked: how long does it take to read all the NATs off the channel until the channel closes?

Cost same time as GetExternalAddress(), Looking for a gateway take long time.

So less than 2 seconds? I asked because this function does three things:

  1. Asks the OS for a list of "routes". This should take no time.
  2. Calls DiscverNATs and waits for it to finish finding NATs.
  3. Calls GetDeviceAddress on each discovered NAT.

I'm trying to figure out what's taking so long.

When I tested go-nat.DiscoverNATs(ctx) on a cloud server, chan pass if no NAT found. Why not close chan?

We do. Closed channels return nil. Specifically:

result := <-closedChan // result == nil
result, ok := <-closedChan // result == nil, ok == false

@marten-seemann
Copy link
Contributor

Haven't heard back in 2.5 years. Closing this issue.

@marten-seemann marten-seemann closed this as not planned Won't fix, can't repro, duplicate, stale May 25, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
kind/bug A bug in existing code (including security flaws)
Projects
None yet
Development

No branches or pull requests

3 participants