Tags

, ,

This post is intended to show you how to configure a Juniper SRX to be a DNS proxy for your network. This will allow you to forward DNS queries to both a private DNS server for your local domain and a public DNS server for all other requests.

Using the SRX as a DNS proxy has a few advantages for a network administrator. The first being that if you need to ever change an upstream DNS server pointer, you just need to update the SRX and not all the clients. The second is that if you want to split domain name DNS queries among different DNS servers, you can do that. This is good if you have a .local domain server locally or over a VPN. This will allow you to keep that query local, yet all other requests will go to a public DNS server.

The topology for this lab is as follows:

  • The internal network in this topology is my Home network that is providing access to the Internet.
  • The SRX is configured with DHCP on the UNTRUST side to obtain an IP from my home network.
  • SRX is configured with a static IP of 192.168.100.1/24 on the TRUST side.
  • SRX is acting as DHCP server for 192.168.100.0/24 and serving DNS server IP of 192.168.100.1.
  • The SRX is NATing all traffic from TRUST to the UNTRUST interface.
  • Linux host is a simple Ubuntu 16.04 desktop default in EVE-NG.

You can find a copy of the EVE-NG topology as well as the SRX start and final configs in my github repository: https://github.com/FryguyPA/Junos-SRX-DNS-Proxy

Below is the starting config for the SRX. Here you can see that we have DHCP configured and a simple security policy that first denies any and DNS queries from the Trust network to the internet and then permits all other traffic.

root@DNS-PROXY> show configuration | no-more   
## Last commit: 2020-07-06 14:45:50 UTC by root
version 18.4R1-S3.1;
system {
    root-authentication {
        encrypted-password "$6$QjdQ6ulL$SWuULtkXo0DXpT4dKIEOedY3zfLHDnAS8lL7LOzZDdQ6QBn6XGKYOE11c.du8uAf873zcwRCm.gf.pKqyxymV."; ## SECRET-DATA
    }
    services {
        dhcp-local-server {
            group TRUST {
                interface ge-0/0/1.0;
            }
        }
    }
    host-name DNS-PROXY;
}
security {
    nat {
        source {
            rule-set OVERLOAD {
                from zone TRUST;
                to zone UNTRUST;
                rule OVERLOAD {
                    match {
                        source-address 192.168.100.0/24;
                        destination-address 0.0.0.0/0;
                    }
                    then {
                        source-nat {
                            interface;
                        }
                    }
                }
            }
        }
    }
    policies {
        from-zone TRUST to-zone UNTRUST {
            policy DENY-DNS {
                match {
                    source-address any;
                    destination-address any;
                    application [ junos-dns-tcp junos-dns-udp ];
                }
                then {
                    reject;
                }
            }
            policy PERMIT-ALL {
                match {
                    source-address any;
                    destination-address any;
                    application any;
                }
                then {
                    permit;
                }
            }
        }
    }
    zones {
        security-zone TRUST {
            host-inbound-traffic {
                system-services {
                    all;
                }
                protocols {
                    all;
                }
            }
            interfaces {
                ge-0/0/1.0;
            }
        }
        security-zone UNTRUST {
            host-inbound-traffic {
                system-services {
                    dhcp;
                }
            }
            interfaces {
                ge-0/0/0.0;
            }
        }
    }
}
interfaces {
    ge-0/0/0 {
        unit 0 {
            family inet {
                dhcp;
            }
        }
    }
    ge-0/0/1 {
        unit 0 {
            family inet {
                address 192.168.100.1/24;
            }
        }
    }
}
access {
    address-assignment {
        pool 192-168-100-0 {
            family inet {
                network 192.168.100.0/24;
                range POOl-RANGE {
                    low 192.168.100.100;
                    high 192.168.100.200;
                }
                dhcp-attributes {
                    domain-name fryguy.lab;
                    name-server {
                        192.168.100.1;
                    }
                    router {
                        192.168.100.1;
                    }
                }
            }
        }
    }
}

A key point the above configuration is that we are all system-services and traffic under the TRUST zone. If your deployment has more granular host-inbound-traffic policies, you will need to add DNS to the list of host-inbound-traffic as seen below.

