How to setup an IDS on a home network

Firstly, I have to say that every home would have a different network setup.  So let me talk about the setup I got a bit:

I don’t have cable and I don’t have ADSL.  Only thing I got is a mifi device with a Viva subscription chip.   It is basically a Huawei device that looks like this:

mifi

 

I got 4 computers and a smartphone that connect to the mifi device  (wirelessly )

As one would image with devices that come with a subscription, I don’t have much control over its settings.   To setup an IDS one would need to at least to mirror traffic to a port or a machine.   There’s no way I could do that here.

So, before settings up the IDS, I needed to add more flexibility to my network.

Updating my Network Infrastructure

I decided to buy a TP-Link TL-WR1043ND. 

TP-Link Router
TP-Link Router

Why, you ask?  It was the first one I found that support OpenWRT, which I will talk about below.

Topology-wise, I needed something like this:

  • One wireless switch that accepts both wireless and cable connection
  • The wireless switch should act as an access point to the mifi device that connects to the Internet.

The Switch in this case that will act as an access point will be the TP-Link router

After that I will make sure to set up port mirroring on the router such that all traffic inbound/outbound will be copied and sent to an IDS sensor, which is also physically connected to the TP-Link router via an Ethernet cable.

 

Let’s start with turning the TP-Link router to an access point to the mifi point

Setting up TP-Link with OpenWrt

The original firmware wouldn’t support turning the router to an access point.  So, I had to flash something that had more functions.  And the first that came to mind was OpenWrt.   OpenWrt is one of the most widely used firmwares around.  It incorporates a lot of the functions needed in a home router.   So I flash the firmware used for my TP-Link model, which is here. I flashed “Attitude Adjustment”.

This what the original page looks like before flashing:

 

Tp-Link Original Firmware
TP-Link original firmware flashing option

 

And here’s what the router web interface looks like under OpenWrt

 

OpenWrt WebUI
OpenWrt WebUI

 

 

Ok.  So, now that I have OpenWrt on my router.  I need to setup the access point, and connect it to my mifi device. I shamelessly copied this from here.    This was a question I asked in the OpenWrt forums.

  • The steps are pretty much straight forward:
    Log into the luci webgui
  • Click on wifi under the network tab
  • Click on edit behind the wirless network
  • Set all settings for your private wifi network as desired (security and ssid)
  • Save and apply the settings
  • Enable the wifi radio, by clicking the enable button behind the wifi network
  • Click on the scan button
  • In the list that appears, click on ‘Join network’ for the appropriate network you want to connect to
  • Untick ‘Replace wireless configuration’
  • Fillout the WPA/WEP passphrase if that’s needed
  • Click on submit
  • And save and apply the unsaved changes

One more thing I need to do is to setup the nameserver for this interface that is set as an access point:

I edit /etc/config/network and make it look something like this:

root@OpenWrt:~# cat /etc/config/network

config interface 'loopback'
option ifname 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'

config interface 'lan'
option ifname 'eth0.1'
option type 'bridge'
option proto 'static'
option netmask '255.255.255.0'
option ipaddr '192.168.1.2'
option dns '8.8.8.8 8.8.4.4'

Do I have Internet on the TP-Link router?


BusyBox v1.19.4 (2013-03-14 11:28:31 UTC) 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
-----------------------------------------------------
ATTITUDE ADJUSTMENT (12.09, r36088)
-----------------------------------------------------
* 1/4 oz Vodka      Pour all ingredients into mixing
* 1/4 oz Gin        tin with ice, strain into glass.
* 1/4 oz Amaretto
* 1/4 oz Triple sec
* 1/4 oz Peach schnapps
* 1/4 oz Sour mix
* 1 splash Cranberry juice
-----------------------------------------------------
root@OpenWrt:~# ping www.google.com
PING www.google.com (173.194.124.48): 56 data bytes
64 bytes from 173.194.124.48: seq=0 ttl=53 time=53.207 ms
64 bytes from 173.194.124.48: seq=1 ttl=53 time=50.760 ms
64 bytes from 173.194.124.48: seq=2 ttl=53 time=59.722 ms
64 bytes from 173.194.124.48: seq=3 ttl=53 time=96.626 ms
^C
--- www.google.com ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 50.760/65.078/96.626 ms

Yes, I do, which means the TP-Link router is connected to the mifi  and I can connect my machines directly to the router and have access to the Internet.

Ok…good:  now let’s see if I can setup port-mirroring on this router.

Setting up Port-mirroring

I found something really convenient on google code:  It’s simply called port-mirroring, and works on OpenWrt 🙂

 

I noticed that the protocols it supports for port mirroring is “TEE” and “TZSP”.

Here is what the Project Home page says:

“TEE” format mirroring is added in version 1.3. Since version 1.3, you can choose “TEE” or “TZSP” as the mirroring protocol.

 

 

If you don’t know what TZSP is,  it’s a protocol used to encapsulate layer 2 packets in UDP datagrams.   This is perfect for my scenario since I want the mirrored packets to be forwarded to a host.  Seems to me a lot easier then the “TEE” option.

