So it seems enough people are having problems with DD-WRT's built-in UPnP support, that there is an automated script that has been written that will fetch a prebuilt MiniUPnP package from a server, unpack it into the RAM disk, run the daemon, and reconfigure the firewall rules.
Unfortunately, the script didn't work out of the box for me. And I also prefer to not have to re-download the package every time I reboot the router. I would prefer to have a local copy, especially since I do have disk space available.
So first, in my opinion, the easiest thing to is just follow their instructions to get everything on your system. Then we'll apply the necessary changes. So run the following commands on the router.
wget http://hackthecode.googlecode.com/files/miniupnpd.sh -O /tmp/miniupnpd.sh chmod +x /tmp/miniupnpd.sh sh /tmp/miniupnpd.sh
Basically, this will fetch their magic installer script from their server. The script will be copied to /tmp which means it only exists in RAM and will disappear on reboot.
Then they run the script which grabs the actual binary executable from their server and then sets up the firewall rules.
So after their script completes, you should find an executable named miniupnpd in /tmp.
I copy this binary onto my permanent file system so I don't have to refetch it every time. Since this is not part of Optware, I decided to copy this to my storage on JFFS instead of my flash drive. It doesn't really matter, so take your pick. (This binary is small enough to fit within my JFFS space.)
Next, I make a directory in /jffs/usr/bin
mkdir -p /jffs/usr/bin
and I copy the binary there.
cp /tmp/minipnpd /jffs/usr/bin
Verify that the binary is executable. If it isn't, run
chmod +x /jffs/usr/bin/miniupnpd
Now before I go on, miniupnpd supports reading a configuration file for settings. But the web install script package we just grabbed doesn't use a configuration file. I want the configuration file so I can easily enable NAT-PMP support and tweak other settings I might be interested in. (I hope to disable UPnP some day soon in favor of NAT-PMP if it turns out that 100% of my apps support it.) So I sifted through the MiniUPnP source repository and grabbed their default configuration file and made a few tweaks to it. The most important tweak is to enable NAT-PMP. I also played with a few other settings, but these are probably minor things that you probably won't notice one way or the other.
I copied the file to /jffs/etc/miniupnpd.conf
# WAN network interface #ext_ifname=eth0 #ext_ifname=xl1 # if the WAN interface has several IP addresses, you # can specify the one to use below #ext_ip= # LAN network interfaces IPs / networks # there can be multiple listening ips for SSDP traffic. # should be under the form nnn.nnn.nnn.nnn/nn # HTTP is available on all interfaces # When MULTIPLE_EXTERNAL_IP is enabled, the external ip # address associated with the subnet follows. for example : # listening_ip=192.168.0.1/24 88.22.44.13 #listening_ip=192.168.0.1/24 #listening_ip=192.168.1.1/24 #listening_ip= # port for HTTP (descriptions and SOAP) traffic. set 0 for autoselect. port=0 #port=5050 # path to the unix socket used to communicate with MiniSSDPd # If running, MiniSSDPd will manage M-SEARCH answering. # default is /var/run/minissdpd.sock #minissdpdsocket=/var/run/minissdpd.sock # enable NAT-PMP support (default is no) enable_natpmp=yes # enable UPNP support (default is yes) #enable_upnp=no enable_upnp=yes # chain names for netfilter (not used for pf or ipf). # default is MINIUPNPD for both #upnp_forward_chain=forwardUPnP #upnp_nat_chain=UPnP # lease file location #lease_file=/var/log/upnp.leases # bitrates reported by daemon in bits per second #bitrate_up=1000000 #bitrate_down=10000000 # "secure" mode : when enabled, UPnP client are allowed to add mappings only # to their IP. secure_mode=yes #secure_mode=no # default presentation url is http address on port 80 # If set to an empty string, no presentationURL element will appear # in the XML description of the device, which prevents MS Windows # from displaying an icon in the "Network Connections" panel. #presentation_url=http://www.mylan/index.php # report system uptime instead of daemon uptime system_uptime=yes # notify interval in seconds. default is 30 seconds. #notify_interval=240 notify_interval=60 # unused rules cleaning. # never remove any rule before this threshold for the number # of redirections is exceeded. default to 20 clean_ruleset_threshold=10 # clean process work interval in seconds. default to 0 (disabled). # a 600 seconds (10 minutes) interval makes sense clean_ruleset_interval=600 # log packets in pf #packet_log=no # ALTQ queue in pf # filter rules must be used for this to be used. # compile with PF_ENABLE_FILTER_RULES (see config.h file) #queue=queue_name1 # tag name in pf #tag=tag_name1 # make filter rules in pf quick or not. default is yes # active when compiled with PF_ENABLE_FILTER_RULES (see config.h file) #quickrules=no # uuid : generate your own with "make genuuid" #uuid=fc4ec57e-b051-11db-88f8-0060085db3f6 # serial and model number the daemon will report to clients # in its XML description #serial=12345678 #model_number=1 # UPnP permission rules # (allow|deny) (external port range) ip/mask (internal port range) # A port range is <min port>-<max port> or <port> if there is only # one port in the range. # ip/mask format must be nn.nn.nn.nn/nn # it is advised to only allow redirection of port above 1024 # and to finish the rule set with "deny 0-65535 0.0.0.0/0 0-65535" #allow 1024-65535 192.168.0.0/24 1024-65535 #allow 1024-65535 192.168.1.0/24 1024-65535 #allow 1024-65535 192.168.0.0/23 22 #allow 12345 192.168.7.113/32 54321 #deny 0-65535 0.0.0.0/0 0-65535
Finally, we need a startup script. Basically, I just modify the web script we took and changed things. I removed the download package stuff. I changed the paths to reflect the new locations. I pass a parameter that specifies the configuration file to read when miniupnpd is invoked. And I change the firewall rules so they actually work because they did not work out of the box for me.
#!/bin/sh ################| December 26 2009 |################ #################################################### # DD-WRT MiniUPnP Daemon Installation Script # #################################################### # set the script variables to be called UPNP=/jffs/usr/bin/miniupnpd WAN="$(nvram get wan_iface)" LAN="$(nvram get lan_ipaddr)" IPT=/usr/sbin/iptables FLUSH="killall TERM miniupnpd" FLUSHPNP="killall TERM upnp" CONF_FILE=/jffs/etc/miniupnpd.conf # flush the DD-WRT upnp daemon $FLUSHPNP # flush the old miniupnpd and hope he does his job re-forwarding previous ports $FLUSH #removing the MINIUPNPD chain for nat $IPT -t nat -F MINIUPNPD $IPT -t nat -D PREROUTING -i $WAN -j MINIUPNPD $IPT -t nat -X MINIUPNPD #removing the MINIUPNPD chain for filter $IPT -t filter -F MINIUPNPD $IPT -t filter -D FORWARD -i $WAN -o ! $WAN -j MINIUPNPD $IPT -t filter -X MINIUPNPD #adding the MINIUPNPD chain for nat $IPT -t nat -N MINIUPNPD #$IPT -t nat -A PREROUTING -i $WAN -j MINIUPNPD $IPT -t nat -I PREROUTING -i $WAN -j MINIUPNPD #adding the MINIUPNPD chain for filter $IPT -t filter -N MINIUPNPD #$IPT -t filter -A FORWARD -i $WAN -o ! $WAN -j MINIUPNPD $IPT -t filter -I FORWARD -i $WAN -o ! $WAN -j MINIUPNPD # run miniupnpd then sleep two seconds #cd $UPNP_DIR $UPNP -f $CONF_FILE -i $WAN -a $LAN sleep 2
Now the rules didn't work out of the box for me. In the places where the -A switch was used, I had to change it to -I. This is kind of mentioned in the forum thread I linked to earlier, though they only mentioned one of the -A switches and not both. Without changing both, running iptables -L MINIUPNPD
would report the ports were mapped, but my client software would complain the ports were still blocked.
I save this file as start_miniupnpd.wanup and make it executable.
chmod +x /jffs/etc/config/restart_avahi.wanup
Since this script contains firewall rules, I read that the script assumes these rules are invoked after all the other rules. So I put the file in a .wanup script since the .wanup script is supposed to run after the firewall goes up. Supposedly, you could move the iptables commands to the web gui firewall script instead.
We now have MiniUPNP running. UPnP and NAT-PMP should now just work. In my experience, applications that support both protocols (and have enabled both) will attempt to use NAT-PMP first and then fallback to UPnP if it is unavailable. This makes a lot of sense since NAT-PMP is the saner protocol.
Next time I will address a question that has come up on more than one occasion.
Links:
Part 6: UPnP and NAT-PMP (previous)
Part 8: How I built a cheap Apple Airport Base Station substitute for $30 (next)