Tuesday, August 18, 2009

6 ways to crash your linux. Because it's fun and useless :)

This is the kind of topics that are completely useless, but that I like. It's probably like playing the Wii, it's useless, but you (we) like it.
Well, here are different ways to crash your linux box, some of them are well known, like the fork bomb, others are more obscure. Some are irreversible, others are just "for the session", where a simple reboot is enough.

Let's see them.
  • The Fork bomb: this is a classic I shouldn't mention. Actually, it has a whole wikipedia page devoted to it.
     :(){ :|:& };: 
    will run your machine out of resource, unless you limit user processes in /etc/security/limits.conf.
  • The next will overwrite your MBR with (pseudo) random data. At least you'll be sure not to boot your OS again (neither Windows).

    dd if=/dev/urandom of=/dev/sda bs=512 count=1
  • Reading I/O ports can have some nice "side effects". Try to run this command and you'll see what I'm talking about
    sudo less -f /dev/port
    The result will be that your machine will freeze. I did not dig into that to know why it was freezing, but this is fun :).
  • What happens when you overwrite the memory of a process ? Usually, it segfaults. You can put some fun (mess ?) in your system memory:
    cp /dev/zero /dev/mem
  • This one became a cult, just because it probably already happened to you. You somehow make a confusion and you remove every single file on your hard drive
    rm -rf /*

  • Finally, we could use the power of the find command, with the 'exec' argument that will execute the command that follows it. This kind of mistake can happen when you are in a hurry.

    find . -type f -name * -exec rm -f {} \;

Hopefully, a lot of these commands (except the fork bomb) won't damage your computer if you run them as a simple user, simply because the linux system won't let you access the file you don't have the permission on.
Obviously, if you try to write some LKM, the kernel will probably crash without your approval :P. From here, you could do whatever you want, since you are "God Almighty".

Do you know some other ways to crash your machine ? Don't hesitate to post your way in here.

Saturday, August 15, 2009

ath_pci & ath5k: I want to use both of them

Here is my problem:
I have two physical wireless cards. Until now, I was using the madwifi ath_pci modules for both cards. However, it fails a lot, is not very accurate, triggers kernel oops, losses the connection, etc. To sum up, I really don't like it. However, there is another option, by using the ath5k module. Sadly, ath5k does not support AP mode for now (well, it's experimental). So what I want to do is to use ath_pci for one card, the one that will be configured as AP, and ath5k for my client.

Thanks to a geek friend (he'll recognize himself, hein nicolas ?), he figured out that we can unbind the device, as it is explained in here.

Basically, I load both drivers (ath5k and ath_pci) when my box boots, and then, I simply do

echo 0000:00:0e.0 > /sys/bus/pci/drivers/ath5k/unbind
echo 0000:00:0e.0 > /sys/bus/pci/drivers/ath_pci/bind

We simply unbind the desired interface from ath5k and bind it again to ath_pci. To know which number to assign, just do a lspci. That works great.

Wednesday, August 12, 2009

9 hardcore tips to boost your Wifi signal [that normal people don't know about]

I'm not going to speak about adding an antenna or adding a repeater to increase your signal. This topics are trivial and well covered (just see here for instance). Instead, we will look at different optimizations for signal gain, that you probably were not aware of.
In this topic, I will mostly address the problem you might have when dealing with a medium distance access point (like your neighbour for example).


Antenna related

1) The antenna is probably the first tool you will need to have a descent signal. Choosing a good antenna does depend on the place where you live. For example, if you live in a very dense city, it makes no sense to use a 26dbi parabolic dish. Instead, you will prefer a Yagi or a panel antenna. Looking at the radiation pattern of the antenna will help you understanding what is the best for you. Moreover, if you have a high gain antenna, you will face up the hidden terminal problem. So don't fall in the trap of "the biggest the best". Of course, it will be a good idea to put your antenna outside, ie on your balcony or on the window edge.

2) Avoid using too many connectors. Indeed, every time you use a connector (or a pigtail), a large part of the signal is lost. Prefer only one wire, directly connected from your access point(AP)/card to the antenna.

3) Use very small cables. I'm always amazed when I see people on ebay selling Yagi antenna with 30 meters of coax cable. A good low-loss cable has a loss of around 0.4db/meter, it means that if you have 30 meters of cable, you are loosing 12dbi. So what's the point of having a 19dbi antenna then ?

4) The polarization of the antenna is something people usually don't care. However, a "mis-polarized" antenna can have tremendous damages on your signal If you don't know what "polarization" is, just think about your polarized sunglasses. Basically, the glasses let only pass certain type of waves. In wireless it's the same: if someone is emitting a vertically (linearly) polarized wave and you set up your antenna horizontally, you will miss the signal.
If you still don't understand what this "polarization" is, the best way to proceed is by "trial and error": turn your antenna all the way around until your get the maximal strength.
The following antenna has an horizontal polarization (source: Wikipedia), for some obvious reasons. If you take another parabolic antenna and you turn it to have a vertical polarization, you won't be able to get any signal.

However, waves might change polarization when they hit objects, so don't go too crazy with that. Usually, omnidirectional antennas are low profile antennas and tempts to have a circular polarization. Based on my observation, I would say that the vertical polarization is predominant, though.

Note that it doesn't mean because your are pointing to the AP that you will get the maximum strength (this is only true for parabolic antennas). In the future, we will see how to measure the signal in a pretty accurate manner.


802.11 & hardware related

5) If you can change the AP channel, try to take one that is not over-used in your neighbourhood. You can figure this out by counting the number of access points that are on the same channel, by using kismet for example. This makes sense, since data is braodcasted, the more people will use the same channel (even with different APs), the more collisions there will be. Note that the channels go by group of 3, like on this figure. Thus, channel 1 and 3 lie on the same frequency band, but channel 1 and 5 don't. Usually, people don't change their channel, and leave the default one (usually 6 or 1), so switching to channel 14 seems to be a good plan. Of course, if you can go 5GHz, go 5GHz, there will be even less people on there.


6) Many times, changing channel does not help, because they are all busy and a lot of people are using them. In this case, enabling RTS/CTS (Request to Send / Clear to Send) will definitely help. Basically, when a client wants to send a packet, it first sends a RTS to make sure nobody is using the channel. Then, the AP replies with a CTS to confirm that it (the client) can send its packet.
RTS/CTS is usually disabled (ie set at a very high value). If the channel is very busy, you'll need to decrease the RTS/CTS threshold, at 500b for example, meaning that a RTS will be sent only for packets >= 500b. You'll increase the overhead, but ultimately you'll transmit more packets (and avoid the hidden node problem).

To understand better why the RTS/CTS is needed, let's take this example: suppose that you are in a restaurant. If it's crowded, there will be a lot of people speaking at the same time (ie channel "busy"). By analogy - if you assume that the restaurant is the channel you are using and the people speaking are the clients using this channel - when using RTS/CTS mechanism, we take care that no other people are speaking. It's like saying "Now I'm speaking, please shut up (RTS)" to everyone in the restaurant, and the person to whom you are speaking would reply (once everybody is silent) "OK, I let you speak now, go ahead (CTS)". Of course, if you are alone in the restaurant, there is no need to say that. Well, don't do it in real life, it might be weird...

7) We have seen that when a channel is busy, we can enable the RTS/CTS mechanism. However, sometimes the link is BAD, meaning there is a lot of white noise on the line. Basically, you might have a good signal, but a lot of noise, decreasing your signal/noise ration (SNR). The trick here is to transmit smaller packets. Suppose that you are sending BIG packets and the noise destroys a packet with a certain probability, you will loose more data (and hence need to retransmit) when these packets are big rather than small. Well, this doesn't work linearly like that, but you got the idea. It means that if the packet is smaller, there will be less to retransmit. This setting can be changed through the fragmentation threshold.

That's interesting to notice that your microwave oven is running at around 2GHz and Wifi is operating at 2.4GHz. Microwave ovens are studied to maximize the absorption by water (to warm it), and it happens to be at around 2GHz. What does it mean ? It means that when it's rainy, the signal is lost in... the rain, or in other words, the Wifi is somehow warming the rain. Thus, humidity acts as a wireless barrier.

8) Have you ever looked at a wireless chip datasheet ? Here is a snippet.





What ca we see from the datasheet ?
  • The output power is maximized when the data rate is low.
  • The sensibility is maximized when the data rate is low (ie 1Mbps).
It makes sens to set the AP between 1->6Mbps, doesn't it ? We will increase the sensibility (ie we will "receive better"), and also increase the output power (ie we will "better send"). However, if you decrease *YOUR* bit rate, you will reserve the channel longer and thus, other people will see a drop down in their maximal bitrate.

9) Decrease the power of your AP: if you are living in a very tiny place and you have access to the tx power (you are using dd-wrt for example), you can decrease it. Indeed, you will radiate less and thus you will decrease the problems you might have with the neighbourhood (with RTS/CTS for example, avoiding the exposed terminal problem).

9.2) Finally, when dealing with multiple user connected to an AP, we can hack the wireless driver to gain priority. Basically, there exist techniques to reserve the channel more than usual (ie greedy user) and this will probably be a topic I'll discuss on this blog.


We are the end of our wifi-tips. I hope your learned something new and feel free to leave your impressions/comments.

Monday, August 10, 2009

Trigger an event when someone (unknown) connects to the AP

To trigger an event when someone connects to my open AP, I had the following choices:

  • Get the output of hostapd. Indeed, when someone associates, hostapd outputs some stuff.
  • We can see the modifications in /proc/net/madwifi/athX/associated_sta

    > cat /proc/net/madwifi/ath0/associated_sta
    macaddr: <00:11:f1:51:e6:10>
    RSSI 30
    last_rx 0.013332
    ni_tstamp 0 ni_rtsf 3567813500
    macaddr: <00:11:77:ce:c1:13>
    RSSI 22
    last_rx 0.003333
    ni_tstamp 0 ni_rtsf 3567821275


  • We can modify the madwifi driver to trigger some special event.
Actually, I chose the 3rd option, because it was the cleanest one in my opinion. Since I don't have a big experience with kernel programming, I first googled a little and found this. That was exactly what I was looking for. Besides, it was even easier to what I was doing (playing with inotify...).

I just could not use his patch, because I am using madwifi-hal-0.10.5.6/ in the branch/, since I had big problems with stuck beacons. Basically, what you have to do, is find the function responsible for association (supposing you want to do something when a new association occurs). In the file madwifi-hal-0.10.5.6/ath/if_ath.c, you will find the ath_newassoc(...) function, that after patching will become:


static void
ath_newassoc(struct ieee80211_node *ni, int isnew)
{
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ath_softc *sc = netdev_priv(ic->ic_dev);

/* Kernel Object Event patch (dmr@c0nc3pt.com) */

