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.