Ok, so I download port-mirroring on my openwrt flashed router and install it.


root@OpenWrt:~# opkg update
root@OpenWrt:~# opkg install http://port-mirroring.googlecode.com/files/port-mirroring_1.3-1_12.09_ar71xx.ipk

 

I then make sure the protocol it uses it “TZSP”  and the IP address the packets go to is 192.168.1.64.


root@OpenWrt:~# cat /etc/config/port-mirroring
#
#"target" defines the mirror target, it can be a local interface or a remote ip
#address. For openwrt routers, it shall be remote ip in most case.
#
#"source_ports" defines the mirrored interface, for example, "wlan0" will mirror#all wireless traffic. Multiple interfaces are supported(ie: "wlan0,eth0").
#

config 'port-mirroring'
option "target" '192.168.1.64'
option 'source_ports' 'br-lan' 'br-wan'
option filter ''
option 'protocol' 'TZSP'
root@OpenWrt:~#

 

and I start the port-mirroring functionality:


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

Now, it’s time to check the IDS monitor with IP 192.168.1.64, is it receiving any traffic:

 

encapulated UDP traffic
UDP Traffic to the Sensor (192.168.1.64) encapsulated

 

Well, the good news is it is receiving traffic.  Bad news is, as you would expect, it is encapsulated with UDP, which is expected with TZSP.  Notice there is other traffic, which is just noise.  Can’t send the traffic to the  IDS sensor encapsulated.  (Well, I could, but would add a lot of overhead and would affect its accuracy).

 

So, I need to remove the UDP datagram to get the “real” network packets.

 “Decapsulating” TZSP Packets

What really comes to rescue here is Scapy.  Scapy is a tool that allows me to mess around with packets.  It has a python library that I will use to remove the UDP details.  I first tell the program to monitor everything on ‘eth0’ and then for all UDP datagrams it should remove the TZSP encapsulation and send the traffic to ‘eth1’.  (I consider this safe, since I only expect TZSP traffic to arrive on this laptop if it is UDP).

 

The code looks like the below:

from scapy.all import *

def writep(packet):

    udp_packet = packet.payload.payload

    tzsp_packet = udp_packet.payload
    tzsp_packet_str = str(tzsp_packet)

# remove 4 bytes of header plus first 2 bytes of tagged fields, last byte will give us how many more bytes we need to remove

    tzsp_minus_header_str = tzsp_packet_str[5:]

    try:    

        tzsp_decapsulated_packet = Ether(tzsp_minus_header_str)
    except:
        return

    sendp(tzsp_decapsulated_packet,iface="eth1",realtime=True)
def main():
    sniff(iface="eth0",filter="udp",prn=writep)    

main()

 

I, of course, need to create the dummy virtual interface ‘eth1’ since I do not actually have it.  This is straight-forward on Debian


root@debian:/home/b3d0uin# ip link add name eth1 type dummy
root@debian:/home/b3d0uin# ip link set promisc on
root@debian:/home/b3d0uin# ip link set dev eth1 promisc on
root@debian:/home/b3d0uin# ip link set eth1 up

I run the scapy code in the background (of course, I need to have python installed on machine).

 

OK.  I will start up my program and take a look at the traffic on eth1 this time:

 

TZSP  'Decapsulated' Traffic
‘Decapsulated’ pakcets after removing the TZSP encapsulation on 192.168.1.64

 

and on wireshark after visiting a website from my phone which is connected to the TP-Link switch:

wireshark traffic
Wireshark traffic after visiting www.indiana.edu on my phone

 

 

Boom!  I have traffic on ‘eth1’

 Setting up and IDS Sensor (Bro):

It is all downhill from here,  I need to install an IDS.  I picked Bro

I downloaded Bro 2.2 since at the time of writing it is the stable release.

I need to make sure it points to ‘eth1’ by  editing node.cfg under /usr/loca/bro/etc/ and set the interface as ‘eth1’

# Example BroControl node configuration.
#
# This example has a standalone node ready to go except for possibly changing
# the sniffing interface.

# This is a complete standalone configuration.  Most likely you will
# only need to change the interface.
[bro]
type=standalone
host=localhost
interface=eth1

I then start bro


root@debian:/home/b3d0uin# /usr/local/bro/bin/broctl

Welcome to BroControl 1.2

Type "help" for help.

[BroControl]> start

 

Is bro receiving?  One way is to test is to connect my smartphone to the TP-Link router and visit a website, and then check http.log under /usr/local/bro/logs/http.log

and it looks like it worked:

 

Bro http.log Traffic
bro-traffic on http.log after visiting a website (guess which one?)

 

 

and that’s it!

 

I have an IDS installed on my home network.  Of course, this is just the beginning.  I need to tune the IDS and test it, of course.  I have no doubt that there might be something I’m missing in terms of port mirroring and directing traffic since I’ve done this real quick.  But if there is anything it will show up sooner or later 🙂  Notice that by using TZSP I don’t really need the sensor to be directly connected to the cable.  It could be on the Internet for all we care.

 