struct kobject *kobj = &vap->iv_dev->dev.kobj;
char atd[12], mac[4+18], bss[4+18];
char *envp_ext[] = {
atd,
mac,
bss,
NULL
};


sc->sc_rc->ops->newassoc(sc, ATH_NODE(ni), isnew);

/* are we supporting compression? */
if (!(vap->iv_ath_cap & ni->ni_ath_flags & IEEE80211_NODE_COMP))
ni->ni_ath_flags &= ~IEEE80211_NODE_COMP;

/* disable compression for TKIP */
if ((ni->ni_ath_flags & IEEE80211_NODE_COMP) &&
(ni->ni_wpa_ie != NULL) &&
(ni->ni_rsn.rsn_ucastcipher == IEEE80211_CIPHER_TKIP))
ni->ni_ath_flags &= ~IEEE80211_NODE_COMP;

ath_setup_keycacheslot(sc, ni);
#ifdef ATH_SUPERG_XR
if (1) {
struct ath_node *an = ATH_NODE(ni);
if (ic->ic_ath_cap & an->an_node.ni_ath_flags & IEEE80211_ATHC_XR)
an->an_minffrate = ATH_MIN_FF_RATE;
else
an->an_minffrate = 0;
ath_grppoll_period_update(sc);
}
#endif
/* KOE: feel free to add whatever you want... :-) */

