How DNS Works with Twingate

Twingate is not a VPN, and instead uses a transparent proxy system to connect users to private Resources. By taking this approach, user devices never join your private network and also require neither direct routing nor private DNS resolver access to complete network connections. This allows you to simultaneously achieve a much stronger default security posture and a much-improved end user experience. Users can only access Resources that they have explicitly been granted access to, and Resource addresses are shielded from public inspection.

The step-by-step example flow and diagram below explains how users can access private DNS addresses without having access to the private DNS resolver. (Note that the same flow applies for Resources with public DNS entries: resolution will still pass through the configured Connector on your private network, overriding the public DNS lookup route directly from the user’s device.)

DNS Resolution Flow with Twingate

  • An application on the client device sends a DNS request for a private Resource to the operating system, which is intercepted by the Twingate Client application. The Twingate Client app runs a DNS resolver for this purpose.
  • The Twingate Client’s DNS resolver responds with an IP address uniquely assigned to the Resource. Note that this assigned IP address is not related to the actual private IP of the Resource in question. IP addresses are assigned from the shared 100.64.0.0/10 CGNAT range so as not to conflict with any local or configured network ranges.
  • The application on the user’s device initiates communication with the Twingate-assigned IP address and the Client acts as a transparent proxy, forwarding traffic to the appropriate Twingate Connector. The Twingate Client keeps a mapping between assigned IPs and Resources, with the effect being that local applications see DNS resolution for Twingate-defined private DNS entries.
  • The Connector, upon receiving the connection request, sends a DNS request to the network’s private DNS server. As long as the Connector is able to resolve the DNS resource you have defined in Twingate and route traffic to the destination, the connection to the private Resource will succeed.
  • The private DNS server responds with the private IP address of the Resource in question. This allows traffic to be routed to the destination host. The destination host’s IP address is not revealed to the Client or application as it sits behind the transparent proxy connection that Twingate has established.
  • Finally, the Connector initiates communication with the requested Resource’s private IP, proxying traffic from the application on the user’s device. This completes the end-to-end connection.

Why Does DNS Matter for Twingate?

Because most of our customers use Resources as FQDNs (Fully Qualified Domain Names aka DNS-style resources like nas.home.int) as opposed to IP addresses (like 192.168.1.50) or CIDR ranges (a CIDR Range is simply a range of consecutive IPs): So the central question around how the Twingate Client works now becomes:

“How does the Twingate Client resolve a FQDN like nas.home.int which is only resolvable by my internal DNS at home, when I am in fact NOT at home?”

This is an essential component of how we make it seamless for people to work remotely just as if they were in the office without configuring anything at all besides installing the Twingate Client so let’s dive deeper.

The Twingate Client knows what Resources it can access

