OpenWRT

From Ggl's wiki

Jump to: navigation, search

Contents

Why using OpenWRT?

Because it's free (as in free speech), fun and open. I can implement quite everything I want with it. I have two Linksys WRT54GL routers. I have also a Fonera. I don't want to mess my home network with the WAN port of the Fonera because I don't entirely trust Fon (who does ??). Consequently with OpenWRT, I can break the default bridge that is configured on the ethernet swith and separate the ports in VLANs. The Fonera will be in a kind of own DMZ.

When I use a hotspot I want to be able to connect through a secure connection. I can install OpenVPN or another VPN server on my wrt and connect to it remotely. For mobile device, when I can't install VPN client I an provide a HTTPS proxy to access to sites that don't provide HTTPS access (yes there are some webmails and other services...).

OpenWRT Configuration with Kamikaze

Short Introductinon

Main WhiteRussian/Kamikaze differences

OpenWRT Configuration with WhiteRussian

WARNING! At the time I got my first WRT54GL, OpenWRT provided WhiteRussian as the stable release. The current release is a Kamikaze one, based on buildroot-ng. /etc/ is now writable and the configuration is not done anymore with nvram. I'll upgrade my routers very soon, so I'll write an up-to-date part of the OpenWRT configuration ;).

Introduction

This article doesn't aim to copy the very helpful documentation on OpenWRT Wiki but to share the configuration of my wrt.

I bought a Linksys WRT54GL which is a WRT54Gv4 with a linux based OS (v5 is VxWorks based). As I am a opensource enthousiast who believe in knowledge sharing and openness I decided to install openwrt on it. As the time I wrote this article the current release was White Russian RC5.

Installing OpenWRT firmware

So I take a SquashFS .bin file because I use the Linksys firmware upgrade procedure in the web interface. After the end of the upgrade, I have an OpenWRT router !