snprintf(atd, sizeof(atd), "ASSOCIATE=%c", isnew ? '1' : '0');

snprintf(mac, sizeof(mac), "MAC=%02x:%02x:%02x:%02x:%02x:%02x",
ni->ni_macaddr[0], ni->ni_macaddr[1],
ni->ni_macaddr[2], ni->ni_macaddr[3],
ni->ni_macaddr[4], ni->ni_macaddr[5]);

snprintf(bss, sizeof(bss), "BSS=%02x:%02x:%02x:%02x:%02x:%02x",
ni->ni_bssid[0], ni->ni_bssid[1],
ni->ni_bssid[2], ni->ni_bssid[3],
ni->ni_bssid[4], ni->ni_bssid[5]);
if (kobject_uevent_env(kobj, KOBJ_CHANGE, envp_ext) < 0) {
printk(KERN_ERR "madwifi-ng kobject trouble!\n");
}
}


I find the way the event is set up is very clear and easy to understand. Then, after that, you recompile your sources and load the module.

Here comes the interesting part: setting a udev rule to catch the event. I was pissed off because it didn't work the way the guy was describing. Actually, since there was a typo, udev didn't catch the event.
Let see how to build a udev event.

> udevadm monitor --kernel --environment
monitor will print the received events for:
KERNEL - the kernel uevent

