Created
June 17, 2018 11:10
Star
You must be signed in to star a gist
A tool to add routes for domains as the work VPN is slow and crap. Also, me learning python.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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