Question

Floating iP gateway as default router and source address for outbound connections

Community!

I am curious if it is possible to setup anchor ip gateway as default router so all outbound traffic from droplet shows to external services as coming from floating ip.

This will greatly simplify my external system firewall setup since floating ip never changes; I can allow all connections from floating ip.

I tried adding the anchor ip gateway as the defaultrouter in /etc/rc.conf and reboot but this did not work. (curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/gateway)

I am using freebsd, but welcome any linux recommendations as well. There may be multiple ways to achieve this (e.g. routes, routed, iptables), but what is the CLEANEST approach, and is this even possible on Digital Ocean?

Subscribe
Share

@animaexos After struggling with this, I achieved it using iptables.

Run this command from your server to retrieve anchor IP address

$ curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address

Then run this command to redirect all outgoing traffic to your floating ip.

$ iptables -t nat -A POSTROUTING -p tcp  -o eth0 -j SNAT --to-source ANCHOR_IP

To build on what @marcoscvp90 said, in PF the same rule would be:

nat pass on $NIC to any { port $PORT|$PORTRANGE } -> $ANCHOR_IP

port is optional if you want to nat all traffic through the floating ip.

Hello,

How would the rule in iptables be for me to work with ping packages?

I tried with iptables -t nat -A POSTROUTING -p icmp -o eth0 -j SNAT --to-source <ANCHORIP> but it does not work. The shared IP continues to appear and not the floating.

Thanks.

good question - I’m also curious about whether this is possible for a HA setup I have in mind …

(I have already been told that floating IP’s can’t have PTR records or forward SMTP traffic so I’m a bit concerned whether they are ‘fit for purpose’ …)


Submit an answer
You can type!ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

We used the command provided above to set the default From IP address on outbound connections to the floating IP address:

iptables -t nat -A POSTROUTING -p tcp  -o eth0 -j SNAT --to-source <ANCHORIP>

where <ANCHOR_IP> should be replaced by your actual anchor IP address. The anchor IP address can be obtained with the following command (which hangs if you have already executed the command above!)

/usr/bin/curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address

However, we then ran into the Digital Ocean block on SMTP connections originating from a floating IP address. This wasted days of our time! We eventually solved this by adding an extra rule to the POSTROUTING table as follows:

iptables -t nat -A POSTROUTING -p tcp --dport 587 -o eth0 -j SNAT --to-source <FIXEDIP>

where <FIXEDIP> is the fixed IP address of your droplet (as appears in your droplet list in the Digital Ocean web management interface). This iptables command says to make SMTP a special case and to use the droplet’s fixed IP address as a From address for outbound SMTP connections.

You have to issue the commands in the correct order so that the special case SMTP rule ends up BEFORE the catchall rule in the resulting POSTROUTING rule chain. So do them in this order:

iptables -t nat -A POSTROUTING -p tcp --dport 587 -o eth0 -j SNAT --to-source <FIXEDIP>
iptables -t nat -A POSTROUTING -p tcp  -o eth0 -j SNAT --to-source <ANCHORIP>

If you are engineering a general solution, put in a rule for each port that is commonly used for SMTP:

# Assumes the POSTROUTING chain is empty at this point.
iptables -t nat -A POSTROUTING -p tcp --dport 25 -o eth0 -j SNAT --to-source <FIXEDIP>
iptables -t nat -A POSTROUTING -p tcp --dport 465 -o eth0 -j SNAT --to-source <FIXEDIP>
iptables -t nat -A POSTROUTING -p tcp --dport 587 -o eth0 -j SNAT --to-source <FIXEDIP>
iptables -t nat -A POSTROUTING -p tcp --dport 2525 -o eth0 -j SNAT --to-source <FIXEDIP>
iptables -t nat -A POSTROUTING -p tcp --dport 2526 -o eth0 -j SNAT --to-source <FIXEDIP>
iptables -t nat -A POSTROUTING -p tcp  -o eth0 -j SNAT --to-source <ANCHORIP>

If all goes well, you will end up with a POSTROUTING chain that looks like this:

[root@www1 ~]# iptables -t nat --list
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
SNAT       tcp  --  anywhere             anywhere             multiport dports smtp,urd,submission,ms-v-worlds,ema-sent-lm /* 455 Use fixed IP for SMTP outbound */ to:<FIXEDIP>
SNAT       tcp  --  anywhere             anywhere             /* 456 Use floating IP for outbound */ to:<ANCHORIP>
[root@www1 ~]# 

Reminder: You can delete the first entry in a chain like this:

iptables -t nat -D POSTROUTING 1

Reminder: If you want your new iptables to survive a reboot, save it using a command something like this:

/sbin/service iptables save

If you are coding all this in Puppet, the following might be helpful:

firewall { '455 Use fixed IP for SMTP outbound':
    table    => 'nat',                  # -t nat
    chain    => 'POSTROUTING',          # -A POSTROUTING
    proto    => 'tcp',                  # -p tcp
    dport    => [25,465,587,2525,2526], # --dport 587 (etc)
    outiface => 'eth0',                 # -o eth0
    jump     => 'SNAT',                 # -j SNAT
    tosource => $fixed_ip_address,      # --to-source $fixed_ip_address
    
    # It seems like a good idea to ensure that the rule to allow established
    # connections to continue unharmed is implemented before we monkey around
    # with anything else. Perhaps this 'require' isn't needed, but I've
    # included it to be on the safe side.
    #
    require  => Firewall['002 accept related established rules'],
}


firewall { '456 Use floating IP for outbound':
    table    => 'nat',                # -t nat
    chain    => 'POSTROUTING',        # -A POSTROUTING
    proto    => 'tcp',                # -p tcp
    outiface => 'eth0',               # -o eth0
    jump     => 'SNAT',               # -j SNAT
    tosource => $anchor_ip_address,   # --to-source $anchor_ip_address
    
    # It is essential that the firewall rule to allow all established
    # connections to continue unharmed is implemented before the floating
    # IP address is made the default for all outbound traffic because if
    # you don't do this, it seems that existing connections suddenly
    # switch to the floating IP address mid-session! Apart from anything else,
    # this causes all SSH sessions to the node to fail, which causes
    # any manual Puppet SSH session to be terminated!
    #
    require  => Firewall['002 accept related established rules'],
}

I hope this saves someone some time!

Ross Williams

I’ve configured this for UDP, and it seems to work at the DO side after his command

iptables -t nat -A POSTROUTING -p udp -o eth0 -j SNAT --to-source 10.18.0.5

and when doing a capture it shows

1	0.000000	82.197.198.218	10.18.0.7	CLASSIC-STUN	70	Message: Binding Request
2	0.000334	10.18.0.7	82.197.198.218	CLASSIC-STUN	98	Message: Binding Response

BUT the packets are never received at the client side. Is there something I’m missing?

Thanks, Martijn

Thanks, this was pretty impressive if you face any problem regarding then head over to 192.168.0.1

To not blocking Digital Ocean’s monitoring agent (do-agent ), exclude the metadata API from the redirect rules:

# iptables -t nat -A POSTROUTING -p tcp  -o eth0 ! -d 169.254.169.254 -j SNAT --to-source $ANCHOR_IP

You can also get IP address using this ip addr show eth0 | awk '/inet .*\/16/ {print $2}' | cut -d/ -f 1 without querying API.

This comment has been deleted

This comment has been deleted

This comment has been deleted

@Brants the ping packets are not being SNATed because you are using -p tcp and they are icmp. If you replace that parameter with -p all, it will work for any protocol coming out of eth0.

@robertomatute I believe that DigitalOcean is blocking all outbound TCP on port 25 from the floating IPs. This is annoying, since I also wanted to use the floating IP feature to support outbound SMTP.

@marcoscvp90 Thanks for this info.

I am trying to use in a postfix config; I want to use the floating ip as the receiving address of my server. In the email world is very important the ip reputation. I want to use floating ip to keep all the reputation.

Using your iptables recomendation, when postfix try to connect to the internet it gets “Network not reachable”.

Its necessary to add a new ip route?

thanks,

Roberto