set security zones security-zone TRUST host-inbound-traffic system-services dns

Now for this lab we will use two public DNS servers ( 9.9.9.9 and 8.8.8.8 ) and one internal DNS server to handle requests for fryguy.local (192.168.0.3). The fryguy.local DNS server is a local-only server for my home network and has a few entries already. You can see a list of those entries in the image below.

Before we start, let us take a moment and demonstrate that we are currently unable to resolve DNS queries on the Ubuntu host. We will try to lookup www.google.com, www.fryguy.net and plex.fryguy.local.

The way that you configure the DNS proxy on the SRX is found under system services dns. As you can see below, we have a few options we can configure. For this blog, we will just focus on the dns-proxy configuraiton.

[edit]
root@DNS-PROXY# edit system services dns dns-proxy

[edit system services dns dns-proxy]
root@DNS-PROXY# 

Now the first thing we need to configure if the interface that the DNS requests are coming in on. For this configuration that is our TRUST interface, ge-0/0/1.0.

[edit system services dns dns-proxy]
set interface ge-0/0/1.0 

Now we need to configure a forwarder for the fryguy.local domain to use my internal DNS server at 192.168.0.3. This is done by using the default-domain option so that it matches fryguy.local and then configuring the forwarder to use 192.168.0.3.

[edit system services dns dns-proxy]
set default-domain fryguy.local forwarders 192.168.0.3

One security feature of configuring this is that it means that any DNS query for fryguy.local will never be queried to any other DNS server others than those specified (192.168.0.3). This can help prevent internal DNS queries from hitting a public server and leaking internal DNS names.

Now we will configure a wildcard match (*) for all other domains to use 9.9.9.9 and 8.8.8.8.

[edit system services dns dns-proxy]
set default-domain * forwarders 9.9.9.9
set default-domain * forwarders 8.8.8.8

If you wanted to configure more domains, you can add them with their perspective DNS server. This can help to troubleshoot problems with DNS lookups – you can say that digitalocean.com domain should use 173.245.58.51 while all others use the defaults of 9.9.9.9 and 8.8.8.8.

If you need to have a static entry for a DNS server, for troubleshooting or testing, you can configure that under the cache option. Here I actually configured a site that I wanted to block to point to an internal web server that hosts a message for the user saying that the site is blocked.

[edit system services dns dns-proxy]
set cache www.someblockedsite.com inet 192.168.0.3

When all is said and done, here is what we have added to the configuration to make the SRX the DNS proxy server for the network.


[edit system services dns dns-proxy]
root@DNS-PROXY# show   
interface {
    ge-0/0/1.0;
}
default-domain fryguy.local {
    forwarders {
        192.168.0.3;
    }
}
default-domain * {
    forwarders {
        9.9.9.9;
        8.8.8.8;
    }
}
cache {
    www.someblockedsite.com inet 192.168.0.3;
}

Now when we test those same DNS lookups from the Ubuntu server, we get successful queries.

If you want to check to see if your DNS proxy is working, you can do that by using the command show system services dns-proxy statistics. Here you can see that we had 3 queries.

To check the DNS cache on the device, you can use the command show system services dns-proxy cache.


root@DNS-PROXY> show system services dns-proxy statistics    
DNS proxy statistics        :
    Status                  : enabled          
    IPV4 Queries received   : 3                
    IPV6 Queries received   : 0                
    Responses sent          : 3                
    Queries forwarded       : 3                
    Negative responses      : 0                
    Positive responses      : 3                
    Retry requests          : 0                
    Pending requests        : 0                
    Server failures         : 0                
    Interfaces              : ge-0/0/1.0

root@DNS-PROXY> show system services dns-proxy cache         
Hostname                  Time-to-live   Type        Class    IP address/Hostname
www.google.com.           154            A           IN       172.217.12.196
www.fryguy.net.           285            A           IN       165.22.42.217

If you need to clear the DNS Cache on the device, you can issue the command clear system services dns-proxy cache.

In the end, here is what our configuration now looks like, with the DNS-proxy configured and working.