Skip to content

Instantly share code, notes, and snippets.

@andrewhowdencom
Created June 17, 2018 11:10
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save andrewhowdencom/ead12c677cb7873bcbc878e8a607e24b to your computer and use it in GitHub Desktop.
A tool to add routes for domains as the work VPN is slow and crap. Also, me learning python.
#!/usr/bin/env python3
import argparse
import dns.resolver
import netifaces
from subprocess import call
def get_interface_by_ip(ip):
"""Given an IP will return the interface associated. Doesn't support the same IP bound to multiple interfaces.
Args:
ip: The IP that belongs to a given interface
Returns:
A string that represents a given interface
"""
for interface in netifaces.interfaces():
# Get the addresses of all interfaces
addresses = netifaces.ifaddresses(interface)
# Check if the interface has an ipv4 address assigned to it
if netifaces.AF_INET in addresses:
# Iterate through the ipv4s checking if peer matches next hop
for ipv4 in addresses[netifaces.AF_INET]:
if 'peer' in ipv4 and ipv4['peer'] == ip:
return interface
raise FileNotFoundError('Could not identify an interface with the IP "' + ip + '"')
def get_ips(domain):
""" Given a domain, looks up the IP
Args:
domain: The domain that should be queried
Returns:
A string IP value for the domain
"""
result = dns.resolver.query(domain, 'A')
ips = []
for answer in result:
ips.append(answer.to_text())
return ips
def get_args():
"""Renders and returns the arguments from the CLI
Returns:
The namespace object containing arguments of the form:
{
'argument_name': 'argument_value'
}
"""
parser = argparse.ArgumentParser(description='Add a route for a given domain to a given interface. Only supports IPv4')
# Add the arguments
parser.add_argument('--domain', dest='domain', action='store', required=True,
help='The domain that you would like to route to via a given interface')
parser.add_argument('--next-hop', dest='next_hop', action='store', required=True,
help='The next hop to route over')
return parser.parse_args()
def main():
args = get_args()
ips = get_ips(args.domain)
interface = get_interface_by_ip(args.next_hop)
for ip in ips:
result = call(['ip', 'route', 'add',ip + '/32', 'via',args.next_hop,'dev',interface])
if result == 2:
raise PermissionError('Unable to add the route: insufficient permissions')
elif result > 0:
raise Exception('Unable to add the route: exit code from "ip" nonzero (' + result + ')')
else:
print('Added route for "' + ip + '" via "' + args.next_hop + ' (' + interface + ')"')
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment