Let's Encrypt SSL Certificates for DD-WRT 05 Jan, 2021 Comments Let's Encrypt SSL Certificates for DD-WRT

Note to self on setting up Let’s Encrypt SSL certificates for DD-WRT.

Prerequisites: a router with DD-WRT with a USB port (to mount external USB drive via jffs), an external USB drive, and a domain to assign to your router. My notes on the router setup are here.

  • Create or renew the necessary certificate.
  • openssl rsa -in privkey.pem -out key.pem
  • scp *.pem root@router:/jffs/etc/
  • Router settings > Administration > Web Access > Protocol > HTTPS (check this box)
  • Router settings > Administration > Remote Access > Use HTTPS (check this box), and set Web GUI Port to 443
  • Save, Apply Settings, and Reboot Router (for good measure).
  • Copy to /jffs/etc/ and run this script, following instructions from this gist

Effectively, this mount-binds the corresponding cert.pem, and key.pem into /etc/*.pem followed by servicestart httpd.

Worked like a charm!

References


Airprint with CUPS on DD-WRT 27 Jul, 2020 Comments Airprint with CUPS on DD-WRT

Another note to self on enabling Airprint for a legacy network printer with Avahi and CUPS on DD-WRT (HP P3005).

Prerequisites: router with DD-WRT and a USB port (to install cupsd via Entware), a network capable printer. My notes on the router setup are here.

Mostly a rehash of the tutorials from TomatoUSB1 and EzUnix2, in case those links go dead:

  • opkg install hplip-full
  • opkg install cups cups-filters cups-pdf # this was required to get CUPS to recognize application/pdf as valid filter and to enable pdftoraster needed below.
  • Add this to Firewall starup script:

      # CUPSd WebInterface (http/tcp)
      iptables -I INPUT -p tcp --dport 631 -i vlan2 -j ACCEPT
      # CUPSd printer port
      iptables -I INPUT -p tcp --dport 9100 -i vlan2 -j ACCEPT
    
  • Navigate to CUPS web interface http://< router-ip >:631 > Administration > Add Printer
    • Choose HP Printer (HPLIP), Continue
    • Connection: socket://< network-printer-ip >:9100, Continue
    • Provide Name, Description, Location and choose to ‘Share This Printer’, Continue
    • Choose Make: HP, Continue
    • Choose Model: HP LaserJet p3005…, Add Printer
  • Run:

      echo "image/urf application/pdf 100 pdftoraster" > /opt/share/cups/mime/airprint.convs
      echo "image/urf urf string(0,UNIRAST<00>)" > /opt/share/cups/mime/airprint.types
    
  • Create /opt/etc/avahi/services/airprint-hpp3005.service with the following content 3,4:

      <?xml version='1.0' encoding='UTF-8'?>
      <!DOCTYPE service-group SYSTEM "avahi-service.dtd">
      <service-group>
        <name replace-wildcards="yes">AirPrint HP1220C @ %h</name>
        <service>
          <type>_ipp._tcp</type>
          <subtype>_universal._sub._ipp._tcp</subtype>
          <port>631</port>
          <txt-record>txtvers=1</txt-record>
          <txt-record>qtotal=1</txt-record>
          <txt-record>Transparent=T</txt-record>
          <txt-record>URF=none</txt-record>
          <txt-record>rp=printers/(name-from-cups)</txt-record>
          <txt-record>note=your note</txt-record>
          <txt-record>product=(GPL Ghostscript)</txt-record>
          <txt-record>printer-state=3</txt-record>
          <txt-record>printer-type=0x82b01c</txt-record>
          <txt-record>pdl=application/octet-stream,application/pdf,application/postscript,image/gif,image/jpeg,image/png,image/tiff,image/urf,text/html,text/plain,application/vnd.cups-banner,application/vnd.cups-command,application/vnd.cups-pdf,application/vnd.cups-postscript</txt-record>
        </service>
      </service-group>
    

    You could generate this file from TJ Fontaine’s airprint-generate, but that did not work for me with some Python errors I chose not to pursue.

  • /opt/etc/init.d/rc.unslung restart

Done, you should find this printer via Airprint. You can use the CUPS web interface to configure printer defaults (duplex, two-sided printing, economy/high quality etc.).

For the record, HP p3005 has a decent web interface at http://< printer-ip > and also at the CUPS port: http://< printer-ip >:631.

References


Managing Your Internet Of 24 Jun, 2020 Comments Managing Your Internet Of

This is yet another note to self on setting up my home network to isolate ‘smart’ and other IoT devices into isolated networks in their own subnets, but having a functional UX for the family.

Contents

  1. End Goal
  2. Choosing a version of DD-WRT
  3. Virtual Interface (WLAN) and VLAN Setup
  4. mDNS Setup for Media Devices
  5. Static Route
  6. Firewall
  7. Caveat
  8. Conclusion
  9. Acknowledgements

End Goal

Here’s an outline of the end goal in ASCII art:

                                               / WLAN B1 (10.2.2.1/24) - Miscl. Devices
                                              / 
ISP -- Gateway/Router-A ---- Gateway/Router-B ---- WLAN B2 (10.3.3.1/24) - IoT Devices
             |                  (DD-WRT)      \
             |              [10.1.1.100/32]    \ LAN B3 (10.4.4.1/24)
          WLAN A1                                    |          |
       (10.1.1.1/24)                             AppleTV   Chromecast
       |     |     |
       Mobile Phones

Choosing a version of DD-WRT

The version of firmware recommended on DD-WRT’s router database is quite a bit dated, and using the bleeding edge beta from the forums isn’t always dependable, so I’ve recently started picking up builds recommended on flashrouter.

Virtual Interface (WLAN) and VLAN Setup

Router-B runs DD-WRT firmware in the Gateway mode. The basic setup itself is a straight forward adaptation of Guest Wi-Fi setup on dd-wrt wiki. Basically, Wireless > Basic Settings > new Virtual interface with AP Isolation enabled, and running a Unbridged network configuration with NAT, Net Isolation and DNS redirection enabled. In addition, I have a VLAN setup for LAN B3 with one of the physical LAN ports on the router. Similar configuration for the VLAN, can be configured under Setup > Networking. The IP Address/subnet here will be that of the interface, eg. 10.x.y.z/24. At the bottom of Setup > Networking > DHCPD, I setup a different DHCPD for each of the WLANs, and VLAN.

Virtual Interface Setup

mDNS Setup for Media Devices

These rely on mDNS broadcasts to allow client devices to discover services. However, by default these broadcasts don’t are local to the subnet of the (AppleTV/Chromecast) device. A solution for cross subnet/interface broadcasts would be the avahi-daemon. Fortunately, DD-WRT supports installing tools such as this via Entware opkg command. I have Entware running off a tiny flash drive setup as described in installing Entware followed by opkg update && opkg upgrade && opkg install avahi-utils. Here’s my /opt/etc/avahi/avahi-daemon.conf 1:

[server]
use-ipv4=yes
use-ipv6=no
check-response-ttl=no
use-iff-running=no
allow-interfaces=br0,vlan2,vlan6
allow-point-to-point=yes
enable-dbus=no

[publish]
publish-addresses=yes
publish-hinfo=yes
publish-workstation=no
publish-domain=yes

[reflector]
enable-reflector=yes
reflect-ipv=no

[rlimits]
rlimit-core=0
rlimit-data=4194304
rlimit-fsize=0
rlimit-nofile=30
rlimit-stack=4194304
rlimit-nproc=3

[wide-area]
enable-wide-area=yes

This snippet in Administration > Commands > Save Startup will auto start avahi-daemon:

# Start avahi/mDNS
echo "nogroup:x:114:nobody" >> /etc/group
/opt/etc/init.d/rc.unslung start

And save the following with ‘Save Firewall’. [The TTL bit was a nice find][1].

# Chromecast/AppleTV mDNS advertisements on vlan6 (AppleTV/Chromecast), from WAN
iptables -I INPUT -p udp --dport 1900 -i `get_wanface` -j ACCEPT
iptables -I INPUT -p udp --dport 1900 -i vlan6 -j ACCEPT
iptables -I FORWARD -p udp --dport 5353 -i `get_wanface` -j ACCEPT
iptables -I FORWARD -p udp --dport 5353 -i vlan6 -j ACCEPT
iptables -I INPUT -p udp --dport 5353 -i `get_wanface` -j ACCEPT
iptables -I INPUT -p udp --dport 5353 -i vlan6 -j ACCEPT

# Increase IP TTL so it can go an extra hop
iptables -t mangle -A PREROUTING -d 239.255.255.250 -j TTL --ttl-inc 1
iptables -t mangle -A PREROUTING -d 224.0.0.251 -j TTL --ttl-inc 1

I verified avahi-daemon/mDNS working by firing up Tildesoft’s Discovery app and looking for my devices and also by firing up YouTube app for casting and the phone’s AirPlay to mirror the screen. The devices are now discoverable by phones and other clients.

However, the actual AirPlay mirroring and casting don’t work :-)

Static Route

mDNS discovery responses contain the IP/Port of the service so clients know how to reach these devices.

_googlecast._tcp.
    Chromecast-xyz
        10.4.4.4:8009
        ...

Starting with a simple traceroute 10.4.4.4 in WLAN A1 in subnet 10.1.1.1/24, it was clear that the network did not know how to route the packets destined for 10.4.4.4. So a friend suggested adding a static route in Gateway/Router-A for packets bound to 10.4.4.0/24 with Gateway 10.1.1.100. And traceroute went until the gateway, and stopped at that with 100% packet loss.

Firewall

The final piece of the puzzle was in figuring out the firewall rules. I started off with a catchall rule that accepted all forwarded traffic to vlan2 (which is the default WAN interface on DD-WRT devices; run get_wanface in an SSH session into your router to check).

Then I added ports 8008, 8009, and high ports as a FORWARD rule, an adaptation from 2, including this to the ‘Save Firewall’ script. Note that I had also added TCP ports based on a packet type from a Wireshark packet capture of the session that failed to connect with firewall enabled for UDP packets.

# https://blog.g3rt.nl/allow-google-chromecast-host-firewall-iptables.html
# Punch a hole out of the router into the private 'WAN'
iptables -I FORWARD -i vlan2 -p tcp --dport 7000 -j ACCEPT
iptables -I FORWARD -i vlan2 -p tcp -m multiport --sports 32768:61000 -m multiport --dports 32768:61000 -j ACCEPT
iptables -I FORWARD -i vlan2 -p tcp -m multiport --dports 8008:8009 -j ACCEPT
# van6: Media Center
iptables -I FORWARD -i vlan6 -p tcp --dport 7000 -j ACCEPT
iptables -I FORWARD -i vlan6 -p tcp -m multiport --sports 32768:61000 -m multiport --dports 32768:61000 -j ACCEPT
iptables -I FORWARD -i vlan6 -p tcp -m multiport --dports 8008:8009 -j ACCEPT

Caveat

We have some early Wemo light switches which did not really play nice with AP and Net Isolation on the Virtual Interfaces, so for the corresponding VAP, these are disabled.

Conclusion

And, that’s all folks. With this, I have devices isolated in their own networks/subnets that are firewalled off, but still usable across subnets for casting/AirPlay mirroring.

Acknowledgements

Thanks to the DD-WRT contributors, community for the very usable software and readable documentation. Thank you to the authors of https://www.shackleton.io and https://blog.gert.nl for the very helpful tips. Many thanks to @zyxmon and @ryzhovau of Entware for quickly fixing a bug with avahi-utils on DD-WRT.

And of course, to my family, for bearing with many, many, many network disruptions!

References


On Good and Evil 20 Jun, 2020 Comments

Yes, evil often seems to surpass good. But then, in spite of us, and without our permission, there comes at last an end to the bitter frosts. One morning the wind turns, and there is a thaw. And so I must still have hope.

Vincent van Gogh, quoted on Twitter


OpenVPN Client on ASUS RT-AC68U with DD-WRT Firmware 26 May, 2020 Comments OpenVPN Client on ASUS RT-AC68U with DD-WRT Firmware

Note to self on setting up OpenVPN Client on Asus RT-AC68U Router with DD-WRT.

The goal of this exercise was to have OpenVPN client installed on a router that allows my family to enable/disable VPN via simple webapp, without dealing with the full settings page of the router management tool.

I had an old TM-AC1900 Cellspot router, but that’s basically a hobbled (in software) version of the capable RT-AC168U hardware. So, first step is to get a capable firmware installed.

I could not host this stand-alone webapp on a local store or webserver as CORS protection kicks in (both for DD-WRT and for the stock ASUS RT-AC68U firmware). With ssh access to the router, I can host the standalone webapp on the same webserver and avoid the CORS restriction.

Between the stock ASUS firmware vs DD-WRT, I prefer DD-WRT for this setup since access to http://router.local/user/ is not password protected, so the user experience (UX) is seamless – for local users connected to. Another ‘benefit’ with DD-WRT is the use of ‘Basic Authentication’ as opposed to some other protocol with the ASUS stock firmware (for an early iteration, I leant towards an insecure setup to simplify UX for the family – in my case, the DD-WRT router wasn’t directly connected to the WAN, but behind another router, so I was taking a risky chance). For actual auth with the router firmware to enable/disable the OpenVPN client, I simply hard-coded the Authentication: Basic <hash> header. Much of the ‘reverse engineering’ of the request/response for the enable/disable OpenVPN client were by simply observing the network traffic with the browser developer tool’s network tab 1 and looking at the request/response headers and the form data.

  1. Transform an old TM-AC1900 to RT-AC68U with this excellent guide from Bay Area Tech Pros2
    • Crucial to getting the CFE to show up was clear NVRAM in step 20 (Power off, Hold WPS button and power on while holding WPS button until the power LED begins to flash quickly)
    • And, navigating to 192.168.1.1 very quickly (seems like the CFE page is only available for a short window after reboot/reset/nvram clear)
  2. Upgrade RT-AC68U to DD-WRT, with the latest beta from the ftp location 3.
  3. Setup OpenVPN client. I tried both ProtonVPN and Surfshark VPN 4 as the providers, both of which have excellent documentation 5. Retrieve the OpenVPN credentials from https://account.protonvpn.com/account#openvpn or https://account.surfshark.com/setup/manual, respectively.
  4. ssh into the router, copy the standalone webapp to /jffs/<user>/, and run ln -s /jffs/<user>/webapp.html /www/user/webapp.html
  5. /jffs/<user>/ is persistent storage, but /www/user isn’t and gets reset on reboot. So create a startup script with the above ln command.
  6. A stripped down version of the webapp I hacked up is here 6.

Quick References




     
Original design for Tumblr crafted by Prashanth Kamalakanthan.
Adapted for Tumblr & Jekyll by Sai Charan. Customized theme available on Github.

Sai Charan's blog by Sai Charan is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
Creative Commons License