KERNEL[1249918765.975675] change /devices/pci0000:00/0000:00:0e.0/net/ath0 (net)
UDEV_LOG=0
ACTION=change
DEVPATH=/devices/pci0000:00/0000:00:0e.0/net/ath0
SUBSYSTEM=net
ASSOCIATE=1
MAC=00:26:11:A1:71:11
BSS=06:C0:B3:A3:b5:d8
INTERFACE=ath0
IFINDEX=8
SEQNUM=942


Basically, udevadm gives us the fields to enter to make our rule.

> cat /etc/udev/rules.d/99-wlan-association.rules
SUBSYSTEM=="net", ACTION=="change", ASSOCIATE=="1", RUN+="/home/root/scripts/assoc.sh"

If you want to be more precise with the udev rule, just add a new field, like the INTERFACE for example. In my case, I found this as being just great. Upon even, the script assoc.sh is executed.

Let see what this script does (as an example):

#!/bin/bash
#!/bin/sh

set $*
FILE=/home/root/scripts/macaddr.txt


RESULT=`grep ${MAC} $FILE`
if [ ! $RESULT ]
then
sms myself "${MAC} associated with ${BSS} (${INTERFACE})"
fi

The file macaddr.txt contains known MAC addresses. If grep does not find the MAC address in this file, it means that we don't know the guy that connected and the box sends me a sms. Cool, isn't it ? Now we can do on-demand-MITM (or on-association-MITM).

Again, greetz to dmr who did the kevent stuff.

Tuesday, August 4, 2009

Cache it, cache it, cache it!

Now that we have a [semi] working box, we can "boost" the connection by adding caching. We can add caching for:
  • dns queries: We already did that when setting up dnsmasq.
  • Web: a squid proxy will do the job.
