This may be an old question, but using packet marking actually can help here.
You need to consider how to set up your iptables rules (the first rule gets hit when the condition is fulfilled, and any subsequent rules are triggered when the condition you are checking for is NOT fulfilled). This neatly implements the logical AND.
iptables -t mangle -A INPUT -m string --string "pattern1" --algo bm -j MARK --or-mark 0x1
iptables -t mangle -A INPUT -m string ! --string "pattern2" --algo bm -j MARK --and-mark 0xFFFFFFFE
[...]
Please note the ! in the second and any subsequent rules which inverts the condition as well as the --and-mark and the inverted bitmask that clears out the desired bit on a match.
Then, for filtering you check whether or not the mark is there:
iptables -A INPUT -m mark --mark 0x1/0x1 -j DROP
The key lies in the order in which the chains in the different tables are processed. What you are doing here is check a given packet for several strings as it traverses the mangle table (selected by issuing -t mangle
to iptables) which is processed before the filter table (no -t filter
needed, because that is the default table) is processed.
After your conditions have been checked you know for certain that you have found all n conditions within the given packet (the mark is still there in this case) so the rule in the filter table gets hit and drops the packet.
Let's assume you want to check for the following three strings:
foobar
roflbtc
cafeface
You'd have to set up the rules like this:
iptables -t mangle -A INPUT -m string --string "foobar" --algo bm -j MARK --or-mark 0x1
iptables -t mangle -A INPUT -m string ! --string "roflbtc" --algo bm -j MARK --and-mark 0xFFFFFFFE
iptables -t mangle -A INPUT -m string ! --string "cafeface" --algo bm -j MARK --and-mark 0xFFFFFFFE
Now, if you have a packet containing all these strings, you are going to get this:
-m string --string "foobar"
is a hit ---> Set mark 0x1 on the packet
-m string ! --string "roflbtc"
is a miss ---> The mark remains unchanged
-m string ! --string "cafeface"
is a miss ---> The mark remains unchanged
Now the packet finally reaches the rule
iptables -A INPUT -m mark --mark 0x1/0x1 -j DROP
Since the mark is present, the rule is a match and the packet gets dropped.
However, what happens if e. g. the second string is missing?
-m string --string "foobar"
is a hit ---> Set mark 0x1 on the packet
-m string ! --string "roflbtc"
is a hit (the string is NOT there!) ---> Remove mark 0x1 from the packet
-m string ! --string "cafeface"
is a miss ---> The mark remains unchanged
Like above the packet is going to reach the aforementioned drop rule, however, -m mark --mark 0x1/0x1
is a miss, because the mark isn't there. As a consequence, the packet can pass the filter.
Let's also examine what happens if the first string is missing:
-m string --string "foobar"
is a miss ---> The mark is NOT set
-m string ! --string "roflbtc"
is a miss ---> The mark remains unchanged
-m string ! --string "cafeface"
is a miss ---> The mark remains unchanged
Again, because one of the conditions are not met, the mark doesn't get set in the first place so if the drop rule is finally reached, it is a miss and again the packet may pass.
This is an easy way to link condition checks, and depending on how you set or clear the marks, you can implement virtually any logical operation - plus since the mark value is 32 bits wide, that makes up to 32 conditions that you can check for this way.