Topology updates with relay node behind NAT or Load Balancer


Since P2P is still not operational, it makes running nodes behind NATs or using Kubernetes load balancers impossible.
Although your pool may run smoothly, you will not be able to use the topology updater due to the fact that the service cannot see your public IP address, hence you will not be added to the topology and won’t be used as incoming peer by other pool operators.

There have been several ideas, detailed in this topic , but I don’t think any of these were implemented.

So, I have two questions:

  1. Does anybody have a workaround around it?
  2. If I implement something that continuously (say, twice a day) queries the blockchain for registered public IPs (based on pools metadata), and allow anyone to retrieve that list using a simple API call, would you use such a service to update your topology?


I’m not an SPO, just curious: Using the data in the pool registrations sounds totally sound and such a service (perhaps cleaned by unreachable) to me would totally make sense, but it does not really help the “behind NAT” topic, does it? If I don’t have a public IP, I cannot register a public IP on the blockchain.

you are right that one must have a public IP in order for others to be able to reach it.
when running behind a NAT your machine can be reachable if your router has a public IP, and you enable port-forwarding to your machine.
The problem is in the second direction: when you are sending someone an outgoing message from your local machine, there is no way for him to know what is your router’s public IP, hence he cannot “get back” to you.
The current topology server is receiving messages from your node, and register the origin IP in the topology. This origin IP is not the public IP of your router.
So we should either change the current service behavior, so one can explicitly specify which public IP should be registered in the topology (rather than just relying on the message origin, which in some cases is incorrect),
or have a completely different service, like the one I proposed.

I don’t really get what problem you are trying to fix, but relays behind nat do work with topology updater at least for me. I just use DNS name in topologyupdater and I have no issue at all with it.

In what setup is the originating IP not the same as the router’s public IP?

There might be mid-sized to large corporate networks that have several static IPs or one static and some dynamic, but if you deal with such a setup, you should also be able to configure outgoing traffic of the Cardano node through the same IP than incoming.

For home setups, if your router has a static IP, it will also be the one of outgoing traffic in 95% of the cases.

Also, what @os11k said: You can use (Dyn)DNS name.

Seems what @eladws meant asymmetric NAT(not just NAT what can have different types) and I think in current times this is not something very often you can see. I know one pool operator who has some relays with this problem and he just doesn’t run topology updater there, works fine for him.

1 Like

I am not certain I understand OP’s problem fully. But hopefully this explanation will help: provides a service that helps collate and distribute cardano relay information.

There are 2 parts to service:

  1. Your node can send information about itself to register by pinging every hour
  2. Your node can download a topology.json file with a list of appropriate relays from

If you do the first action, then you can also do the second action but you don’t have to. You can create your own topology.json file however you want.

If you don’t do the first action then other nodes that use the service will not know about your relay and thus will not get its details included in their topology.json files they get issued.

You can do the first action with whatever script you like. You just need to provide certain details.

Here is an example bash script:

set -o nounset
set -o errexit
set -o pipefail

CNODE_HOME='/opt/cardano' #FIXME
export CARDANO_NODE_SOCKET_PATH='/run/cardano/mainnet-node.socket' #FIXME
shelley_genesis="${CNODE_HOME}/etc/mainnet-shelley-genesis.json" #FIXME
nwmagic="$(jq -r '.networkMagic' "$shelley_genesis")"
hostname="$(hostname -f)"
port=3000 #FIXME

function send_topology() {
  # Sometimes cardano socket recreated causing broken pipe so try 5 times
  local count=0
    if (( ++count > 5 )); then
      echo 'Error: send_topology(): cardano-cli failed' >&2
      return 1
    local blockNo="$(cardano-cli query tip --mainnet 2>/dev/null | jq -r '.block')"
    [[ -z "${blockNo:-}" ]]
  do sleep 1; done
  local response="$(curl -sf -4 "${service_url}?port=${port}&blockNo=${blockNo}&valency=1&magic=${nwmagic}&hostname=${hostname}")"
  echo "$response"

send_topology || exit 1
exit 0

Configure variables listed before the function to your values and run this every hour. Eg. With a cron job.

When you “ping” this information to the service, will register the IP address it sees as the IP address for your relay. In other words, this will be the IP address your internal machine masquerades as, to the rest of the internet. If your router only has one fixed IP address then it will be that IP address since your router will be doing SNAT (source network address translation).

Then you need to ensure you have configured DNAT (destination network address translation) properly on your router so that incoming connections to your fixed public IP on port (eg. 3000) will be connected into the correct port on your internal relay.

1 Like

By the way if anybody relays are behind asymmetric nat you can contact @werkof and he will provide access key and in this case topology-updater will work.

TU is designed to work permission-less. But this comes only with the obligation to subscribe your relays public reachable IP from exact this public IP. This results in the here previously described issues for certain network setups (load Balancers, NAT, …)

There is a manual workaround solution.

  1. You need to DM me the public reachable IP your relay will be listed in TopologyUpdater
  2. I’ll provide you an unique access key
  3. you use this access key together to extend the original subscribe request URL (in script) It will be accepted despite not comming from this public IP
1 Like

I’m new to the forum, and I’m not sure how to DM on here.

I’m using an AWS load balancer, with EKS and am having this problem. AWS does not have a way to do this using their standard services, as far as i can tell. The load balancer acts as a proxy. You can’t route outgoing traffic through it. I’d have to set up a NAT instance but that is a single point of failure.

We’re currently on testnet but am wanting to get everything set so we’ll be ready for mainnet.


I had a similar problem when setting up a TOR bridge on a raspberry pi. In order to overcome this I used a virtual AWS hosted router. I setup a wireguard connection between the PI and the virtual router, and made the wireguard interface the default gateway ( on the PI - this way the public IP address is the virtual routers IP address. When traffic comes into the virtual router on a certain port ( TOR port (or relay traffic port 6000?)) you DST-NAT that traffic to the PI’s Wireguard IP address.

You could probably use a vanilla ubuntu VM on a cloud provider and manage it with IP tables. But IP tables are less user friendly.

Thanks, I’ll check that out for mainnet. I switched hostname back to CHANGE ME and it seems (on testnet at least) to just warn about the inability to connect back on the client ip address and it gave me a list of peers anyway.