I plug a crossover (because it's a switch to switch link) rj45 on a lan port of the wrt and on my home switch. I telnet the default management IP :

$ telnet 192.168.1.1

Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.
 === IMPORTANT ============================
  Use 'passwd' to set your login password
  this will disable telnet and enable SSH
 ------------------------------------------


BusyBox v1.00 (2006.03.27-00:00+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 WHITE RUSSIAN (RC5) -------------------------------
  * 2 oz Vodka   Mix the Vodka and Kahlua together
  * 1 oz Kahlua  over ice, then float the cream or
  * 1/2oz cream  milk on the top.
 ---------------------------------------------------
root@OpenWrt:/#

Change the root password to activate ssh access :

root@OpenWrt:/# passwd
Changing password for root
Enter the new password (minimum of 5 characters)
Please use a combination of upper and lower case letters and numbers.
Enter new password:
Re-enter new password:
Password changed. 
root@OpenWrt:/#

Like most of standard linux distro, configuration files are in /etc . But with the SquashFS image :

banner -> /rom/etc/banner
dnsmasq.conf -> /rom/etc/dnsmasq.conf
firewall.user -> /rom/etc/firewall.user
unctions.sh -> /rom/etc/functions.sh
group -> /rom/etc/group
hosts -> /rom/etc/hosts
inittab -> /rom/etc/inittab
ipkg.conf -> /rom/etc/ipkg.conf
modules -> /rom/etc/modules
preinit -> /rom/etc/preinit
profile -> /rom/etc/profile
protocols -> /rom/etc/protocols
resolv.conf -> /tmp/resolv.conf
shells -> /rom/etc/shells
sysctl.conf -> /rom/etc/sysctl.conf

Important files are symlinks to the /rom/ directory which is read-only as shows the mount command (it is also fully documented in the OpenWRT Wiki):

root@OpenWrt:/# mount
/dev/root on /rom type squashfs (ro)
none on /dev type devfs (rw)
none on /rom/mnt type tmpfs (ro)
none on /rom/mnt/proc type proc (rw)
none on /tmp type tmpfs (rw,nosuid,nodev)
none on /dev/pts type devpts (rw)
/dev/mtdblock/4 on / type jffs2 (rw)
none on /proc type proc (rw)
root@OpenWrt:/# 

When you need to edit a file, just remove it and copy the corresponding symlink instead.

/# cd /etc
/etc# rm resolv.conf
/etc# cp /rom/resolv.conf .

Network configuration

I don't want to have the wireless and the lan interfaces bridged. So I need to unset br0 interface. The OpenWRT wifi explains how the interfaces are set on a WRT54Gv4.

Thus :

  • eth1 is the 802.11 interface
  • vlan0 is the lan
  • vlan1 is the wan

I wanted to isolate my FON routeur from the LAN. For this purpose I create a vlan2 interface :

  • vlan2 is the fon

VLANs

The default configuration :

root@OpenWrt:~# nvram show | grep vlan
size: 1624 bytes (31144 left)
wan_device=vlan1
vlan0ports=3 2 1 0 5*
lan_ifnames=vlan0 eth1 eth2
vlan1hwname=et0
vlan1ports=4 5
lan_ifname=vlan0
vlan0hwname=et0

The changes I made to have a dmz for fon :

root@OpenWrt:~# nvram set vlan0ports="2 1 0 5*"
root@OpenWrt:~# nvram set vlan2ports="3 5"
root@OpenWrt:~# nvram set vlan2hwname=et0

LAN Interface

By default eth1 (802.11 interface) and vlan0 are bridge in br0. I don't want to keep this bridge, thus i configure the vlan0 interface and removoe br0.

root@OpenWrt:~# nvram set lan_ifname=vlan0
root@OpenWrt:~# nvram set lan_ipaddr=192.168.1.1
root@OpenWrt:~# nvram set lan_netmask=255.255.255.0
root@OpenWrt:~# nvram set lan_proto=static
root@OpenWrt:~# ifup lan

WAN Interface

If you use pppoe :

root@OpenWrt:~# nvram set wan_ifname=ppp0
root@OpenWrt:~# nvram set wan_proto=pppoe
root@OpenWrt:~# nvram set ppp_idletime=10
root@OpenWrt:~# nvram set ppp_mtu=1492
root@OpenWrt:~# nvram set ppp_redialperiod=15
root@OpenWrt:~# nvram set ppp_username=<your_isp_account_login>
root@OpenWrt:~# nvram set ppp_passwd=<your_isp_account_password>
root@OpenWrt:~# nvram pppoe_ifname=vlan1

Don't forget to commit the changes in nvram :

root@OpenWrt:~# nvram commit
root@OpenWrt:~# ifdown wan
root@OpenWrt:~# ifup wan

FON Interface

Configure IP settings:

root@OpenWrt:~# nvram set fon_ifname=vlan2
root@OpenWrt:~# nvram set fon_proto=static
root@OpenWrt:~# nvram set fon_ipaddr=192.168.3.1
root@OpenWrt:~# nvram set fon_netmask=255.255.255.0

Edit the /etc//init.d/S40network to enable the fon interface a startup:

root@OpenWrt:~# rm /etc/init.d/S40network
root@OpenWrt:~# cp /rom/etc/init.d/S40network /etc/init.d/
root@OpenWrt:~# vim /etc/init.d/S40network
root@OpenWrt:~# ifup fon
#!/bin/sh
case "$1" in
  start|restart)
    ifup lan
    ifup fon
    ifup wan
    ifup wifi
    wifi up

    for route in $(nvram get static_route); do {
      eval "set $(echo $route | sed 's/:/ /g')"
      $DEBUG route add -net $1 netmask $2 gw $3 metric $4 dev $5
    } done
    ;;
esac

Now the vlan2 interface is created and up:

root@OpenWrt:~# ifconfig vlan2
vlan2     Link encap:Ethernet  HWaddr 00:16:B6:D9:9E:56
          inet addr:192.168.3.1  Bcast:192.168.3.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

Management Services

Removing useless services

What services are started by default?

root@OpenWrt:/# netstat -lut Active Internet connections (only servers)

Proto Recv-Q Send-Q Local Address     Foreign Address         State
tcp        0      0 *:80              *:*                     LISTEN
tcp        0      0 *:53              *:*                     LISTEN
tcp        0      0 *:22              *:*                     LISTEN
tcp        0      0 *:23              *:*                     LISTEN
netstat: no support for `AF INET6 (tcp)' on this system.
udp        0      0 *:53              *:* 
udp        0      0 *:67              *:*
netstat: no support for `AF INET6 (udp)' on this system.

hum, don't need http and telnet admin, neither dhcpd. Stop these services:

root@OpenWrt:/# killall httpd telnetd dnsmasq udhcpc

note: if udhcpc doesn'5 stop use killall -9 udhcpc

Ok, so let's check:

root@OpenWrt:/etc/init.d# netstat -lut
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 *:22                    *:*                     LISTEN
netstat: no support for `AF INET6 (tcp)' on this system.
netstat: no support for `AF INET6 (udp)' on this system. 

Well, that's fine only ssh server started.

I need to remove other services from init config files.

Disable dhcp server at startup. There are only dhcp related options in dnsmasq.conf, so just remove it (if you need it later the file is in /rom/etc/) :

root@OpenWrt:/etc# rm dnsmasq.conf

Start dnsmasq:

root@OpenWrt:~# /etc/init.d/S50dnsmasq start

Remove httpd and telnetd from init :

root@OpenWrt:/etc/init.d# rm S50httpd
root@OpenWrt:/etc/init.d# rm S50telnet 

I remove useless packages:

root@OpenWrt:/etc/init.d# ipkg remove webif haserl

Now only ssh and dns services are listening:

root@OpenWrt:~# netstat -lut
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 *:53                    *:*                     LISTEN
tcp        0      0 *:22                    *:*                     LISTEN
netstat: no support for `AF INET6 (tcp)' on this system.
udp        0      0 *:53                    *:*
netstat: no support for `AF INET6 (udp)' on this system. 

But they are binded on all ('*') IP addresses. No problem for dns, this could be the wanted behaviour. For ssh I want it to listen only on the lan interface IP. With OpenSSH I would add ListenAddress directive into /etc/ssh/sshd_config file, but actually the default ssh server is dropbear.

MaraDNS

I replace dnsmasq by a true dns server: maradns. So let's remove dnsmasq and install maradns:

root@OpenWrt:~# ipkg remove dnsmasq
Removing package dnsmasq from root...
Successfully terminated.
root@OpenWrt:~# ipkg install maradns
Installing maradns (1.0.26-1) to root...
Downloading http://downloads.openwrt.org/whiterussian/packages/maradns_1.0.26-1_mipsel.ipk
Installing libpthread (0.9.27-1) to root...
Downloading http://downloads.openwrt.org/whiterussian/packages/libpthread_0.9.27-1_mipsel.ipk
Configuring libpthread
Configuring maradns
Successfully terminated.

The default configuration looks like this:

root@OpenWrt:~# cat /etc/mararc
hide_disclaimer="YES"
chroot_dir="/etc/maradns"
bind_address="192.168.1.1"
maradns_uid=65534
maxprocs=10
random_seed_file="/dev/urandom"
recursive_acl="192.168.1.0/24"
root_servers={}
root_servers["."]="198.41.0.4,128.9.0.107,192.33.4.12,128.8.10.90,192.203.230.10,192.5.5.241,192.112.36.4,128.63.2.53,192.36.148.17,192.58.128.30,193.0.14.129,198.32.64.12,202.12.27.33"

I only add the line:

no_fingerprint=1

That's ok, start maradns:

root@OpenWrt:/etc# /etc/init.d/S60maradns 
root@OpenWrt:/etc# netstat -lu
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
udp        0      0 192.168.1.1:53          *:*

Well, maradns is listening on port 53/udp. Let's test dns resolving:

$ host -t A -v www.openwrt.org 192.168.1.1
Trying "www.openwrt.org"
Using domain server:
Name: 192.168.1.1
Address: 192.168.1.1#53
Aliases: 

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25497
;; flags: qr; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.openwrt.org.               IN      A

;; ANSWER SECTION:
www.openwrt.org.        604800  IN      A       195.56.146.238

Received 49 bytes from 192.168.1.1#53 in 324 ms

note: 324 ms seems long (for example the same resolving takes about 40 ms on my local dns server) but the router is not yet directly connected to the Internet. I'll re-test later to see how much time it takes in better conditions.

It works. The recursive request was achieved successfully. Does the cache work ?

$ host -t A -v www.openwrt.org 192.168.1.1
Trying "www.openwrt.org"
Using domain server:
Name: 192.168.1.1
Address: 192.168.1.1#53
Aliases: 

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63309
;; flags: qr; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.openwrt.org.               IN      A

;; ANSWER SECTION:
www.openwrt.org.        604800  IN      A       195.56.146.238

Received 49 bytes from 192.168.1.1#53 in 2 ms

maradns used its cached entry for the host which was resolved in 2 ms.

I re-wrote the init script that starts maradns as following:

#!/bin/sh

RUN_D=/var/run
PID_F=$RUN_D/maradns.pid
                                        
case $1 in                                          
 start)                                             
       [ -d $RUN_D ] || mkdir -p $RUN_D            
       [ -d /etc/maradns ] || mkdir -p /etc/maradns
       /usr/sbin/maradns >/dev/null 2>&1 &
       pidof maradns > $PID_F                          
       ;;                                              
 stop)                                                  
       [ -f $PID_F ] && kill $(cat $PID_F) && rm $PID_F
       ;;                                              
 *)                                  
       echo "Usage: $0 (start|stop)"
       exit 1                       
