Skip to content

Commit

Permalink
Merge pull request #72 from josmo/allow-vpn-dns-for-domains
Browse files Browse the repository at this point in the history
MacOS implementation of domain specific use of vpn dns
  • Loading branch information
gmacon authored Jan 16, 2021
2 parents a52880c + 4e8ebc4 commit 7c8c607
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 2 deletions.
22 changes: 21 additions & 1 deletion vpn_slice/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@ def get_default_providers():
prep = CheckTunDevProvider,
)
elif platform.startswith('darwin'):
from .mac import PsProvider, BSDRouteProvider
from .mac import PsProvider, BSDRouteProvider, MacSplitDNSProvider
from .posix import PosixHostsFileProvider
from .dnspython import DNSPythonProvider
return dict(
process = PsProvider,
route = BSDRouteProvider,
dns = DNSPythonProvider or DigProvider,
hosts = PosixHostsFileProvider,
domain_vpn_dns = MacSplitDNSProvider,
)
elif platform.startswith('freebsd'):
from .mac import BSDRouteProvider
Expand Down Expand Up @@ -134,6 +135,13 @@ def do_disconnect(env, args):
except sp.CalledProcessError:
print("WARNING: failed to deconfigure firewall for VPN interface (%s)" % env.tundev, file=stderr)

if args.vpn_domains is not None:
try:
providers.domain_vpn_dns.deconfigure_domain_vpn_dns(args.vpn_domains, env.dns)
except:
print("WARNING: failed to deconfigure domains vpn dns", file=stderr)


def do_connect(env, args):
global providers
if args.banner and env.banner:
Expand Down Expand Up @@ -219,6 +227,14 @@ def do_connect(env, args):
if args.verbose:
print("Restored routes for %d excluded subnets." % len(exc_subnets), exc_subnets, file=stderr)

# Use vpn dns for provided domains
if args.vpn_domains is not None:
if 'domain_vpn_dns' not in providers:
print("WARNING: no split dns provider available; can't split dns", file=stderr)
else:
providers.domain_vpn_dns.configure_domain_vpn_dns(args.vpn_domains, env.dns)


def do_post_connect(env, args):
global providers
# lookup named hosts for which we need routes and/or host_map entries
Expand Down Expand Up @@ -429,6 +445,7 @@ def parse_args_and_env(args=None, environ=os.environ):
g.add_argument('-D','--dump', action='store_true', help='Dump environment variables passed by caller')
g.add_argument('--no-fork', action='store_false', dest='fork', help="Don't fork and continue in background on connect")
g.add_argument('--ppid', type=int, help='PID of calling process (normally autodetected, when using openconnect or vpnc)')
g.add_argument('--domains-vpn-dns', dest='vpn_domains', default=None, help="comma seperated domains to query with vpn dns")
args = p.parse_args(args)
env = parse_env(environ)
return p, args, env
Expand Down Expand Up @@ -470,6 +487,9 @@ def finalize_args_and_env(args, env):
if args.route_splits:
args.subnets.extend(env.splitinc)
args.exc_subnets.extend(env.splitexc)
if args.vpn_domains is not None:
args.vpn_domains = str.split(args.vpn_domains, ',')


def main(args=None, environ=os.environ):
global providers
Expand Down
21 changes: 20 additions & 1 deletion vpn_slice/mac.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ipaddress import ip_network, ip_interface

from .posix import PosixProcessProvider
from .provider import RouteProvider
from .provider import RouteProvider, SplitDNSProvider
from .util import get_executable


Expand Down Expand Up @@ -112,3 +112,22 @@ def add_address(self, device, address):
# with BSD ifconfig. See example in default vpnc-script:
# https://gitlab.com/openconnect/vpnc-scripts/blob/https://gitlab.com/openconnect/vpnc-scripts/blob/921e8760/vpnc-script#L193
self._ifconfig(device, 'inet', address.ip, address.ip, 'netmask', '255.255.255.255')


class MacSplitDNSProvider(SplitDNSProvider):
def configure_domain_vpn_dns(self, domains, nameservers):
if not os.path.exists('/etc/resolver'):
os.makedirs('/etc/resolver')
for domain in domains:
resolver_file_name = "/etc/resolver/{0}".format(domain)
with open(resolver_file_name, "w") as resolver_file:
for nameserver in nameservers:
resolver_file.write("nameserver {}\n".format(nameserver))

def deconfigure_domain_vpn_dns(self, domains, nameservers):
for domain in domains:
resolver_file_name = "/etc/resolver/{0}".format(domain)
if os.path.exists(resolver_file_name):
os.remove(resolver_file_name)
if not len(os.listdir('/etc/resolver')):
os.removedirs('/etc/resolver')
15 changes: 15 additions & 0 deletions vpn_slice/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,18 @@ def prepare_tunnel(self):
Base class behavior is to do nothing.
"""

class SplitDNSProvider:
def configure_domain_vpn_dns(self, domains, nameservers):
"""Configure domain vpn dns.
Base class behavior is to do nothing.
"""

def deconfigure_domain_vpn_dns(self, domains, nameservers):
"""Remove domain vpn dns.
Base class behavior is to do nothing.
"""

0 comments on commit 7c8c607

Please sign in to comment.