February 14, 2010

HOWTO: Port Forwarding with OpenWRT Kamikaze

Something I've been working on recently is beefing up my home network. I own two domains, btr3.com and one for my wife's business, and I wanted to host them from my own server. Recently, I had to change ISPs, and my new ISP's modem doesn't have the "IP Passthrough" feature to make my web server visible to the outside world. My solution was to load the OpenWRT firmware onto my router. OpenWRT allows me to do a lot more than the vendor firmware. Here's how I solved my problem.


1) For starters, I moved OpenWRT's web interface to another port. It originally sits on port 80, so it catches all of the requests to port 80. You may also find it convenient to move OpenWRT's SSH access to a port other than 22, so that you can enable SSH access to a server on the network. You can change these settings through the admin web interface.

The rest of this builds on the following blog post, which I found after a few hours of Googling. The post has a couple of typos and outdated URLs in the provided code, and I'll try to fix those here. Also, the original poster no longer uses OpenWRT, so if there's any tweaking or testing, I'm able to try things out.

2) You want to configure your server to have a static IP, which you can do through OpenWRT's web interface. For example, you can have your server at 192.168.1.100, so that your redirect can send requests directly to the server. For the rest of this HOWTO, I'll assume that your router is at 192.168.1.1 and your server at 192.168.1.100.

3) Next, you want to configure your firewall to allow port 80 and 22 requests and redirect them to your server IP. You can find OpenWRT's firewall configuration at /etc/config/firewall (through SSH access). Open the file with your favorite text editor, and add the following lines in order to open the ports (via a "rule") and redirect the traffic (via a "redirect"):

config 'redirect' 'http'
option 'src' 'wan'
option 'proto' 'tcp'
option 'src_ip' ''
option 'src_dport' '80'
option 'dest_ip' '192.168.1.100' # your server IP
option 'dest_port' '80'

config 'rule'
option 'src' 'wan'
option 'proto' 'tcp'
option 'src_ip' ''
option 'dest_ip' ''
option 'dest_port' '80'
option 'target' 'ACCEPT'

config 'redirect' 'ssh'
option 'src' 'wan'
option 'proto' 'tcp'
option 'src_ip' ''
option 'src_dport' '22'
option 'dest_ip' '192.168.1.100' # your server IP
option 'dest_port' '22'

config 'rule'
option 'src' 'wan'
option 'proto' 'tcp'
option 'src_ip' ''
option 'dest_ip' ''
option 'dest_port' '22'
option 'target' 'ACCEPT'

Somewhat surprisingly, this doesn't fix our problem. I'm not entirely clear on the reason, but basically, we need the equivalent of lan-to-lan port forwarding (according to the original blog post) and this isn't natively provided by OpenWRT. We need to redirect the on-lan traffic explicitly, and to do that, we can use xinetd, a secure web server.

4) Install xinetd on your router using opkg, which should be installed on the router:
opkg install http://ipkg.nslu2-linux.org/feeds/optware/openwrt-brcm24/cross/unstable/xinetd_2.3.14-9_mipsel.ipk

5) xinetd depends on a couple of configuration files. One file common to many *nix systems (but not OpenWRT) is /etc/services. Create an /etc/services file, and add listings for http and ssh services as follows:
http 80/tcp http # HTTP service
ssh 22/tcp ssh # SSH service

6) There should be a folder created by the xinetd install at /opt/etc/xinetd.d. We want to add a couple of files here to configure the internal forwarding for our services. I chose to add separate files, http-forward and ssh-forward, but any files in this directory are loaded when xinetd is started, so you can name them whatever you want.

http-forward:
service http
{
flags = REUSE
socket_type = stream
wait = no
user = root
redirect = 192.168.1.100 80
log_on_failure += USERID
}

ssh-forward:
service ssh
{
flags = REUSE
socket_type = stream
wait = no
user = root
redirect = 192.168.1.100 22
log_on_failure += USERID
}

7) Create a startup script for xinetd by creating a file /etc/init.d/xinetd and placing the following:
#!/bin/sh /etc/rc.common
# Copyright (C) 2006 OpenWrt.org

START=39
start() {
[ -x /opt/sbin/xinetd ] && {
/opt/sbin/xinetd
}
}

(*Update on 3/2, thanks to comment from Dubravko) You can change the permissions of this file to 755 with:
chmod 755 /etc/init.d/xinetd
Then you can use this script to enable the newly defined service with:
/etc/init.d/xinetd enable 
and to start the service with:
/etc/init.d/xinetd start 
8) I usually reboot the router at this point, to ensure that the firewall rules and xinetd configuration files are all freshly loaded. After reboot, you'll want to start xinetd (currently, I do this manually, although I know it's possible to have the service started every time the router reboots - I just haven't taken the time to do that). You should now be able to access your web server correctly.

Debugging tools: The following tools can be helpful in debugging your setup:
  • DynDNS's Open Port tool
  • The logread command in the OpenWRT SSH - shows when xinetd starts, how many services started, and when each request is received/processed, etc.

If anyone wants to update on how to setup xinetd or a similar service to automatically start on router reboot, OR the precise need for "internal LAN redirect" please let me know so I can update the post. I've also hacked out a little script for automating some of this, and I'll post that once I clean it up.

4 comments:

  1. Isn't doing all this and spending hours on google trying to figure something out fun! People ask me all the time how I can dedicate so much time doing stuff like this and it's because it's a challenge. Once I get something in my head that I want to try something, It's hard for me to give up.

    Keep up the good work!

    ReplyDelete
  2. Add chmod 755 for /etc/init.d/xinetd

    Good work

    ReplyDelete
  3. hmm, I'm a noob regarding iptables, but the following in firewall.users is working, too; without the need to install xinetd:

    MYSERVER="your.ip"

    iptables -F forwarding_wan
    iptables -t nat -F prerouting_wan

    iptables -t nat -A prerouting_wan -p tcp --dport 80 -j DNAT --to $MYSERVER:80
    iptables -A forwarding_wan -p tcp --dport 80 -d $MYSERVER -j ACCEPT

    ReplyDelete
  4. I have read your blog its very attractive and impressive. I like it your blog.

    Java Training in Chennai Core Java Training in Chennai Core Java Training in Chennai

    Java Online Training Java Online Training JavaEE Training in Chennai Java EE Training in Chennai

    ReplyDelete