Ok, this was a long post, but I really couldn’t find a less complicated way of doing what I did given my initial network setup.  I hope in upcoming posts I can talk more about doing stuff on the actual IDS.

 

SSH Tunnels

 

I got fascinated by this topic when I messed around with machines that were behind firewalls.  It could really be annoying using services on those machines especially if you’re out of the machine’s subnet.

Imagine for example you access a wiki at work.  But the problem is, the wiki server only accepts private IPs that are in the work subnet.  So if I wanted to work from home, I am kind of doomed.  Of course, one way is to setup a VPN service that would accept a remote connection and have access to the wiki.  But, not many companies would like to use any of its resources for a VPN service.  Also, accessing a VPN in and of itself could be annoying.

Here’s where I started getting attracted to SSH tunnels.  SSH stand for Secure Shell, a protocol that allows you to access a server remotely through a console where, unlike Telnet, the communication is actually encrypted.  So, this protocol was basically what allowed me to easily access the wiki from home.

I had a computer that had a public IP address at work.  I setup an OpenSSH server on it, and added an account that I could log in to.  The word tunnel in SSH tunnel refers to the fact that my laptop at home will access the work wiki through the SSH server that I setup on the work machine.  So a tunnel will be established between my laptop and my work computer where that will allow me to send (and receive) HTTP data to the work computer.  It would be just like I was on my work computer.

I just needed to do the following:

  • Install OpenSSH on my work computer
  • For firefox install an add-on called FoxyProxy that would allow your browser to direct http requests to the tunnel I will setup.

Setting up a tunnel:

To setup a tunnel, all what needs to be done from a Unix terminal is:

ssh -D8080 [my work computer ip]

According to the man page of the SSH tunnel, this basically opened up a port on my local machine (laptop) for forwarding  quoted from the ssh man page:

“Whenever a connection is made to
this port, the connection is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine”

So basically the tunnel is set, now all  I need to do is tell Firefox that I would like  it to direct some requests to this SSH tunnel.

Righting click on the FoxyProxy icon (lower right of the browser in my case), I clicked on options to add a new proxy.  Under the proxy details tab,I simply select the manual proxy configuration where I declare IP as localhost since that is where the first end of the tunnel is located, and the port as the listening port in the tunnel (8080 in my case).  Since SSH man page mentions that the ssh protocol  will act as a SOCKS server, I specify on FoxyProxy that the main protocol I will be using is SOCKS5.

Foxyproxy also has the option of setting up whitelist or blacklist urls, so that it only uses a proxy when you enter a specific URL. So that way, Firefox knows when to use the proxy.  So I basically added my work’s URL followed by an asterisk indicating a wildcard.

Now I am done, as long as the tunnel is open, I can simply open my browser and type the work’s URL, and I have full access to the wiki.

 

Multiple Tunnels

Ok, that was relatively simple.  Now let’s say you want to access a SOAP service in your company that is on an internal IP address.

Imagine the following environment:

  • The SOAP service is in an internal subnet (e.g. 192.168.5.0/24)
  • you have access to a server A that is in that subnet, but the server also has another network interface eth1 on a different subnet.
  • eth1 on Server A can only be accessed through Server B.
  • Authorized users have SSH access to Server B from anywhere in the world.

Confusing?  yes.   Don’t ask me why this configuration exists, sometimes building subnets and firewalls leads to this kind of mess.  Nonetheless , I found myself required to open up a public interface to the soap server so that a remote client machine could access it.  I decided to set it up on a server that I have control over let’s call it Server C.

So this is what I needed to do:

  1. Setup a tunnel between Server C and Server B.  I’m not allowed to do a lot on server B, but I do have SSH access and I am allowed to ssh from it.  So I setup a tunnel between server C and B (call it Tunnel A).
  2. I use the tunnel in 1 to setup another Tunnel between C and Server A, which I will use to get to the SOAP server.
  3. I need to make sure that the tunnel I set is open to the outside world so that the remote client could connect to it.

Here are the SSH commands I needed to perform:

ssh -L localhost:2222:[ip-address-of-server-A]:22 [ip-addres-of-server-B]
ssh -L [ip-address-of-server-C]:3333:[IP-address-of-SOAP-service]:80 localhost -p 2222

This way I simply tell the remote client to use the SOAP service by using the IP address of server C port 3333.  That will direct the requests through the tunnel to the SOAP server I have in the private subnet.

It might be a good idea to setup security at this stage.  One option would be to set iptables on server C that allows access to port 3333 to the client only.

This really summarizes what you can do with SSH: you tie up many servers together and setup one tunnel.  Even though the protocol itself is secure it doesn’t mean we can really ignore security.  Firewalls need to be set to limit what goes “in” and “out” of the tunnel.   After all, an access point  (a point that an attacker can exploit) is being opened up, so….make sure the right traffic gets to this access point.