How to log (eg. iptables) messages based on message body in a separate file using rsyslogd

In Debian the default /etc/rsyslog.conf includes all *.conf files from /etc/rsyslog.d. The contents of these config files are read by rsyslogd before the default rules, so you easily override any defaults.

Eg. to save all messages starting with "iptables: " into /var/log/iptables.log, you can create a /etc/rsyslog.d/iptables.conf with the following contents:
:msg, startswith, "iptables: " -/var/log/iptables.log
& ~

Yes, these are two lines. Smile
If the above doesn't work for you, chances are that the message body contains has something else at the message start besides the "iptables: " prefix (that you might have used in all of your iptables rules). To debug the issue, use contains instead of startswith and use a template to mark the boundaries of the various log line segments.
Eg.
$template MyTemplate,"aaa%timegenerated%bbb%HOSTNAME%ccc%syslogtag%ddd%msg%eee\n"
:msg, contains, "ipt: " -/var/log/iptables.log;MyTemplate
& ~

Eg. on a default Debian Squeeze system the above template generates log entries like this:
aaaFeb 20 21:58:13bbbapps4ccckernel:ddd[1766537.526785] iptables: IN=eth0 OUT= MAC=b4:99:ba:bd:3f:36:00:1e:8c:10:84:b6:08:00 SRC=195.228.155.30 DST=195.228.155.36 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=33501 DF PROTO=TCP SPT=38402 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0 eee

The above log was the result of an iptables rule with a --log-prefix "iptables: " option. However the kernel has put the "[1766537.526785] " string before our prefix. To compensate for it, you can use the contains compare operation:
:msg, contains, " iptables: " -/var/log/iptables.log
& ~

Or you can use a (basic) regular expression:
:msg, regex, "^\[[0-9][0-9]*\.[0-9][0-9]*\] iptables: " -/var/log/iptables.log
& ~