This shows you the differences between two versions of the page.
— | linux:networking:firewall_and_routing [2011/10/04 21:58] (current) – created Nathan Martin | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Firewall and Advanced Routing Under Linux ====== | ||
+ | |||
+ | ===== Introduction ===== | ||
+ | This page content was cloned from [[http:// | ||
+ | |||
+ | ==== Objective ===== | ||
+ | |||
+ | To present different tools and functionalities present on [[http:// | ||
+ | |||
+ | |||
+ | |||
+ | ==== Requirements ==== | ||
+ | |||
+ | It is assumed that the author has basic knowledge about [[http:// | ||
+ | |||
+ | It is recommended that the reader follow the article together with each tool´s manual in hand for reference. | ||
+ | |||
+ | |||
+ | |||
+ | ====== Firewall: IP Tables ====== | ||
+ | |||
+ | The current tool for firewall under Linux is [[http:// | ||
+ | |||
+ | IP Tables behavior is based on pairs of //rules// and // | ||
+ | |||
+ | The main tool is the command '' | ||
+ | |||
+ | # man iptables | ||
+ | |||
+ | The next sections will explain how the explained behavior works inside iptables and how to configure it. | ||
+ | |||
+ | |||
+ | ===== Tables ===== | ||
+ | |||
+ | The name '' | ||
+ | |||
+ | ^ Table ^ Meaning ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | Thus, depending on what you wish to do with a certain packet, there is an adequate table for that. | ||
+ | |||
+ | |||
+ | ===== Chains ===== | ||
+ | |||
+ | In IP Tables, there are several //chains// glued to each table and each one associated a certain kind of traffic. Here they are: | ||
+ | |||
+ | ^ Chain ^ Meaning ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | It is also possible to create personalized chains, topic that will not be covered on this article. | ||
+ | |||
+ | The '' | ||
+ | |||
+ | net.ipv4.ip_forward=1 | ||
+ | |||
+ | to allow [[wp> | ||
+ | |||
+ | # sysctl -w net.ipv4.ip_forward=1 | ||
+ | |||
+ | This can be automated by adding the following line to '' | ||
+ | |||
+ | net.ipv4.ip_forward=1 | ||
+ | |||
+ | **Note:** [[http:// | ||
+ | |||
+ | |||
+ | ===== Data Flow Diagram ===== | ||
+ | |||
+ | The data flow inside each table / chain inside the Linux kernel is described by the graph below. In each box, it is labeled the acting chain and the names of the valid tables for each chain. Traffic flows through each one of the tables in series for each chain. For example, at '' | ||
+ | |||
+ | Incoming | ||
+ | | ||
+ | | | ||
+ | | | ||
+ | V | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | | | ||
+ | | | | ||
+ | | ||
+ | +- Decision -+ | | ||
+ | | | | | ||
+ | | | | | ||
+ | V V | | ||
+ | Local Remote | ||
+ | Destination | ||
+ | | | | | ||
+ | | | | | ||
+ | V V | | ||
+ | +--------+ | ||
+ | | INPUT | | FORWARD | | | ||
+ | +--------+ | ||
+ | | mangle | | mangle | ||
+ | | filter | | filter | ||
+ | +--------+ | ||
+ | | | | | ||
+ | | | | | ||
+ | V | | | ||
+ | Local | | | ||
+ | | ||
+ | | | | | ||
+ | | | | | ||
+ | V | | | ||
+ | | ||
+ | | ||
+ | | | | | ||
+ | | | | | ||
+ | V | | | ||
+ | +--------+ | ||
+ | | OUTPUT | | ||
+ | +--------+ | ||
+ | | raw | ||
+ | | mangle | | ||
+ | | nat | ||
+ | | filter | | ||
+ | +--------+ | ||
+ | | | | | ||
+ | | +-------------+ | ||
+ | | | POSTROUTING | Local | ||
+ | +----> +-------------+ --> Traffic | ||
+ | | ||
+ | | ||
+ | | ||
+ | | | ||
+ | | | ||
+ | V | ||
+ | Outgoing | ||
+ | Traffic | ||
+ | |||
+ | Let´s take as an example an access from the machine to itself. Traffic will flow sequentially by each one of the following chains / tables: | ||
+ | |||
+ | - Packet generated by a local process / kernel | ||
+ | - Routing decision | ||
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
+ | - Routing decision | ||
+ | - '' | ||
+ | - '' | ||
+ | - Packet delivered to a local process / kernel | ||
+ | |||
+ | Thus, if one wish to allow such traffic, there must have no rule / action pair prohibiting the traffic in any of the above cases. | ||
+ | |||
+ | ===== Rules ===== | ||
+ | |||
+ | Given a certain chain / table, it is necessary to use //rules// to select in which packets a certain action will take place. Not all rules applies to all chains. For example, a rule specifying the outgoing interface of a packet does not apply to the chain '' | ||
+ | |||
+ | There are general rules (referred as '' | ||
+ | |||
+ | General rules are: | ||
+ | |||
+ | ^ Rule ^ Description ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | Match extensions will be treated to follow. | ||
+ | |||
+ | ===== Target ===== | ||
+ | |||
+ | A target specify the action to be taken when a certain packet match a certain rule. This target can be one of the default (should be available on all kernels) or one target extension (refer to '' | ||
+ | |||
+ | The default targets are: | ||
+ | |||
+ | ^ Target ^ Meaning ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | In practice, most times you will be using either '' | ||
+ | |||
+ | |||
+ | ===== Writing rules ===== | ||
+ | |||
+ | According to '' | ||
+ | |||
+ | To add a single rule (at the end of the existing ones), follow this general form: | ||
+ | |||
+ | # iptables -t [TABLE] -A [CHAIN] [RULES] -j [TARGET] | ||
+ | |||
+ | Where: | ||
+ | |||
+ | ^ Variable ^ Meaning ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | For example, to allow the network 192.168.0.0/ | ||
+ | |||
+ | # iptables -t filter -A FORWARD -s 192.168.0.0/ | ||
+ | |||
+ | Follow the data flow on the above data flow graph to note that this rule would not be enough, since the packet flows through many other table / chains. | ||
+ | |||
+ | In the case that no rule matches a certain traffic, there is a way to set up a default policy to a certain table / chain. This default policy configure a target to be executed in the case no other terminative rule on the same target / table match the traffic. To define a default policy try: | ||
+ | |||
+ | # iptables -t [TABLE] -P [CHAIN] [TARGET] | ||
+ | |||
+ | For example: | ||
+ | |||
+ | # iptables -t raw -P OUTPUT ACCEPT | ||
+ | |||
+ | This rule will allow free traffic by default on the table raw, chain OUTPUT | ||
+ | |||
+ | Up to here, resources to control traffic are limited. The neTABELAxt topic will cover some extensions that give much more control / power over the firewall. | ||
+ | |||
+ | |||
+ | ==== Match extensions ==== | ||
+ | |||
+ | As said previously, there are match extensions that allow to better select packets. The general form is: | ||
+ | |||
+ | ... -m [NAME] [OPTIONS] | ||
+ | |||
+ | where | ||
+ | |||
+ | ^ Variable ^ Meaning ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | Please reffer to the topic '' | ||
+ | |||
+ | === Examples === | ||
+ | |||
+ | Here are presented some common match extensions, that will be used most of the times. | ||
+ | |||
+ | == tcp == | ||
+ | |||
+ | Allow to specify a certain source / destination TCP port: | ||
+ | |||
+ | ... -m tcp --dport www | ||
+ | |||
+ | This will match TCP connections which destination port is www (number 80, please reffer to ''/ | ||
+ | |||
+ | == udp == | ||
+ | |||
+ | Allow to specify a certain source / destination UDP port: | ||
+ | |||
+ | ... -m udp --dport www | ||
+ | |||
+ | === Connection tracking === | ||
+ | |||
+ | IP Tables is a so called [[wp> | ||
+ | |||
+ | # iptables -t filter -A FORWARD -d [WEB_SERVER] -i [EXTERNAL_INTERFACE] -o [INTERNAL_INTERFACE] -j ACCEPT | ||
+ | # iptables -t filter -A FORWARD -m state --state RELATED, | ||
+ | |||
+ | The first rule allows external traffic coming via '' | ||
+ | |||
+ | The connection tracking system from netfilter has many different modules, being able to track specific protocols, such as FTP, to allow related (data) connections to work with no additional rule or the need of a proxy server. In the case where no connection is defined (eg. UDP or ICMP) after the traffic goes, a window is opened to allow its return. Thus, everything works like if there was actually an "UDP connection" | ||
+ | |||
+ | It is recommended to let a rule similar to the above second one. It is better to have a generic rule "catch all" than writing an specific connection rule for each traffic. Since this rule will not allow traffic if it was not allowed before, it is not security problem to do this. It is also recommended to allow ICMP traffic to flow freely. | ||
+ | |||
+ | Please refer to iptables manual to find out more about connection tracking and more uses of this tool. | ||
+ | |||
+ | ==== Target Extensions ==== | ||
+ | |||
+ | Target extensions allow some specialized actions and packet treatment to be done, such as [[wp> | ||
+ | |||
+ | * **LOG** | ||
+ | This one allow to log (via kernel logging, you can see using the command '' | ||
+ | |||
+ | * **MASQUERADE, | ||
+ | Those are three possibilities of implementing [[wp> | ||
+ | |||
+ | ====== Advanced Routing ====== | ||
+ | |||
+ | Linux has a different approach for routing than other UNIX. The way things are implemented on Linux is more flexible and powerful than traditional ways. Legacy utilities such as '' | ||
+ | |||
+ | Linux advanced routing is implemented in two parts: | ||
+ | |||
+ | - Rules | ||
+ | - [[wp> | ||
+ | |||
+ | It is possible to have multiple routing tables under Linux and the rules indicate when to use each one of them. | ||
+ | |||
+ | |||
+ | ===== Rules ===== | ||
+ | |||
+ | To list existing routing rules, one can try: | ||
+ | |||
+ | # ip rule list | ||
+ | 0: from all lookup local | ||
+ | 32766: from all lookup main | ||
+ | 32767: from all lookup default | ||
+ | |||
+ | Rules are processed in increasing priority (1< | ||
+ | |||
+ | # ip route list table local | ||
+ | local 192.168.1.1 dev eth3 proto kernel | ||
+ | local 200.170.111.237 dev eth0 proto kernel | ||
+ | broadcast 192.168.1.0 dev eth3 proto kernel | ||
+ | broadcast 192.168.2.255 dev eth1 proto kernel | ||
+ | local 200.170.111.236 dev eth0 proto kernel | ||
+ | broadcast 127.255.255.255 dev lo proto kernel | ||
+ | broadcast 200.170.111.239 dev eth0 proto kernel | ||
+ | local 200.170.111.239 dev eth0 proto kernel | ||
+ | local 200.170.111.238 dev eth0 proto kernel | ||
+ | local 200.170.111.233 dev eth0 proto kernel | ||
+ | broadcast 200.170.111.232 dev eth0 proto kernel | ||
+ | local 200.170.111.235 dev eth0 proto kernel | ||
+ | local 201.20.202.11 dev eth0 proto kernel | ||
+ | broadcast 201.6.149.0 dev eth2 proto kernel | ||
+ | local 200.170.111.234 dev eth0 proto kernel | ||
+ | local 192.168.2.1 dev eth1 proto kernel | ||
+ | broadcast 192.168.1.255 dev eth3 proto kernel | ||
+ | broadcast 192.168.2.0 dev eth1 proto kernel | ||
+ | broadcast 201.20.207.255 dev eth0 proto kernel | ||
+ | broadcast 201.20.200.0 dev eth0 proto kernel | ||
+ | broadcast 127.0.0.0 dev lo proto kernel | ||
+ | broadcast 201.6.149.255 dev eth2 proto kernel | ||
+ | local 201.6.149.41 dev eth2 proto kernel | ||
+ | local 127.0.0.1 dev lo proto kernel | ||
+ | local 127.0.0.0/8 dev lo proto kernel | ||
+ | |||
+ | This table is long, but is managed by the kernel itself, thus, do not worry about it. This table contains information regarding local addresses (the ones associated with network interfaces), | ||
+ | |||
+ | In the case the table does not solve a certain destination address (eg. traffic to another machine in this case), Linux kernel look for the next rule with lower priority (higher priority number) to find out a routing solution. In this case, the next rule is the one with priority 32766, which says to go to table '' | ||
+ | |||
+ | # ip route list table main | ||
+ | 200.170.111.232/ | ||
+ | 192.168.2.0/ | ||
+ | 192.168.1.0/ | ||
+ | 201.6.149.0/ | ||
+ | 201.20.200.0/ | ||
+ | default via 201.6.149.1 dev eth2 | ||
+ | |||
+ | This table contain exactly the same information displayed by the '' | ||
+ | |||
+ | # route -n | ||
+ | Kernel IP routing table | ||
+ | Destination | ||
+ | 200.170.111.232 0.0.0.0 | ||
+ | 192.168.2.0 | ||
+ | 192.168.1.0 | ||
+ | 201.6.149.0 | ||
+ | 201.20.200.0 | ||
+ | 0.0.0.0 | ||
+ | |||
+ | So, this table contains the traditional routing information. The last table named '' | ||
+ | |||
+ | The rules and tables described here contain all the traditional routing information. It is possible however to insert new rules and new tables to fit demands of a more complex environment. | ||
+ | |||
+ | |||
+ | |||
+ | ==== Custom Rules ==== | ||
+ | |||
+ | One can for example, add a rule specifying that traffic from a certain source must be routed using a specific routing table: | ||
+ | |||
+ | # ip rule add type unicast from 192.168.4.0/ | ||
+ | |||
+ | This will instruct the kernel to when it finds traffic coming from 192.168.4.0/ | ||
+ | |||
+ | # ip rule list | ||
+ | 0: from all lookup local | ||
+ | 55: from 192.168.4.0/ | ||
+ | 32766: from all lookup main | ||
+ | 32767: from all lookup default | ||
+ | |||
+ | Note that priority number 55 and table number 55 are absolutely arbitrary and have no need to be the same number. These numbers must only make sense to fit your routing needs. | ||
+ | |||
+ | Please look at '' | ||
+ | |||
+ | ===== Tables ===== | ||
+ | |||
+ | Routing tables are identified by numbers from 0 to 255. Tables '' | ||
+ | |||
+ | The existence of a table containing routing rules inside does not imply that it is in use. A table will only be used if there is a rule pointing to it. | ||
+ | |||
+ | Please consult '' | ||
+ | |||
+ | |||
+ | ===== Note ===== | ||
+ | |||
+ | Linux kernel comes with an anti-spoof protection apart from firewall. This protection protects an internal network against external attacks. Depending on the routing situation you need (specially when connected to multiple ISPs) this setting must be disable in order for your routing rules to work. | ||
+ | |||
+ | This option is accessible vis sysctl | ||
+ | |||
+ | net.ipv4.conf.all.rp_filter | ||
+ | |||
+ | which changes configuration for all network interfaces. There is also the possibility to enable / disable by interface (substituting '' | ||
+ | |||
+ | The line: | ||
+ | |||
+ | net.ipv4.conf.all.rp_filter=0 | ||
+ | |||
+ | at ''/ | ||
+ | |||
+ | |||
+ | |||
+ | ====== Integrating Firewall and Routing ====== | ||
+ | |||
+ | One possible routing rule matching filter is '' | ||
+ | |||
+ | # ip rule list | ||
+ | 0: from all lookup local | ||
+ | 33: from all fwmark 0x1 lookup 33 | ||
+ | 32766: from all lookup main | ||
+ | 32767: from all lookup default | ||
+ | |||
+ | In this case, packets marked as 0x1 by the firewall (0x1 is 1 noted in hexa-decimal) to be solved by the table numbered 33. The number 0x1 is absolutely arbitrary. | ||
+ | |||
+ | It is important to know that this mark is local and internal to the Linux kernel and in any way alters the packets. | ||
+ | |||
+ | |||
+ | ===== Marking packets ===== | ||
+ | |||
+ | To mark a packet with iptables, use the target '' | ||
+ | |||
+ | # iptables -t mangle -A PREROUTING -i eth0 -j MARK --set-mark 1 | ||
+ | |||
+ | In this example, all traffic coming through interface eth0 will be marked as 1 (an arbitrary number). After this, it is possible to include a routing rule matching these packets, as explained on the previous topic. Thus, this iptables rule and the routing rule will make specific routing for packets coming by interface eth0. | ||
+ | |||
+ | Note by the above iptables fluxogram that the mark is being done before routing table. In this case, traffic is entering the machine, thus the '' | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Connections ==== | ||
+ | |||
+ | It is also possible to mark all packets related to a connection. The target '' | ||
+ | |||
+ | # iptables -t mangle -A OUTPUT -d SERVER -j CONNMARK --set-mark 1 | ||
+ | # iptables -t mangle -A OUTPUT -m connmark --mark 1 -j MARK --set-mark 1 | ||
+ | |||
+ | The first rule mark all desired connections. The second rule uses the match extension '' | ||