I have a network with multiple gateways and one is set as the default gateway on a server. I want a single specific command to use a separate gateway for all its traffic. How would I achieve that?
Unfortunately using a destination IP route is not possible since I do not know the IPs that the command will contact beforehand.
What I really want to do is send all traffic through my default gateway and use a separate one for a script that uploads some stuff to Amazon S3. I achived it by getting Amazon's IPs from https://ip-ranges.amazonaws.com/ip-ranges.json and periodically updating the route table with the gateway I want for them but that feels hacky as hell.
I realise that there's no way to route traffic by domain name so could I do it some other way? Maybe with iptables or something similar?
Here's the script I whipped up for reference:
#!/usr/bin/env bash
set -eo pipefail
IFS=$'\n\t'
amazon_gateway='XXX.XXX.XXX.XXX'
amazon_ips_url='https://ip-ranges.amazonaws.com/ip-ranges.json'
route="$(which route)"
curl="$(which curl)"
jq="$(which jq)"
awk="$(which awk)"
netstat="$(which netstat)"
# taken from https://forums.gentoo.org/viewtopic-t-888736-start-0.html
mask2cdr ()
{
# Assumes there's no "255." after a non-255 byte in the mask
set -- 0^^^128^192^224^240^248^252^254^ ${#1} ${1##*255.}
set -- $(( ($2 - ${#3})*2 )) ${1%%${3%%.*}*}
echo $(( $1 + (${#2}/4) ))
}
# get amazon ips
amazon_ips=$("${curl}" "${amazon_ips_url}" | "${jq}" -r '.prefixes | map(select(.service == "AMAZON"))[].ip_prefix')
# get networks routed to requested gateway
routed_networks=$("${netstat}" -nr | "${awk}" '{ if ($2 == "'"${amazon_gateway}"'") print $1"/"$3 }')
# convert masks to cdrs
routed_networks=$(for network in ${routed_networks}; do echo "${network%\/*}/$(mask2cdr ${network#*\/})"; done)
# remove routes for all these networks
for network in ${routed_networks}; do "${route}" del -net "${network}" gw "${amazon_gateway}"; done
# add a route for each amazon ip
for amazon_ip in ${amazon_ips}; do "${route}" add -net "${amazon_ip}" gw "${amazon_gateway}"; done