Before continuing you have to understand how packets are processed by netfilter/iptables framework. Firewall rules are data driven language, but actually, the things are very simple. All the packets traverse different parts of the Linux kernel. At certain points those packets are stopped (figuratively speaking) and set of rules is "executed" that can alter, drop or pass packet. If packet is passed (or modified and passed) it goes to the other parts of the kernel where potentially another set of rules is invoked.
The points where packets are "stopped" are chains, PREROUTING, INPUT, FORWARD, POSTROUTING, OUTPUT. In each chain there are different tables, but I'll ignore those for the moment as they are not important for this post.
Set of rules at each point (chain) is added or deleted using iptables command. The iptables command needs an argument that defines in which chain rule is added. That argument is option -A after which name of the chain follows. For example, to add something to INPUT chain, you would write:
iptables -A INPUT ...
To achieve that functionality, just write the rule as follows:if (src(ip) == 192.168.1.1) {do_something_with_packet;}
iptables -A INPUT -s 192.168.1.1 do_something_with_packetThe part do_something_with_packet I'll explain later, but basically this is a part that will do something useful with the packet on which this rule is executed.
Now, what if you want to add additional constraint, e.g. destination address is 192.168.1.2, i.e.
Well, what you'll write is the following:if (src(ip) == 192.168.1.1 and dst(ip) == 192.168.1.2) {do_something_with_packet;}
iptables -A INPUT -s 192.168.1.1 -d 192.168.1.2 do_something_with_packeteasy, isn't it? All the constraint you wish to bind with operator AND are just written one after another. Operator AND is implicit. Ok, now you can ask: But if I want to have OR, what to do then? For example, something like the following:
Believe it or not, it's simple, write it like this:if (src(ip) == 192.168.1.1 or dst(ip) == 192.168.1.2) {do_something_with_packet;
}
iptables -A INPUT -s 192.168.1.1 do_something_with_packetI suppose that you figured it that when you add iptables one after the other, they are bound by OR, while, when you write constraints in a single command they are bound by AND. Alternatively speaking, reading from left to right is AND, and from top to bottom is OR.
iptables -A INPUT -d 192.168.1.2 do_something_with_packet