Even if dnsmasq was extremely easy to configure, it has a big disadvantage: it does not keep the cache between two reboots. Personally, my box reboots at least once a day, so if I can keep the cache it would be great. After googling for a while, I figured out that dnsmasq does not have permanent caching :(. That's very sad. However, there is another another proxy dns server called pdnsd, keeping the cache permanently, ie surviving the reboots.

Here is my configuration file:

global {
perm_cache=1024;
cache_dir="/var/cache/pdnsd";
run_as="nobody";
server_ip = ath0; # Use eth0 here if you want to allow other
# machines on your network to query pdnsd.
status_ctl = on;
# but may make pdnsd less efficient, unfortunately.
query_method=udp_tcp;
min_ttl=15m; # Retain cached entries at least 15 minutes.
max_ttl=2w; #
timeout=10; # Global timeout option (10 seconds).
server_port=53;
daemon=on;
}

server {
ip="83.219.127.194";
label= "resolvconf";
# This may be necessary if you are behind some
# kind of firewall and cannot receive replies
# from outside name servers.
timeout=4; # Server timeout; this may be much shorter
# that the global timeout option.
uptest=if; # Test if the network interface is active.
interface=ath0; # The name of the interface to check.
interval=10m; # Check every 10 minutes.
purge_cache=off; # Keep stale cache entries in case the ISP's
# DNS servers go offline.
}


I put server_ip = ath0 to listen to my WPA encrypted interface. The IP entry is one of the /etc/resolv.conf file. This is not really interesting to have to import manually the nameserver from resolv.conf, but it is not really hard to do a small script that does it. There are plenty of ressources for that on the net.

If the router's IP address is 192.168.100.1, you have to add "nameserver 192.168.100.1" to the client's resolv.conf. Then, you can test that it is working properly (from the client):


> dig @192.168.100.1 mycokemusic.ch mx

;; QUESTION SECTION:
;mycokemusic.ch. IN MX

;; ANSWER SECTION:
mycokemusic.ch. 3600 IN MX 10 mx.eunet.at.

;; AUTHORITY SECTION:
mycokemusic.ch. 3587 IN NS ns3.ko.com.
mycokemusic.ch. 3587 IN NS ns4.ko.com.

;; ADDITIONAL SECTION:
ns3.ko.com. 123575 IN A 205.160.52.52
ns4.ko.com. 49422 IN A 205.160.52.53

;; Query time: 365 msec
;; SERVER: 192.168.100.1#53(192.168.100.1)
;; WHEN: Tue Aug 4 20:34:38 2009
;; MSG SIZE rcvd: 133





> dig @192.168.100.1 mycokemusic.ch mx

;; QUESTION SECTION:
;mycokemusic.ch. IN MX

;; ANSWER SECTION:
mycokemusic.ch. 3597 IN MX 10 mx.eunet.at.

;; AUTHORITY SECTION:
mycokemusic.ch. 3584 IN NS ns3.ko.com.
mycokemusic.ch. 3584 IN NS ns4.ko.com.

;; ADDITIONAL SECTION:
ns3.ko.com. 123572 IN A 205.160.52.52
ns4.ko.com. 49419 IN A 205.160.52.53

;; Query time: 1 msec
;; SERVER: 192.168.100.1#53(192.168.100.1)
;; WHEN: Tue Aug 4 20:34:41 2009
;; MSG SIZE rcvd: 133


We passed from 365ms to 1ms, which is not bad. Note that since we are not using dnmasq for its dns proxy settings, we have to deactivate it. I did not find how to disable it, so I simply added port=1 to the dnsmasq.conf.

Now it's time for squid. As you probably now, squid has a feature called "accelerator mode". The idea here is that we want to configure the proxy and the user not to have to configure it manually (ie transparent proxying).
I did not change a lot from the squid.conf default file. I added the following at the end of the file:

acl port80 port 80
http_access allow port80
always_direct allow all


I also changed the file were the cache is written, due to the partitioning of my CF.

cache_mem 100 MB
cache_dir ufs /home/squid/ 100 16 256


After that, squid is opened on port 3128. We want to redirect all the http traffic toward the squid proxy (the same way we did for sslstrip)

iptables -t nat -A PREROUTING -i ath0 -p tcp --dport 80 -j REDIRECT --to-port 3128


From the client, you should be able to connect to the net, without having to modify the network settings of your browser.

By using these two caching methods we substantially decreased the amount of internet traffic ;)