esac          
       
exit $?

Using xinetd

xinetd installation

Install xinetd:

root@OpenWrt:/etc/init.d# ipkg install xinetd
Installing xinetd (2.3.13-2) to root...
Downloading http://downloads.openwrt.org/whiterussian/packages/xinetd_2.3.13-2_mipsel.ipk
Configuring xinetd
Successfully terminated.

By default the package installs an xinetd script in /etc/init.d . Rename it to /etc/init.d/S50xinetd and edit it:

#!/bin/sh

DEFAULT=/etc/default/xinetd

LOG_D=/var/log
LOG_F=$LOG_D/xinetd.log

RUN_D=/var/run
PID_F=$RUN_D/xinetd.pid

[ -f $DEFAULT ] && . $DEFAULT

case $1 in
 start)
  [ -d $RUN_D ] || mkdir -p $RUN_D
  [ -d $LOG_D ] || mkdir -p $LOG_D
  xinetd $OPTIONS
  pidof xinetd > $PID_F
  ;;
 stop)
  [ -f $PID_F ] && kill $(cat $PID_F) && rm $PID_F
  ;;
 *)
  echo "usage: $0 (start|stop)"
  exit 1
esac

exit $?

Acutally I just add theses lines, define the path where xinetd.log file is:

 LOG_D=/var/log
 LOG_F=$LOG_D/xinetd.log

