Thursday, June 22, 2017

DHCP, dnsmasq and the ASUS EA-AC87 Wireless Router

Today Marcus and Agata had a more detailed look at the Linux Based Asus EA-AC87 Router and got DHCP working.  And here is how

The Problem Stated
The Asus EA-AC87 is a Wireless router than can also operate as a Bridge.  We use it as a Wirless router in the following way

- We have an Internet Connection
- It passes thru some Firewalls
- Then out into our Home Etheret Cabling
- Then finally into the ASUS EA-AC87
- We setup the ASUS as a wireless router but DHCP has to come from somewhere else

We already used a Raspberry Pi as a custom DHCP server  but today we had the time to start reconfiguring our Network properly.  We recently moved house and made a 'lash up' Internet Configuration, which was not secure.

Today we divided it up and the Raspberry Pi was no longer visible to the ASUS because the ASUS now sits on its own isolated network.

What to do?

#Option1 == Buy another Raspberry Pi and configure it on this new subnet

#Option2: Sneak into the ASUS EA-AC87 Router

I found it is possible to Telnet into the router and use your web credentials to give root level access, for us, the user admin

I had a look around at the UNIX filesystem and found some relevent scripts:
Some Scripts
cd /scripts
quantenna # ls -l dh**
-rwxrwxr-x    1 root     root          908 Aug 21  2015 dhclient_restart

-rwxrwxr-x    1 root     root          898 Aug 21  2015


CUR_MODE=`call_qcsapi get_mode wifi0`
if [ "${CUR_MODE}" != "Access point" ] ; then
        echo "Not AP Mode"
        exit 0;
LAN_PROTO=`nvram get lan_proto`
if [ "${LAN_PROTO}" != "dhcp" ] ; then
        echo "Not DHCP client"
        exit 0;
sleep 10
nvram set reset_lan_client=0
while [ 1 = 1 ] ;
if [ -e /tmp/dhclient.leases ] ; then
        CHECK_IP=`cat /tmp/dhclient.leases |grep fixed-address|awk '{print $2}'`
        if [ -z $CHECK_IP ] ; then
                # echo "DHCPD not found, set LAN to and start dnsmasq"
                if [ ! -f /tmp/ ] ; then
                        ifconfig br0
                        dnsmasq -z br0 -l /tmp/dnsmasq.leases -F,,24h -A /
                # else
                        # echo "DNSMASQ existed, keep waiting DHCP server"
                nvram set reset_lan_client=1
                echo "*** found DHCPD, IP is " $CHECK_IP
                killall dnsmasq
                exit 0
        dhclient -4 br0 &
        sleep 5

So I found some dhcp scripts which made use of the dnsmasq command   So all we need to do is start that up then, right?   I had to research dmsmasq on the Web since I never heard of it before.

quantenna # /usr/sbin/dnsmasq --help
Usage: dnsmasq [options]

Valid options are :

-a, --listen-address=ipaddr         Specify local address(es) to listen on.
-A, --address=/domain/ipaddr        Return ipaddr for all hosts in specified domains.
-b, --bogus-priv                    Fake reverse lookups for RFC1918 private address ranges.
-B, --bogus-nxdomain=ipaddr         Treat ipaddr as NXDOMAIN (defeats Verisign wildcard).
-c, --cache-size=cachesize          Specify the size of the cache in entries (defaults to 150).
-C, --conf-file=path                Specify configuration file (defaults to /etc/dnsmasq.conf).
-d, --no-daemon                     Do NOT fork into the background: run in debug mode.
-D, --domain-needed                 Do NOT forward queries with no domain part.
-e, --selfmx                        Return self-pointing MX records for local hosts.
-E, --expand-hosts                  Expand simple names in /etc/hosts with domain-suffix.
-f, --filterwin2k                   Don't forward spurious DNS requests from Windows hosts.
-F, --dhcp-range=ipaddr,ipaddr,time Enable DHCP in the range given with lease duration.
-g, --group=groupname               Change to this group after startup (defaults to dip).
-G, --dhcp-host=<hostspec>          Set address or hostname for a specified machine.
-h, --no-hosts                      Do NOT load /etc/hosts file.
-H, --addn-hosts=path               Specify a hosts file to be read in addition to /etc/hosts.
-i, --interface=interface           Specify interface(s) to listen on.
-I, --except-interface=int          Specify interface(s) NOT to listen on.
-j, --dhcp-userclass=<id>,<class>   Map DHCP user class to option set.
-J, --dhcp-ignore=<id>              Don't do DHCP for hosts in option set.
-k, --keep-in-foreground            Do NOT fork into the background, do NOT run in debug mode.
-K, --dhcp-authoritative            Assume we are the only DHCP server on the local network.
-l, --dhcp-leasefile=path           Specify where to store DHCP leases (defaults to /var/lib/misc/dnsmasq.leases).
-L, --localmx                       Return MX records for local hosts.
-m, --mx-host=host_name,target,pref Specify an MX record.
-M, --dhcp-boot=<bootp opts>        Specify BOOTP options to DHCP server.
-n, --no-poll                       Do NOT poll /etc/resolv.conf file, reload only on SIGHUP.
-N, --no-negcache                   Do NOT cache failed search results.
-o, --strict-order                  Use nameservers strictly in the order given in /etc/resolv.conf.
-O, --dhcp-option=<optspec>         Set extra options to be set to DHCP clients.
-p, --port=number                   Specify port to listen for DNS requests on (defaults to 53).
-P, --edns-packet-max=<size>        Maximum supported UDP packet size for EDNS.0 (defaults to 1280).
-q, --log-queries                   Log queries.
-Q, --query-port=number             Force the originating port for upstream queries.
-R, --no-resolv                     Do NOT read resolv.conf.
-r, --resolv-file=path              Specify path to resolv.conf (defaults to /etc/resolv.conf).
-S, --server=/domain/ipaddr         Specify address(es) of upstream servers with optional domains.
    --local=/domain/                Never forward queries to specified domains.