Let’s assume [nas.home.int](http://nas.home.int) is a Twingate Resource our Twingate Client & User have legitimate access to.

Our local Twingate Client is given a copy of all the FQDNs and Addresses it has legitimate access to (including nas.home.int); our client uses this list locally to intercept the right traffic (it will intercept everything destined for [nas.home.int](http://nas.home.int) but will ignore anything for, say, [server.home.int](http://server.home.int) (because it isn’t a Twingate Resource)).

How the Twingate Client Resolves nas.home.int

In order to check the IP address the Client resolves for it, let’s use dig and find out. (dig is a command you can use on Macs & Linux to resolve the IP from the FQDN).

Let’s first look at the dig command with the Twingate Client OFF and resolve our local resource nas.home.int while on our home network:

my-mbp16 git % dig nas.home.int

; <<>> DiG 9.10.6 <<>> nas.home.int
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12309
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;nas.home.int.    IN  A

;; ANSWER SECTION:
nas.home.int.     86400     IN  A     192.168.1.50

;; AUTHORITY SECTION:
home.int.         86400     IN  NS    ns.home.int.

;; ADDITIONAL SECTION:
ns.home.int.      86400     IN  A     192.168.1.1

;; Query time: 153 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Mon Jun 27 19:05:27 EDT 2022
;; MSG SIZE  rcvd: 90

Great! it resolves to 192.168.1.50 which is indeed a local IP on my home network.

Now let’s run the same command but with the Twingate Client ON:

my-mbp16 git % dig nas.home.int

; <<>> DiG 9.10.6 <<>> nas.home.int
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57867
;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;nas.home.int.      IN  A

;; ANSWER SECTION:
nas.home.int.   15  IN  A 100.108.194.142

;; Query time: 83 msec
;; SERVER: 100.95.0.251#53(100.95.0.251)
;; WHEN: Mon Jun 27 19:01:55 EDT 2022
;; MSG SIZE  rcvd: 46

Hmm, the address resolved is no longer a local IP but a public IP within the CGNAT range..

In fact, you will notice 2 big differences once the Twingate Client is switched on:

  • [nas.home.int](http://nas.home.int) now resolves to 100.108.194.142 which is NOT a local IP address on our home network (it’s a public IP in the CGNAT Range)
  • the DNS Server is no longer 192.168.1.1 but is now 100.95.0.251

So.. Why does a local resource resolve to a public IP?

Because The Twingate Client needs to intercept all traffic meant for nas.home.int; and to do this, the Client does a few things on your device:

1. The Twingate Client sets up its own Network Interface, visible on Macs under Network:

And on Windows via the Control Panel:

See the Twingate Interface (next to last)

2. Upon start up the Twingate Client adds a Primary DNS Resolver (on top of the resolver list for my computer) that points to its own DNS servers (100.95.0.25[1-4])

my-mbp16 ~ % scutil --dns
DNS configuration

resolver #1
  nameserver[0] : 100.95.0.251
  nameserver[1] : 100.95.0.252
  nameserver[2] : 100.95.0.253
  nameserver[3] : 100.95.0.254
  if_index : 29 (utun7)
  flags    : Supplemental, Request A records
  reach    : 0x00000003 (Reachable,Transient Connection)
  order    : 102400

resolver #2
  nameserver[0] : 192.168.1.1
  if_index : 14 (en0)
  flags    : Request A records
  reach    : 0x00020002 (Reachable,Directly Reachable Address)
  order    : 200000

3. Twingate reconfigures its own DNS

This is to map internal FQDN-like resources like nas.home.int to IP Addresses in the CGNAT Range (in this case 100.108.194.142)

4. The Twingate Client modifies the local routing table on the device

This ensures all traffic addressed to IPs in the CGNAT range (100.96/12)is dealt with by the local Twingate Network Interface (utun7 in this case, see screenshot below).

(modifying the Routing Table basically tells the OS “if you see traffic meant for an IP in the CGNAT range, it needs to be handled by the Twingate Network Interface”)

my-mbp16 ~ % netstat -rn | grep utun7
default            link#29            UCSIg           utun7
10.0.0.5/32        link#29            UCS             utun7
10.0.1.25/32       link#29            UCS             utun7
10.0.1.102/32      link#29            UCS             utun7
10.0.1.244/32      link#29            UCS             utun7
10.128.0.5/32      link#29            UCS             utun7
10.128.0.8/32      link#29            UCS             utun7
10.128.0.112/32    link#29            UCS             utun7
100.95.0.251       172.16.30.1        UGHS            utun7
100.95.0.252       172.16.30.1        UGHS            utun7
100.95.0.253       172.16.30.1        UGHS            utun7
100.95.0.254       172.16.30.1        UGHS            utun7
100.96/12          link#29            UCS             utun7
172.16.30.1        172.16.30.1        UH              utun7
172.16.62.242/32   link#29            UCS             utun7
224.0.0/4          link#29            UmCSI           utun7
255.255.255.255/32 link#29            UCSI            utun7

Altogether, this ensures that:

  • [nas.home.int](http://nas.home.int) resolves to a CGNAT IP
  • all traffic for nas.home.intgets handled by the Twingate Network Interface (because it resolves to a CGNAT IP and because the Routing Table tells the OS that all CGNAT IPs need to be handled by the Twingate Network Interface)

What happens to Network Traffic once it reaches the Twingate Network Interface?

The Twingate Client has now successfully intercepted traffic for nas.home.int, now what?

This is where the 3 proxies that are in the Twingate Client intervene. (The Twingate Client has 3 proxies, one for each of the 3 protocols TCP, UDP and ICMP (ping only)).

How do network packets go from the Client to the Connector?

Before we answer this question, let’s take a look at what Network Packets actually contain.

To keep things simple, conceptually, a Network Packet contains:

  • data / a payload (actual information that needs to reach the destination)
  • a Destination IP (where the payload should be delivered)
  • a Source IP (where response packets should be sent to)

In short, think of it as a single Network Packet as:

[SOURCE IP][payload][DESTINATION IP]

Back to Proxies

The role of the proxy in the Twingate Client is to simply take the payload from the network traffic (without source or destination), and forward it from the Client to the Connector’s proxy via the network.

What does the Connector do with the Payload once it receives it?

At this point, the Connector locally resolves the original FQDN nas.home.int(which from the perspective of the Connector will correctly resolve to 192.168.1.50 via the private DNS on our home network) and reassembles the Payload in a new Network Packet with:

  • as a source: the Connector’s own IP (in our case 192.168.1.88)
  • as a destination: the resolved IP (192.168.1.50)
  • as a payload: the payload sent by the Twingate Client’s proxy

The Connector then sends the packets to the right destination (192.168.1.50) which responds with new network traffic now destined for the Twingate Client.

How does Traffic flow back from the Resource to the Client?

The traffic from the destination back to the Twingate Client works the exact opposite way:

  • the application responds with a payload to the Connector (which it gets from the “source IP” in the original packets sent by the Connector)
  • the Connector’s proxy strips the network packets from Source and Destination, forwards them to the Twingate Client’s proxy which reassembles the payload into network packets with the same payload and:
    • as a source: the local IP of the Twingate Network Interface (in this case 172.16.30.1)
    • as a destination: local IP of the Client This will ensure the traffic from the application flows back to my Twingate Client and therefore my computer.

Last updated 19 hours ago