To be sure to have created the file:

 [ -d $LOG_D ] || mkdir -p $LOG_D

Create pid file:

 pidof xinetd > $PID_F

Add this line to /etc/default/xinetd (create the file if it's not present):

OPTIONS="-filelog /var/log/xinetd.log"
Dropbear with xinetd

So now I gonna create the file for dropbear. I create and edit /etc/xinetd.d/ssh:

service ssh
{
       type            = UNLISTED
       socket_type     = stream
       bind            = 192.168.1.1
       port            = 2222
       only_from       = <allowed_ips>
       user            = root 
       wait            = no
       instances       = 5
       per_source      = 4
       protocol        = tcp 
       server          =/usr/sbin/dropbear
       server_args     = -i
       disable         = no
       log_type        = FILE /var/log/xinetd.log
       log_on_success  = PID USERID HOST DURATION
       log_on_failure  = HOST
}

I choose to be restrictive to prevent configuration error, for example in my iptables rules. ssh access is on of the most exposed services. To continue, I create user keys to enable key authentication.

Maradns with xinetd

I'd like to try maradns with xinetd. I wrote the following /etc/xinetd.d/dns config file:

service dns
{
       type            = UNLISTED
       id              = dns
       socket_type     = dgram
       bind            = 192.168.1.1
       port            = 53 
       user            = 65534
       wait            = no
       instances       = 20
       per_source      = 10
       protocol        = udp 
       server          =/usr/sbin/maradns
       disable         = no
       log_type        = FILE /var/log/xinetd.log
       log_on_success  = PID USERID HOST DURATION
       log_on_failure  = HOST 
}

Unfortunately, it doesn't work :( :

root@OpenWrt:~# cat /var/log/xinetd.log
00/1/2@06:14:56: START: dns pid=26073 from=192.168.1.10
00/1/2@06:14:56 xinetd[25867]: ERROR: file descriptor of service dns has been closed
00/1/2@06:14:56 xinetd[25867]: NOTICE: select reported EBADF but no bad file descriptors were found
00/1/2@06:14:57: EXIT: dns pid=26073 duration=1(sec)

After reading the documentation on Maradns official website, it appears that I should use version 1.2. What is my version ?

root@OpenWrt:~# maradns --version
This is MaraDNS version 1.0.26
Compiled on a Linux system at Sun Mar 26 19:50:57 CEST 2006
For usage information, 'man maradns'

hmmmm, 1.0.26 ...

Probably the problem can be solved in version 1.0 but since this version is no longer supported as maradns main developer said: "Note: If you are using MaraDNS 1.0, and have a question about how to configure MaraDNS, please upgrade to MaraDNS 1.2.". I decided to take the opportunity to build a maradns v1.2.

Before I checked on ipkg.be to be sure that is no already available (MaraDNS) 1.2 package.

Building Maradns 1.2 package

Documentation on how to build package for OpenWRT is available on the wiki section OpenWrt building packages howto.

802.11 Configuration

I need to connect devices like PDA (windows mobile 2005), laptop (mainly linux ones, but from time to time Windows XP) and maybe ubiquitous devices (wireless video player, etc ...).

The main goal is security.

I believe the best choice is to follow 802.11i standard :

  • 802.11x with EAP-TLS
  • AES-CCMP encryption

This is also called WPA2 Entreprise.

To implement it I need :

  • A radius server (freeradius will be fine)
  • A basic PKI to issue AP and clients certs (openssl's CA scripts are ok)
  • Supplicant on each client device
root@OpenWrt:~# nvram set wl0_mode=ap
root@OpenWrt:~# nvram set wl0_ssid=SSID
root@OpenWrt:~# nvram set wl0_infra=1
root@OpenWrt:~# nvram set wl0_closed=1
root@OpenWrt:~# nvram set wl0_channel=13
root@OpenWrt:~# nvram set wl0_macmode=allow
root@OpenWrt:~# nvram set wl0_maclist="MAC1 ... MACn"
root@OpenWrt:~# nvram set wl0_akm=psk
root@OpenWrt:~# nvram set wl0_crypto=aes+tkip
root@OpenWrt:~# nvram commit

Firewall configuration

Default configuration

Network and management services are done. Now I need to check the firewall rules.

First, let's check the /proc/sys/net options values:

root@OpenWrt:~# cat /etc/sysctl.conf 
kernel.panic=3
net.ipv4.conf.default.arp_ignore=1
net.ipv4.conf.all.arp_ignore=1
net.ipv4.ip_forward=1
net.ipv4.icmp_echo_ignore_broadcasts=1
net.ipv4.icmp_ignore_bogus_error_responses=1
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_keepalive_time=120
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_timestamps=0

hum, don't see other option like rp_filter=1 etc ... Let's check:

root@OpenWrt:~# for f in /proc/sys/net/ipv4/conf/all/*; do echo "$f = `cat $f`"; done                
/proc/sys/net/ipv4/conf/all/accept_redirects = 0
/proc/sys/net/ipv4/conf/all/accept_source_route = 0
/proc/sys/net/ipv4/conf/all/arp_announce = 0
/proc/sys/net/ipv4/conf/all/arp_filter = 0
/proc/sys/net/ipv4/conf/all/arp_ignore = 1
/proc/sys/net/ipv4/conf/all/bootp_relay = 0
/proc/sys/net/ipv4/conf/all/force_igmp_version = 0
/proc/sys/net/ipv4/conf/all/forwarding = 1
/proc/sys/net/ipv4/conf/all/log_martians = 0
/proc/sys/net/ipv4/conf/all/mc_forwarding = 0
/proc/sys/net/ipv4/conf/all/medium_id = 0
/proc/sys/net/ipv4/conf/all/proxy_arp = 0
/proc/sys/net/ipv4/conf/all/rp_filter = 0
/proc/sys/net/ipv4/conf/all/secure_redirects = 1
/proc/sys/net/ipv4/conf/all/send_redirects = 1
/proc/sys/net/ipv4/conf/all/shared_media = 1
/proc/sys/net/ipv4/conf/all/tag = 0

vlan0:

root@OpenWrt:~# for f in /proc/sys/net/ipv4/conf/vlan0/*; do echo "$f = `cat $f`"; done  
/proc/sys/net/ipv4/conf/vlan0/accept_redirects = 1
/proc/sys/net/ipv4/conf/vlan0/accept_source_route = 1
/proc/sys/net/ipv4/conf/vlan0/arp_announce = 0
/proc/sys/net/ipv4/conf/vlan0/arp_filter = 0
/proc/sys/net/ipv4/conf/vlan0/arp_ignore = 0
/proc/sys/net/ipv4/conf/vlan0/bootp_relay = 0
/proc/sys/net/ipv4/conf/vlan0/force_igmp_version = 0
/proc/sys/net/ipv4/conf/vlan0/forwarding = 1
/proc/sys/net/ipv4/conf/vlan0/log_martians = 0
/proc/sys/net/ipv4/conf/vlan0/mc_forwarding = 0
/proc/sys/net/ipv4/conf/vlan0/medium_id = 0
/proc/sys/net/ipv4/conf/vlan0/proxy_arp = 0
/proc/sys/net/ipv4/conf/vlan0/rp_filter = 0
/proc/sys/net/ipv4/conf/vlan0/secure_redirects = 1
/proc/sys/net/ipv4/conf/vlan0/send_redirects = 1
/proc/sys/net/ipv4/conf/vlan0/shared_media = 1
/proc/sys/net/ipv4/conf/vlan0/tag = 0

eth0:

root@OpenWrt:~# for f in /proc/sys/net/ipv4/conf/eth0/*; do echo "$f = `cat $f`"; done
/proc/sys/net/ipv4/conf/eth0/accept_redirects = 1
/proc/sys/net/ipv4/conf/eth0/accept_source_route = 1
/proc/sys/net/ipv4/conf/eth0/arp_announce = 0
/proc/sys/net/ipv4/conf/eth0/arp_filter = 0
/proc/sys/net/ipv4/conf/eth0/arp_ignore = 0
/proc/sys/net/ipv4/conf/eth0/bootp_relay = 0
/proc/sys/net/ipv4/conf/eth0/force_igmp_version = 0
/proc/sys/net/ipv4/conf/eth0/forwarding = 1
/proc/sys/net/ipv4/conf/eth0/log_martians = 0
/proc/sys/net/ipv4/conf/eth0/mc_forwarding = 0
/proc/sys/net/ipv4/conf/eth0/medium_id = 0
/proc/sys/net/ipv4/conf/eth0/proxy_arp = 0
/proc/sys/net/ipv4/conf/eth0/rp_filter = 0
/proc/sys/net/ipv4/conf/eth0/secure_redirects = 1
/proc/sys/net/ipv4/conf/eth0/send_redirects = 1
/proc/sys/net/ipv4/conf/eth0/shared_media = 1
/proc/sys/net/ipv4/conf/eth0/tag = 0

iptables rules:

root@OpenWrt:/etc/init.d# iptables -L -v
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  any    any     anywhere             anywhere            state INVALID 
 4350  292K ACCEPT     all  --  any    any     anywhere             anywhere            state RELATED,ESTABLISHED 
    0     0 DROP       tcp  --  any    any     anywhere             anywhere            tcp option=!2 flags:SYN/SYN 
   49  9824 input_rule  all  --  any    any     anywhere             anywhere            
   49  9824 ACCEPT     all  --  !ppp0  any     anywhere             anywhere            
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere            
    0     0 ACCEPT     gre  --  any    any     anywhere             anywhere            
    0     0 REJECT     tcp  --  any    any     anywhere             anywhere            reject-with tcp-reset 
    0     0 REJECT     all  --  any    any     anywhere             anywhere            reject-with icmp-port-unreachable  

Why having REJECT target ?? Probably to make port scanners job easier ;). hmmm, icmp and gre accepted are bad. Don't need icmp or at least icmp echo-request but not all the messages. I don't want to make xprobe2 or other icmp fingerprinters job easier.

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  any    any     anywhere             anywhere            state INVALID 
    0     0 TCPMSS     tcp  --  any    any     anywhere             anywhere            tcp flags:SYN,RST/SYN TCPMSS clamp to PMTU 
    0     0 ACCEPT     all  --  any    any     anywhere             anywhere            state RELATED,ESTABLISHED 
    0     0 forwarding_rule  all  --  any    any     anywhere             anywhere            
    0     0 ACCEPT     all  --  br0    br0     anywhere             anywhere            
    0     0 ACCEPT     all  --  vlan0  ppp0    anywhere             anywhere             

Everyone from the lan (vlan0) can access everything on the Internet (ppp0). Not cool.

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  any    any     anywhere             anywhere            state INVALID 
 3579  910K ACCEPT     all  --  any    any     anywhere             anywhere            state RELATED,ESTABLISHED 
    0     0 output_rule  all  --  any    any     anywhere             anywhere            
    0     0 ACCEPT     all  --  any    any     anywhere             anywhere            
    0     0 REJECT     tcp  --  any    any     anywhere             anywhere            reject-with tcp-reset 
    0     0 REJECT     all  --  any    any     anywhere             anywhere            reject-with icmp-port-unreachable   

hmmm, I dislike the 'ACCEPT all -- any any anywhere' rule. Why can the router send packet everywhere ? Same comment for REJECT target rules, they are useless and even harmful.

The next tables are defined to be customized in /etc/firewall.user. Another to had custom firewall rules is /etc/config/firewall. This one is parsed by /usr/lib/firewall.awk script.

Chain forward_ppp0 (1 references)
 pkts bytes target     prot opt in     out     source               destination    

Chain forwarding_rule (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 forward_ppp0  all  --  ppp0   any     anywhere             anywhere             

Chain input_ppp0 (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain input_rule (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 input_ppp0  all  --  ppp0   any     anywhere             anywhere            

Chain output_rule (1 references)
 pkts bytes target     prot opt in     out     source               destination

What need to be patched

The router doesn't need to access everything on the Internet (OUTPUT chain). The needed services are:

iptables -A OUTPUT -o $WAN -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -o $WAN -p tcp --dport 53 -j ACCEPT
iptables -A OUTPUT -o $WAN -dst 195.56.146.238 -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -o $WAN -dst 195.220.94.163 -p udp --dport 123 -j ACCEPT
iptables -A OUTPUT -o $WAN -dst 195.220.94.163 -p tcp --dport 123 -j ACCEPT

I think these rules should be in /etc/firewall.user .

Patch for /etc/init.d/S45firewall:

38,43d37
<   iptables -A INPUT -p icmp   -j ACCEPT       # allow ICMP
<   iptables -A INPUT -p gre    -j ACCEPT       # allow GRE
< 
<   # reject (what to do with anything not allowed earlier)
<   iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
<   iptables -A INPUT -j REJECT --reject-with icmp-port-unreachable
58,64d51
<   # allow
<   iptables -A OUTPUT -j ACCEPT                #allow everything out
< 
<   # reject (what to do with anything not allowed earlier)
<   iptables -A OUTPUT -p tcp -j REJECT --reject-with tcp-reset
<   iptables -A OUTPUT -j REJECT --reject-with icmp-port-unreachable
< 
79,82d65
<   # allow
<   iptables -A FORWARD -i br0 -o br0 -j ACCEPT
<   iptables -A FORWARD -i $LAN -o $WAN -j ACCEPT

Authorized services

To anywhere:

  • http and https
  • dns udp and tcp

To defined hosts:

  • smtp to an smtp relaies to send mail
  • pop3 or imap to pop3/imap servers to retrieve mails.
  • ntp client to some choosen ntp servers
  • msn main server e.g. messenger.hotmail.com
  • jabber servers.
  • irc or ircs to irc servers.
  • silc to silcservers.

OpenVPN Configuration

If things go wrong

The reset button on the rear panel, next to the wan port, put the router in the failsafe mode. The failsafe mode can be enabled during the pre-init phase (see /etc/preinit):

ifconfig $ifname 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 up
netmsg 192.168.1.0 "(dummy message)" # b44 eats the first packet             
netmsg 192.168.1.255 "Press reset now, to enter Failsafe!"      

sleep 2

if [ $(cat /proc/sys/reset) = 1 -o "$(nvram get failsafe)" = 1 ]; then
       while :; do { echo $(((X=(X+1)%8)%2)) > /proc/sys/diag; sleep $((X==0));
       export FAILSAFE=true
       [ "$(nvram get boot_wait)" != "on" ] && {
               nvram set boot_wait=on
               nvram commit
       }
       netmsg 192.168.1.255 "Entering Failsafe!"
       telnetd -l /bin/login <> /dev/null 2>&1
else                                           
       ifconfig $ifname 0.0.0.0

       # revert to the boot loader's vlan config
       # required for at least WRT54G v1.1
       [ -d /proc/switch/eth0 ] && {
               echo "$v0p" > /proc/switch/eth0/vlan/0/ports
               echo "$v1p" > /proc/switch/eth0/vlan/1/ports
               echo "$v2p" > /proc/switch/eth0/vlan/2/ports
       }
fi       

mount_root ${FAILSAFE:+failsafe}

exec /sbin/init

By default the wait time is 2 seconds, if you want more, just edit the line "sleep 2".

To see this you can launch a listening utiliy on udp port 4919 (e.g. 0x1337). nbd provides a tiny utility which bind a listening socket on the port (recvudp.c or recvudp).

You can start a netcat listening on the udp port too:

$ nc -u -l -p 4919

Wait for :

Msg from 192.168.1.1: Press reset now, to enter Failsafe!

Push the reset button. If you successfully push the button in the short range of time you will see:

Msg from 192.168.1.1: Entering Failsafe!

When you are in failsafe mode, the router is in default configuration with filesystems mounted read-only. You can mount the filesystem somewhere and make a backup if you forgot to make one before ;) :

root@(none):~# mkdir /tmp/wrt 
root@(none):~# mount -o rw /dev/mtdblock/4 /tmp/wrt
root@(none):~# tar zcvf wrt-backup.tar.gz wrt/* 

To transfer the tarball to another host, use netcat. Start a listening netcat en port 4444 on 192.168.1.10 for example:

$ netcat -l -p 4444 > wrt-backup.tar.gz
root@(none):~# dd if=/tmp/wrt-backup.tar.gz | nc 192.168.1.10 4444

You can also mount the actual root filesystem read-write:

root@(none):~# mount_root

Now, /dev/mtdblock/4 is mounted on / (rw).

To come back to default configuration, use the following command:

root@(none):~# firstboot

And reboot:

root@(none):~# reboot

More info on Troubleshooting section of the OpenWRT wiki.

TODO

I'd like to improve the security level of my wrt router. I will probably switch to kamikaze for some features I want.

  • chroot services with unprivileged user
  • harden kernel and memory management
  • compile with buffer overflow protection
Personal tools