[Japanese|English]

A Patch to Change the Format of alias.log in FreeBSD natd

Why I did it?

It's just a hard luck story.

Tokyo Metallic Communications' ADSL service, that I subscribed until recently, use PPPoE, and I set up packet filtering and NAT in ppp configuration. On the other hand, Yahoo! BB service, that I'm now using, delivers via simple bridging (IPoE.) I had to switch to a combination of ipfw and natd to do the job. The migration was (and is still) tough. The settings should essentially be same, but the new nat box behaves differently.

I tried several debug tools and techniques. The crux seemed to be in the NAT table. However, I found no handy way (other than invoking a gdb against a running natd) to refer to the exact NAT table content at a given time. So, I rewrote the natd.

The original natd has an option (that can be enabled by -l) to write the status of the address translation table to a log file called alias.log. What it actually writes is the number of translation entries per protocols, and is insufficient to know what translation is performed. So, I hacked the code to log changes to the NAT table whenever an entry is added or removed so that we can trace the contents of the table.

How to use the patch

Compiling

The patch changes a part of a source file of libalias that natd uses inernally. You should first get the original source files of natd and libalias as well as related build files, apply the patch, and re-compile everything. Alternatively, you can put source files from natd and libalias in a same directory, then compile and link all *.c files, ignoring Makefile's.

The patch changes only one source file, alias_db.c in libalias.

The source files of natd are located in the directory src/sbin/natd/ in the FreeBSD source tree. Those of libalias are in src/lib/libalias/.

The new log file

Applying this patch changes the format of alias.log file. When starting natd, use -l option to let the command to create the log file in the new format. Once you patched, it is impossible to get alias.log in old format.

The following example shows a part of a typical log file (of new format.) It is from a natd running on a machine with two Ethernet interfaces; a local (inner) interface of address 192.168.1.1 and a public (outer) interface of address 219.63.255.49. DNS server (named) is running on the same machine, and any PCs on the local subnet query to it when resolving domain names.

+ udp 219.63.255.49:1024 211.5.1.219:53 219.63.255.49:1024 *:* (0x8060100)
+ udp 219.63.255.49:1024 165.76.0.98:53 219.63.255.49:1024 *:* (0x8060180)
+ udp 219.63.255.49:1024 165.76.4.2:53 219.63.255.49:1024 *:* (0x8060200)
+ udp 219.63.255.49:1024 211.5.1.217:53 219.63.255.49:1024 *:* (0x8060280)
+ tcp 192.168.1.188:1346 210.142.46.154:80 219.63.255.49:1346 *:* (0x8060300)
+ udp 219.63.255.49:1024 210.141.108.194:53 219.63.255.49:1024 *:* (0x8060400)
+ udp 219.63.255.49:1024 210.239.166.194:53 219.63.255.49:1024 *:* (0x8060480)
+ tcp 192.168.1.188:1347 219.106.255.170:80 219.63.255.49:1347 *:* (0x8060500)
+ tcp 192.168.1.188:1348 219.106.255.170:80 219.63.255.49:1348 *:* (0x8060600)
+ udp 219.63.255.49:1024 210.142.46.155:53 219.63.255.49:1024 *:* (0x8060700)
+ udp 219.63.255.49:1024 211.18.214.210:53 219.63.255.49:1024 *:* (0x8060780)
- tcp 192.168.1.188:1346 210.142.46.154:80 219.63.255.49:1346 *:* (0x8060300)
+ tcp 192.168.1.188:1349 210.142.46.155:80 219.63.255.49:1349 *:* (0x8060300)
- tcp 192.168.1.188:1349 210.142.46.155:80 219.63.255.49:1349 *:* (0x8060300)
- udp 219.63.255.49:1024 211.5.1.217:53 219.63.255.49:1024 *:* (0x8060280)
- tcp 192.168.1.188:1348 219.106.255.170:80 219.63.255.49:1348 *:* (0x8060600)
- udp 219.63.255.49:1024 165.76.4.2:53 219.63.255.49:1024 *:* (0x8060200)
- udp 219.63.255.49:1024 210.239.166.194:53 219.63.255.49:1024 *:* (0x8060480)
- udp 219.63.255.49:1024 165.76.0.98:53 219.63.255.49:1024 *:* (0x8060180)

As you can see, the log file is recorded line-by-line, and fields in a line are separated with a space character. The fields are as follows:

  1. A "+" on the first column shows the line is from an addition of a new table entry, a "-" a deletion, and an "=" a modification.
  2. The second field shows the protocol that the entry is for. If the protocol is not significant to the natd operation, it is shown as a protocol number instead of a protocol name. This value is taken from link_type.)
  3. IP address and port number of inner end point. They are taken from src_addr and src_port.
  4. IP address and port number of outer end point. They are taken from dst_addr and dst_port.
  5. The alias IP address and port number (of translated inner end point.) They are taken from alias_addr and alias_port.
  6. The redirect IP address and port number for transparent proxy operation. They are taken from proxy_addr and proxy_port.
  7. The (virtual memory) address of struct alias_link data block. (This information is rarely useful.)

The above example is a snapshot when a PC with IP address 192.168.1.188 is accessing a WWW site.

All UDP entries have a same port number, 53, in public end points. They correspond to several DNS resolve operations. Local end points of them are all 219.63.255.49:1024, that is actually a port grabbed by the DNS server (named) running on the machine.