NOTE: The following guide assumes you understand UNIX.

I needed to install MiniUPNP to get NAT-PMP on DD-WRT. I did lots of research and finally found the right way to do it.

First search Google for a compatible version of OpenWRT for your router, mine being http://wiki.openwrt.org/toh/buffalo/wzr-600dhp, then look at the firmware download links for the location of the firmware, in my case http://downloads.openwrt.org/attitude_adjustment/12.09/ar71xx/generic/, then go into packages and  search for miniupnpd. SSH or telnet into the router and run “wget http://downloads.openwrt.org/attitude_adjustment/12.09/ar71xx/generic/packages/miniupnpd_1.8-1_ar71xx.ipk -O /tmp/miniupnpd.ipk” (replace URL with correct one for your router), then run “ipkg install /tmp/miniupnpd.ipk” to install. Once you have it installed, test to verify it runs by typing miniupnpd. If it gives an error saying a library is needed, look for that library in the packages folder and possibly install the same way you installed miniupnpd.

Once miniupnpd runs properly, remove the file /jffs/etc/config/upnpd and  vi /jffs/etc/miniupnp.conf to paste the following config, modifying for your network (I use 10.0.0.1 for my router, most dd-wrt routers are configured for 192.168.1.1).

# network interface
ext_ifname=eth1
#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
# It can also be the network interface name (ie “eth0”)
# It if mandatory to use the network interface name to enable IPv6
# 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=10.0.0.1/24 #listening_ip=eth0
# port for HTTP (descriptions and SOAP) traffic. set 0 for autoselect.
port=0

# 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=yes

# configure minimal and maximal lifetime of the port mapping in seconds
# 120s and 86400s (24h) are suggested values from PCP-base
#min_lifetime=120
#max_lifetime=86400

# 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=/tmp/upnp.leases

# name of this service, default is “`uname -s` Router”
friendly_name=DD-WRT

# 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 (default is no)
#packet_log=no

# anchor name in pf (default is miniupnpd)
anchor=miniupnpd

# 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 http://www.famkruithof.net/uuid/uuidgen uuid=a68ce000-5cf5-11e3-949a-0800200c9a66

# 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 10.0.0.0/24 1024-65535
deny 0-65535 0.0.0.0/0 0-65535

After you write and close vi, vi /jffs/etc/config/miniupnp.startup to add the following which will make it start up at boot.

#!/bin/sh

#Wait for firewall and other services to startup.
sleep 30

#Configure firewall rules for MiniUPnP
/usr/sbin/iptables -t filter -N MINIUPNPD
/usr/sbin/iptables -t filter -I FORWARD 4 -j MINIUPNPD
/usr/sbin/iptables -t nat -N MINIUPNPD
/usr/sbin/iptables -t nat -I PREROUTING 1 -j MINIUPNPD

#Start MiniUPnP
/jffs/usr/sbin/miniupnpd -f /jffs/etc/miniupnp.conf -d

and then run “chmod +x /jffs/etc/config/miniupnp.startup” to make it executable.

To enable jffs, look at http://www.dd-wrt.com/wiki/index.php/JFFS

Be sure to disable old UPnP server on DD-WRT.

You can of course run it without rebooting to test by running the command noted above.

I used http://www.codingmonkeys.de/portmap/ to test the server.