Hello! This is a custom NAT-PMP daemon designed for specific case when one client IP subnet is divided into several ranges, each is mapped to separate external IP address (this is useful when you have several white addresses and users are banned on sites for too many connections from one IP). UPnP doesn't play well in this situation because it uses multicast which affects entire subnet, not only range. NAT-PMP was not designed for this also, but it at least allows such setup. I decided to write this after talking with author of miniupnpd, because UPnP is main application, and it doesn't support this setup. However, this daemon also uses another scheme to talk to OS/firewall for actual redirects, a PFCFBP protocol developed by me (and described in proto.txt), which allows to change OS/firewall without recompiling daemon. This avtnatpmpd daemon is a proof of concept, supplied with an example (but working) backend utilizing FreeBSD's ng_nat kernel NAT engine. Currently miniupnpd doesn't support ng_nat, but I plan to help miniupnpd's author to integrate this particular piece of avtnatpmpd's code, so miniupnpd will support PFCFBP (and therefor ng_nat) in the future. See http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=436 for more info. The avtnatpmpd was written and tested on FreeBSD 6.3 with ng_nat, but due to frontend-backend architecture it is possible for you to port it to another platfrom, just write a backend for it. So, here is my setup for this on FreeBSD. First, setup ng_nat using my rcNG script for ng_nat, I keep it in the /usr/local/etc/rc.d/ng_nat.sh, and config your nodes in /etc/rc.conf.d/ng_nat - here is part of my setup: $ cat /etc/rc.conf.d/ng_nat # This is a config for ng_nat script, with nodes params and ipfw rules # it is included together with rc.conf by rc.d/ng_nat script # vim: syntax=sh # Let's do some scripting work first to make actual descriptions # below more customizable... # plug in settings from main firewall script eval "`awk '/^##SOIPFWVARS##$/,/^##EOIPFWVARS##$/' /etc/ipfw.rules`" # list of external addresses of our nodes in white network ext_nat_ips="20 24 48" _i=0 for _ip in $ext_nat_ips; do i=$(($i+1)) eval avt_nat_ext_ip$i=$avtf.$_ip done # Generate a bunch of redirect_port for a set of addresses on a given node # where port maps addr-based within /24 subnet (protocol also passed), # e.g. for base port 17000 and x.y.z.123 it will be 17123 -> x.y.z.123:17123 portredir_block() { local name subnet start addrcount destport _addr _port i name=$1 subnet=$2 start=$3 addrcount=$4 destport=$5 i=0 while [ "$i" -lt $addrcount ]; do _addr=$((${start} + ${i})) _port=$((${destport} + ${_addr})) echo ng_nat_${name}_redirect_port$((i * 2))=\"tcp ${subnet}.${_addr}:$_port ${_port}\" echo ng_nat_${name}_redirect_port$((i*2+1))=\"udp ${subnet}.${_addr}:$_port ${_port}\" i=$((${i} + 1)) done } # OK, yes, I'm too lazy to generate node setups from one template, but some # of them are slightly different, and listing each individually is more # readable, after all. So here they are... # list of or our nodes first ng_nat_nodes="natmsf natavt1 natavt2 natavt3" # MSF NAT has IP block from 1 to 143 ng_nat_natmsf_interface="${avtf}.1" ng_nat_natmsf_cookies="61 60" ng_nat_natmsf_ipfw_rules="171 181" ng_nat_natmsf_ipfw_rule0="171 netgraph 60 src-ip ${msf}.0/25" ng_nat_natmsf_ipfw_rule1="181 netgraph 61 ip from any to ${avtf}.1 in recv $extiface" # Cashine inet with block 240-254, external host avt-nat1 ng_nat_natavt1_interface="$avt_nat_ext_ip1" ng_nat_natavt1_cookies="82 72" ng_nat_natavt1_ipfw_rules="172 182" ng_nat_natavt1_ipfw_rule0="172 netgraph 72 { src-ip ${msf}.240/28 or src-ip 10.117.64.2 }" ng_nat_natavt1_ipfw_rule1="182 netgraph 82 ip from any to $avt_nat_ext_ip1 in recv $extiface" eval "`portredir_block natavt1 ${msf} 240 15 17000`" # avt-nat2, block 224-239 ng_nat_natavt2_interface="$avt_nat_ext_ip2" ng_nat_natavt2_cookies="83 73" ng_nat_natavt2_ipfw_rules="173 183" ng_nat_natavt2_ipfw_rule0="173 netgraph 73 src-ip ${msf}.224/28" ng_nat_natavt2_ipfw_rule1="183 netgraph 83 ip from any to $avt_nat_ext_ip2 in recv $extiface" eval "`portredir_block natavt2 ${msf} 224 16 17000`" # avt-nat3, block 208-223 ng_nat_natavt3_interface="$avt_nat_ext_ip3" ng_nat_natavt3_cookies="84 74" ng_nat_natavt3_ipfw_rules="174 184" ng_nat_natavt3_ipfw_rule0="174 netgraph 74 src-ip ${msf}.208/28" ng_nat_natavt3_ipfw_rule1="184 netgraph 84 ip from any to $avt_nat_ext_ip3 in recv $extiface" eval "`portredir_block natavt3 ${msf} 208 16 17000`" $ As you can see, I define several nodes with similar setup, and give each user a pair of static redirects, one for TCP and one for UDP, 32 total for 16 users. Then I put rcNG script avtnatpmp.sh as /usr/local/etc/rc.d/avtnatpmp (with chmod +x on it), put backend script pfcfbp_ng_nat.sh, which hard-codedly reads config from /etc/rc.conf.d/ng_nat, to /usr/local/adm/bin/pfcfbp_ng_nat.sh, and then add proper lines to /etc/rc.conf for daemon and to /etc/inetd.conf for backend to listen on the UNIX domain socket: $ head /etc/inetd.conf # $FreeBSD: src/etc/inetd.conf,v 1.70.2.2 2006/09/07 20:03:25 obrien Exp $ # # Internet server configuration database # # Define *both* IPv4 and IPv6 entries for dual-stack support. # To disable a service, comment it out by prefixing the line with '#'. # To enable a service, remove the '#' at the beginning of the line. :vadim:daemon:660:/var/run/pfcfbp.sock stream unix nowait root /bin/sh sh /usr/local/adm/bin/pfcfbp_ng_nat.sh $ head /etc/rc.conf ng_nat_enable="YES" # SEE /etc/rc.conf.d/ng_nat FOR ng_nat DEFINITIONS !!! avtnatpmpd_enable="YES" avtnatpmpd_user="daemon" avtnatpmpd_flags="82.117.64.20,172.18.46.240/28 82.117.64.24,172.18.46.224/28 82.117.64.48,172.18.46.208/28" $ And after this setup all of that crap works, you can then after some time type command to ng_nat script as root and see reirects created both statically and by daemon: # /usr/local/etc/rc.d/ng_nat list_redirects natavt2 List of static redirects for node natavt2 (38 total): ID PROTO LOCAL ADDR:PORT ALIAS ADDR:PORT REMOTE ADDR:PORT LSNAT DESCRIPTION 1 tcp 172.18.46.224:17224 *:17224 *:* 0 2 udp 172.18.46.224:17224 *:17224 *:* 0 ...28 more redirects skipped by me... 31 tcp 172.18.46.239:17239 *:17239 *:* 0 32 udp 172.18.46.239:17239 *:17239 *:* 0 97 udp 172.18.46.233:40040 82.117.64.24:40040 *:* 0 NAT-PMP 1226254561 98 tcp 172.18.46.233:40040 82.117.64.24:40040 *:* 0 NAT-PMP 1226254562 99 tcp 172.18.46.225:37570 82.117.64.24:37570 *:* 0 NAT-PMP 1226256388 100 udp 172.18.46.225:37570 82.117.64.24:37570 *:* 0 NAT-PMP 1226256388 101 tcp 172.18.46.239:41421 82.117.64.24:41421 *:* 0 NAT-PMP 1226256710 102 udp 172.18.46.239:41421 82.117.64.24:41421 *:* 0 NAT-PMP 1226256711 Enjoy! ;-) -- WBR, Vadim Goncharov, vadimnuclight tpu.ru