openfortivpn
openfortivpn copied to clipboard
Use VPN only for certain domains
I am wondering if it is possible to use openfortivpn only for certain domains. For example, route *.myorganisation.com
but not others.
Well, openfortivpn mainly opens an SSL tunnel.
Then it does apply changes to the DNS and routing configuration of the client, according to the instructions sent by the router. You are free to further modify routes yourself, see for example How to add specific routes using pppd and option --no-routes
.
@DimitriPapadopoulos Thank you!
I understand that if I have a list of expected domains, like
a.myorganisation.com 192.168.1.10
b.myorganisation.com 192.168.1.11
I can resolve them in advance, and add specific routes using pppd.
However, I am wondering if it is still possible when the domain names *.myorganisation.com
(*
can be any subdomain) are not known in advance.
Just to clarify, is this a discussion about name resolution (DNS) or routing?
And where and when would the information "not known in advance" come from?
For example, assume that the organisation contains the following:
(name server) 192.168.1.2
a.myorganisation.com 93.184.216.34
b.myorganisation.com 93.184.216.35
... ...
x.myorganisation.com 192.168.1.10
y.myorganisation.com 192.168.1.11
... ...
Currently, after running openfortivpn and opening a certain application of the organisation, assume that the following things will happen:
- the application send an request to
*.myorganisation.com
(*
can be any subdomain) - connected to the 192.168.1.2 (the name server) via ppp0
- the domain name is resolved by 192.168.1.2 (the name server)
- connected to the corresponding IP address via ppp0
and,
- the application send an request to
google.com
(or any domain outside the organisation) - connected to the 192.168.1.2 (the name server) via ppp0
- the domain name is resolved by 192.168.1.2 (the name server)
- connected to the corresponding IP address via ppp0
Now what I want to achieve is:
- the application send an request to
*.myorganisation.com
(*
can be any subdomain) - we detect that the domain is ended with
.myorganisation.com
, so that should be resolved by 192.168.1.2 (the name server) - connected to the 192.168.1.2 (the name server) via ppp0
- the domain name is resolved by 192.168.1.2 (the name server)
- connected to the corresponding IP address via ppp0
and,
- the application send an request to
google.com
(or any domain outside the organisation) - we detect that the domain is not ended with
.myorganisation.com
, so that should be resolved by the original name server before running openfortivpn - connected to the original name server via the original interface
- the domain name is resolved by the original name server
- connected to the corresponding IP address via the original interface
OK. You want to use a different DNS server for different domains. I believe this is sometimes referred to as split DNS.
https://github.com/adrienverge/openfortivpn/search?q=%22split+DNS%22&type=issues
Currently, I run a custom Python DNS server to solve this issue:
import dnslib
import socket
import subprocess
upstream_internet = ('10.0.10.254', 53)
upstream_intranet = ('192.168.1.2', 53)
intranet_domain_suffix = '.myorganisation.com.'
socket_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket_server.bind(('127.0.0.1', 53))
socket_client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
# Receive
dns_query, addr = socket_server.recvfrom(512)
dns_query_record = dnslib.DNSRecord.parse(dns_query)
is_intranet = any(
str(question.qname).endswith(intranet_domain_suffix)
for question in dns_query_record.questions
if dnslib.QTYPE.get(question.qtype) == 'A'
)
# Dispatch
upstream_addr = upstream_intranet if is_intranet else upstream_internet
socket_client.sendto(dns_query, upstream_addr)
dns_answer = socket_client.recv(512)
dns_answer_record = dnslib.DNSRecord.parse(dns_answer)
# Add route
if is_intranet:
for rr in dns_answer_record.rr:
if dnslib.QTYPE.get(rr.rtype) == 'A':
ipv4_addr = repr(rr.rdata)
subprocess.run(['ip', 'r', 'add', ipv4_addr, 'dev', 'ppp0'])
# Response
socket_server.sendto(dns_answer, addr)
Instead of a python script you could use something like dnsmasq
with custom server
stanzas. Ex. server=/myorganization.com/192.168.x.x
would resolve all queries for *.myorganization.com
using 192.168.x.x
. Although maybe not - I'm not quite sure why you're adding routes in your script - that seems a bit weird. It seems you could push routes from FG as usual.