-s, --domain=domain                 Specify the domain to be assigned in DHCP leases.
-t, --mx-target=host_name           Specify default target in an MX record.
-T, --local-ttl=time                Specify time-to-live in seconds for replies from /etc/hosts.
-u, --user=username                 Change to this user after startup. (defaults to nobody).
-U, --dhcp-vendorclass=<id>,<class> Map DHCP vendor class to option set.
-v, --version                       Display dnsmasq version and copyright information.
-V, --alias=addr,addr,mask          Translate IPv4 addresses from upstream servers.
-W, --srv-host=name,target,...      Specify a SRV record.
-w, --help                          Display this message.
-x, --pid-file=path                 Specify path of PID file. (defaults to /var/run/
-X, --dhcp-lease-max=number         Specify maximum number of DHCP leases (defaults to 150).
-y, --localise-queries              Answer DNS queries based on the interface a query was sent to.
-Y  --txt-record=name,txt....       Specify TXT DNS record.
-z, --bind-interfaces               Bind only to interfaces in use.

-Z, --read-ethers                   Read DHCP static host information from /etc/ethers.

Man Page

-Z, --read-ethers
Read /etc/ethers for information about hosts for the DHCP server. The format of /etc/ethers is a hardware address, followed by either a hostname or dotted-quad IP address. When read by dnsmasq these lines have exactly the same effect as --dhcp-host options containing the same information. /etc/ethers is re-read when dnsmasq receives SIGHUP. IPv6 addresses are NOT read from /etc/ethers.
-O, --dhcp-option=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>|option6:<opt>|option6:<opt-name>],[<value>[,<value>]]
Specify different or extra options to DHCP clients. By default, dnsmasq sends some standard options to DHCP clients, the netmask and broadcast address are set to the same as the host running dnsmasq, and the DNS server and default route are set to the address of the machine running dnsmasq. (Equivalent rules apply for IPv6.) If the domain name option has been set, that is sent. This configuration allows these defaults to be overridden, or other options specified. The option, to be sent may be given as a decimal number or as "option:<option-name>" The option numbers are specified in RFC2132 and subsequent RFCs. The set of option-names known by dnsmasq can be discovered by running "dnsmasq --help dhcp". For example, to set the default route option to, do --dhcp-option=3, or --dhcp-option = option:router, and to set the time-server address to, do --dhcp-option = 42, or --dhcp-option = option:ntp-server, The special address is taken to mean "the address of the machine running dnsmasq".

I had a lot of difficulty figuring out the precise syntax of the command to be run.  In general you can put options into a file but since this is supposed to be a trivial command we thought a single command line would be best.

Unfortunately bad command line syntax kept producing a crashed binary with the message

Segmentation Fault

Until finally I read from the Man Page the proper way to specify options.  Unfortunately since the Asus uses Busybox a cut down Linux command line it does not respond properly to the command

dnsmasq --help dhcp

So I got the following information from my Linux booting Laptop.

dnsmasq --help dhcp  
Known DHCP options:
  1 netmask
  2 time-offset
  3 router
  6 dns-server
  7 log-server
  9 lpr-server
 13 boot-file-size
 15 domain-name
 16 swap-server
 17 root-path
 18 extension-path
 19 ip-forward-enable
 20 non-local-source-routing
 21 policy-filter
 22 max-datagram-reassembly
 23 default-ttl
 26 mtu
 27 all-subnets-local
 31 router-discovery
 32 router-solicitation
 33 static-route
 34 trailer-encapsulation
 35 arp-timeout
 36 ethernet-encap
 37 tcp-ttl
 38 tcp-keepalive
 40 nis-domain
 41 nis-server
 42 ntp-server
 44 netbios-ns
 45 netbios-dd
 46 netbios-nodetype
 47 netbios-scope
 48 x-windows-fs

 49 x-windows-dm

So Finally

dnsmasq --bind-interfaces br0 --dhcp-leasefile /tmp/dnsmasq.leases --dhcp-range,  --dhcp-option=3,   --dhcp-option=6,

When the above command is run as root on the Wireless router then its DHCP server is enabled and clients such as Google Chromecast Ultra and Google Home  which share this home network can now get a valid IP, Gateway and DNS and hence work.

Ah,  wonderful.

We like the EA-AC87 Router