Hi @ylempereur, thank you for the quick response
. To give some context on my issue:
My scenario I am trying to do a socket communication between 2 nodes which are behind a NAT. So as I mentioned before my nodes are able to see and ping each other, but not able to do socket communication. Based on your explanation I understood that pings and all go through relay (I have 3 bootstrap nodes hosted on AWS, and one bootstrap node on ngrok), but the data flows through a direct connection. I tried to establish a direct connection using “ipfs swarm connect” command and it displays “connected”. But even after this it is not able to communicate. So then I tried to use the example mentioned in kubo/docs/experimental-features.md at master · ipfs/kubo · GitHub, which shows how to connect 2 netcat server to netcat client, in a similar manner as my socket program(to eliminate any socket programming related errors from my side). I guess holepunching has failed for me as they are not able to communicate. Are there any config errors in my setup?
Config of nodes behind NAT:
{
"API": {
"HTTPHeaders": {}
},
"Addresses": {
"API": "/ip4/127.0.0.1/tcp/5001",
"Announce": [],
"AppendAnnounce": [],
"Gateway": "/ip4/127.0.0.1/tcp/8080",
"NoAnnounce": [],
"Swarm": [
"/ip4/0.0.0.0/tcp/4001",
"/ip6/::/tcp/4001",
"/ip4/0.0.0.0/udp/4001/quic-v1",
"/ip4/0.0.0.0/udp/4001/quic-v1/webtransport",
"/ip6/::/udp/4001/quic-v1",
"/ip6/::/udp/4001/quic-v1/webtransport"
]
},
"AutoNAT": {},
"Bootstrap": [
"/ip4/<bootstrap_ip1>/tcp/4001/p2p/12D3KooWJeCNUxFXmD8pqf27HC9h9rbRxcHfAqc61GCUuTvCiUPE",
"/ip4/<bootstrap_ip2>/tcp/4001/p2p/12D3KooWR8FQ3pAtnXwJgKKJ2tkwrYbgpzZZUpo7aQcLyVPSqoxL",
"/ip4/<bootstrap_ip3>/tcp/4001/p2p/12D3KooWCc2QDzx75SGCTuuYnWYFunQTBS8Cd3JTHRvsTWJKK74R",
"/dns/<bootstrap_ip4>/tcp/19295/p2p/12D3KooWQUJu9N1G7vqbDkzPuKEgjo8NNWkPAoTr4hd2sLVyqMfQ"
],
"DNS": {
"Resolvers": {}
},
"Datastore": {
"BloomFilterSize": 0,
"GCPeriod": "1h",
"HashOnRead": false,
"Spec": {
"mounts": [
{
"child": {
"path": "blocks",
"shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
"sync": true,
"type": "flatfs"
},
"mountpoint": "/blocks",
"prefix": "flatfs.datastore",
"type": "measure"
},
{
"child": {
"compression": "none",
"path": "datastore",
"type": "levelds"
},
"mountpoint": "/",
"prefix": "leveldb.datastore",
"type": "measure"
}
],
"type": "mount"
},
"StorageGCWatermark": 90,
"StorageMax": "10GB"
},
"Discovery": {
"MDNS": {
"Enabled": true
}
},
"Experimental": {
"FilestoreEnabled": false,
"Libp2pStreamMounting": true,
"OptimisticProvide": false,
"OptimisticProvideJobsPoolSize": 0,
"P2pHttpProxy": false,
"StrategicProviding": false,
"UrlstoreEnabled": false
},
"Gateway": {
"APICommands": [],
"DeserializedResponses": null,
"DisableHTMLErrors": null,
"ExposeRoutingAPI": null,
"HTTPHeaders": {},
"NoDNSLink": false,
"NoFetch": false,
"PathPrefixes": [],
"PublicGateways": null,
"RootRedirect": ""
},
"Identity": {
"PeerID": "12D3KooWFXoGG4a3hcXXaeDc3Qwsg1rbAZoSXjGCkhHaMHE49kht"
},
"Internal": {},
"Ipns": {
"RecordLifetime": "",
"RepublishPeriod": "",
"ResolveCacheSize": 128
},
"Migration": {
"DownloadSources": [],
"Keep": ""
},
"Mounts": {
"FuseAllowOther": false,
"IPFS": "/ipfs",
"IPNS": "/ipns"
},
"Peering": {
"Peers": null
},
"Pinning": {
"RemoteServices": {}
},
"Plugins": {
"Plugins": null
},
"Provider": {
"Strategy": ""
},
"Pubsub": {
"DisableSigning": false,
"Router": ""
},
"Reprovider": {},
"Routing": {
"AcceleratedDHTClient": false,
"Methods": null,
"Routers": null,
"Type": "dht"
},
"Swarm": {
"AddrFilters": null,
"ConnMgr": {},
"DisableBandwidthMetrics": false,
"DisableNatPortMap": false,
"EnableHolePunching": true,
"RelayClient": {
"Enable": true
},
"RelayService": {},
"ResourceMgr": {},
"Transports": {
"Multiplexers": {},
"Network": {},
"Security": {}
}
}
}
Config of bootstrap:
{
"API": {
"HTTPHeaders": {}
},
"Addresses": {
"API": "/ip4/127.0.0.1/tcp/5001",
"Announce": [],
"AppendAnnounce": [
"/ip4/<bootstrap_ip2>/tcp/4001"
],
"Gateway": "/ip4/127.0.0.1/tcp/8080",
"NoAnnounce": [],
"Swarm": [
"/ip4/0.0.0.0/tcp/4001",
"/ip6/::/tcp/4001",
"/ip4/0.0.0.0/udp/4001/quic-v1",
"/ip4/0.0.0.0/udp/4001/quic-v1/webtransport",
"/ip6/::/udp/4001/quic-v1",
"/ip6/::/udp/4001/quic-v1/webtransport"
]
},
"AutoNAT": {},
"Bootstrap": [
"/ip4/<bootstrap_ip1>/tcp/4001/p2p/12D3KooWJeCNUxFXmD8pqf27HC9h9rbRxcHfAqc61GCUuTvCiUPE",
"/ip4/<bootstrap_ip2>/tcp/4001/p2p/12D3KooWR8FQ3pAtnXwJgKKJ2tkwrYbgpzZZUpo7aQcLyVPSqoxL",
"/ip4/<bootstrap_ip3>/tcp/4001/p2p/12D3KooWCc2QDzx75SGCTuuYnWYFunQTBS8Cd3JTHRvsTWJKK74R",
"/dns/<bootstrap_ip4>/tcp/19295/p2p/12D3KooWQUJu9N1G7vqbDkzPuKEgjo8NNWkPAoTr4hd2sLVyqMfQ"
],
"DNS": {
"Resolvers": {}
},
"Datastore": {
"BloomFilterSize": 0,
"GCPeriod": "1h",
"HashOnRead": false,
"Spec": {
"mounts": [
{
"child": {
"path": "blocks",
"shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
"sync": true,
"type": "flatfs"
},
"mountpoint": "/blocks",
"prefix": "flatfs.datastore",
"type": "measure"
},
{
"child": {
"compression": "none",
"path": "datastore",
"type": "levelds"
},
"mountpoint": "/",
"prefix": "leveldb.datastore",
"type": "measure"
}
],
"type": "mount"
},
"StorageGCWatermark": 90,
"StorageMax": "10GB"
},
"Discovery": {
"MDNS": {
"Enabled": true
}
},
"Experimental": {
"FilestoreEnabled": false,
"Libp2pStreamMounting": true,
"OptimisticProvide": false,
"OptimisticProvideJobsPoolSize": 0,
"P2pHttpProxy": false,
"StrategicProviding": false,
"UrlstoreEnabled": false
},
"Gateway": {
"APICommands": [],
"DeserializedResponses": null,
"DisableHTMLErrors": null,
"ExposeRoutingAPI": null,
"HTTPHeaders": {},
"NoDNSLink": false,
"NoFetch": false,
"PathPrefixes": [],
"PublicGateways": null,
"RootRedirect": ""
},
"Identity": {
"PeerID": "12D3KooWR8FQ3pAtnXwJgKKJ2tkwrYbgpzZZUpo7aQcLyVPSqoxL"
},
"Internal": {},
"Ipns": {
"RecordLifetime": "",
"RepublishPeriod": "",
"ResolveCacheSize": 128
},
"Migration": {
"DownloadSources": [],
"Keep": ""
},
"Mounts": {
"FuseAllowOther": false,
"IPFS": "/ipfs",
"IPNS": "/ipns"
},
"Peering": {
"Peers": null
},
"Pinning": {
"RemoteServices": {}
},
"Plugins": {
"Plugins": null
},
"Provider": {
"Strategy": ""
},
"Pubsub": {
"DisableSigning": false,
"Router": ""
},
"Reprovider": {},
"Routing": {
"AcceleratedDHTClient": false,
"Methods": null,
"Routers": null,
"Type": "dhtserver"
},
"Swarm": {
"AddrFilters": null,
"ConnMgr": {},
"DisableBandwidthMetrics": false,
"DisableNatPortMap": false,
"EnableHolePunching": true,
"RelayClient": {},
"RelayService": {
"Enable": true
},
"ResourceMgr": {},
"Transports": {
"Multiplexers": {},
"Network": {},
"Security": {}
}
Right now I understand all data flows through port 4001 on every node (even if netcat/any services use different ports, the custom protocol name given in the example highlihited on the link I shared above forwards this to the appropriate port using ipfs p2p forward/ipfs p2p listen commands).
Can you please explain how port mapping solves the holepunching issue? Also can you please let me know how the port mappings are done or do you have a document for how to get it done?