2012年2月6日 星期一

七個有意思的 iptables 用法


譯者:Nica < nicaliu at gmail dot com >
.
iptables 是一套含括在最新 Linux 分支套件裡的防火牆,網路上已經有相當多關於它的的教戰守則。
.
它是使用者層級的一套應用,讓系統管理者能夠組態 Linux kernel 防火牆 (會是以各種不同的 Netfilter 模組實作) 所提供的表單,並儲存它的 chains 與 rules。不同的 kernel 模組與程式使用的是不同的協定;iptables 應用在 ipv4 上、ip6tables 應用在 ipv6 上、arptables 應用在 ARP 上,而 ebtables 則特指定為 Ethernet frames 所用。
.
iptables 需要較高權限才能操作,因此必須由 root 使用者的身份執行,否則無法使用。在絕大多數 linux 系統上,iptables 安裝在 /usr/sbin/iptables 裡,且擁有自已的 man page 文件,在已安裝的情況下 man iptables 就能開啟。
.
要瞭解 iptables 的基本用法,建議參考 Ubuntu 指導手冊:
.
這裡,我要講的是這個指令的一些特別用法。
.
【任務一:封鎖已知的問題主機,讓它到不了你的機器】
wget -qO – http://infiltrated.net/blacklisted|awk ‘!/#|[a-z]/&&/./{print “iptables -A INPUT -s “$1″ -j DROP”}’
Blacklisted 是編輯過的所有已知問題主機 (僵屍網路botnets、濫發垃圾郵件主機spammer、暴力攻擊主機bruteforcers 等等),會每個小時更新。這個指令會取得清單、幫你建立 rules,若你要它們動階封鎖,在命令列最後加入 |sh 即可。這是一個相當實用的解法,封鎖所有但允許指定的幾個,很多人沒這麼作只是因為手邊沒有一個這樣的 script。
【譯註:此 script 將 rule 寫入正執行中的 iptables,當iptables 重新啟動,這些 rule 將會清除需重新載入】
.
【任務二:有人”敲”了,就打開特定的門(通訊埠)】
knock < host > 3000 4000 5000 && ssh -p
user@host && knock < host > 5000 4000 3000
這個例子裡,看不到直接用到 iptables 什麼,它其實是將 iptables 用在 knockd 組態檔裡,你得安裝它。以下是 sshd (通訊埠22) 的組態範例。
.
[options]
logfile = /var/log/knockd.log
[openSSH]
sequence = 3000,4000,5000
seq_timeout = 5
command = /sbin/iptables -A INPUT -i eth0 -s %IP% -p tcp –dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 5000,4000,3000
seq_timeout = 5
command = /sbin/iptables -D INPUT -i eth0 -s %IP% -p tcp –dport 22 -j ACCEPT
tcpflags = syn
.
【任務三:對通訊埠 80 重導至較高通訊埠】
iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-port 9001
當你希望一般使用者執行較高通訊埠的 daemon,但服務顯示的是標準通訊埠時,這個規則就很好用了。本例中你可以讓一般使用者啟動/停用聆聽 9001 通訊埠的 apache,但他的網站是顯示通訊埠 80。
.
【任務四:讓 proxy 只用在非本地端 LAN 上】
iptables -t nat -A OUTPUT -d ! 10.0.0.0/8 -p tcp –dport 80 -j DNAT –to-destination 10.1.1.123:3128
把 10.0.0.0/8 換成你最大的那個本地端子網路,然後將 10.1.1.123:3128 改成你的 proxy 設定。不過要注意這個設定只有在 proxy 伺服器組態為 passive 才能運作。
Now your firefox transparently proxy’s stuff destined outside your network.. and Doesn’t proxy stuff inside your network. as well as all your other favorite web applications. curl, wget.
.
【任務五:限制只能有 10 個 ssh 連線】
/sbin/iptables -A INPUT -p tcp –syn –dport 22 -m connlimit –connlimit-above 10 -j REJECT
這個命令可讓你限制存取連線某通訊埠在一定的範圍內,對用來限制連線到 Apache 通訊埠的數量也相當好用。
.
【任務六:限制 ssh 每 15 秒內只能有一個 session】
iptables -A INPUT -p tcp -i eth0 -m state –state NEW –dport 22 -m recent –update –seconds 15 -j DROP
iptables -A INPUT -p tcp -i eth0 -m state –state NEW –dport 22 -m recent –set -j ACCEPT
這兩條規則讓 iptables 命令從相同 IP 連結至通訊埠 22 的兩個新連線中間必須間隔 15 秒。若你的防火牆已有自已的 ssh accept 規則,請用它來取代上面 ACCEPT 這行。
.
【任務七:一個命令指定多重指令】
iptables -A INPUT -p tcp -m multiport –dports 22,80,143,6000:6003 -j ACCEPT
Multiport 擴充元件讓使用者可以指定多個通訊埠與範圍,透過一行指令就能建立複雜的規則。
multiport 指令讓你省掉好幾行-要新增修改時就簡單得多,只有一行所需的系統處理也較少。
.
原文出處:

L7-filter Kernel Version HOWTO


Table of Contents

Important links on this page:

What You Need To Get

Kernel Patch

Short version for experts: Apply our kernel patch. Enable the new match option in Netfilter.
Check our kernel compatibility list to see if the Linux version you want to use has been tested.
Use the appropriate kernel patch from the "Layer 7 patches" package to patch[1] the kernel (read the README in the package to determine which patch to use). Set up your kernel as you would otherwise. Now enable the following options (these are correct for Linux 2.6.21.1, but they tend to move around a lot, so you may have to go hunting if you have a different kernel version):
  • "Prompt for development and/or incomplete code/drivers" (under "Code maturity level options")
  • "Network packet filtering framework" (Networking → Networking support → Networking Options)
  • "Netfilter Xtables support" (on the same screen)
  • "Netfilter connection tracking support" (... → Network packet filtering framework → Core Netfilter Configuration), select "Layer 3 Independent Connection tracking"
  • "Connection tracking flow accounting" (on the same screen)
  • And finally, "Layer 7 match support"
  • Optional but highly recommended: Lots of other Netfilter options, notably "FTP support" and other matches. If you don't know what you're doing, go ahead and enable all of them.
Warning: Some users have reported kernel crashes when they using SMP with l7-filter. (Some have also reported that their SMP systems run fine.) If you have a multi-CPU machine, test carefully before putting it into production with l7-filter.
Compile and install the kernel as usual. (Our code may generate warnings about "initialization from incompatible pointer type", ignore them.) Reboot.

1How to patch a source tree

Suppose you have a patch called happy.patch. To apply it, go into the root directory of the source tree you want to patch and run "patch -p1 < happy.patch"

Iptables Setup

First read the README in the package "Layer 7 patches". Depending on your version of iptables, the instructions are different.

iptables 1.4.0 and older

Use the appropriate iptables patch to to patch[1] iptables. Compile iptables, pointing it at your patched kernel source:
  • Run "chmod +x extensions/.layer7-test" (information about file permissions can't be contained in the patch)
  • Then "make KERNEL_DIR=/path/to/patched/kernel_source" (you must have configured your kernel source before this step)
  • And install (as root): "make install KERNEL_DIR=/path/to/patched/kernel_source"

iptables 1.4.1

Don't use this version. There's no reason to and it's difficult to compile.

iptables 1.4.1.1 and newer

Copy libxt_layer7.c and libxt_layer7.man (from the subdirectory of the "Layer 7 patches" package that the README points you to) to the extensions/ directory of your iptables source. Then:
  • "./configure --with-ksource=/path/to/patched/kernel_source" (use the full path)
  • "make"
  • (as root) "make install"

Protocol Definitions (Pattern Files)

These files tell iptables and the kernel how protocol names correspond to regular expressions, e.g. "ftp" means "^220[\x09-\x0d -~]*ftp".
Uncompress the "Protocol Definitions" package and make the resulting directory /etc/l7-protocols.[2]
You should now be ready to actually do stuff.

2Notes for non-conformists

You can also install the patterns in a custom location. If you do this, you need to specify --l7dir before --l7proto when you use l7-filter:

iptables [...] -m layer7 --l7dir /home/bob/patterns --l7proto http [...]

Actually doing stuff

There are three things you may be interested in doing: (1) blocking certain protocols (2) controlling bandwidth use (3) accounting. We cover each of these cases below.
First, a reminder: Just because you're using l7-filter, you don't need to do all of your packet classification using it. It's likely that what you want to accomplish can be at least partially done with less demanding classifiers, such as port matching. For instance, you can probably assume that traffic on TCP port 80 that isn't matched by any P2P patterns is HTTP; you don't need to actually use the HTTP pattern.
l7-filter uses the standard iptables extension syntax. (If you are not familiar with this, it's time to read the documentation at netfilter.org or at least "man iptables".)
iptables [specify table & chain] -m layer7 --l7proto [protocol name] -j [action]
(Or, if you're just interested in accounting, omit "-j [action]".)
For a list of valid protocol names, see the protocols page. You can also add your own protocols.
The only trick is that, in order to do its classification, l7-filter must be able to see all of the relevant traffic. It only sees packets if they go through an l7-filter rule. One way of ensuring this is to use the POSTROUTING chain of the mangle table:
iptables -t mangle -A POSTROUTING -m layer7 --l7proto [etc.]
See this packet flow diagram for details. In some cases, l7-filter can sucessfully match even if it can only see one side of the connection, but in general, this won't work.
If you are using a version of l7-filter earlier than 2.7, you must manually load the ip_conntrack module kernel for l7-filter to work. Newer versions do this automatically.

1. Blocking

Don't. Here's why:
  • l7-filter matching isn't foolproof: there may be both false positives (one protocol can look like another) and false negatives (applications can do obscure things that we didn't count on). Patterns that are known to regularly generate false positives are marked "overmatching" on the protocols page, but others may also do so occasionally.
  • Almost every type of Internet traffic has legitimate uses. For instance, P2P protocols, while widely used to violate copyright, are also an efficient way to distribute open source software and legally free music.
  • Programs can respond to being blocked by port-hopping, switching between TCP and UDP, opening a new connection for every trivial operation, using encryption, or employing other evasion tactics. Trying to block such protocols has consequences on two levels:
    1. In the case of port/protocol-hopping, you make it harder for yourself to identify protocols that already act this way.
    2. You encourage programmers to include these "features" in new programs, making it harder for everyone in the future. For example: In early 2006, Bittorrent started moving towards end-to-end encryption because many networks were either blocking it or severely restricting its bandwidth.
  • l7-filter patterns are not generally designed with blocking in mind. We consider a protocol to be well identified if the identification is useful for controlling its bandwidth. This means, for instance, that for P2P applications, we do not focus on catching connections that are not downloads.
  • Blocking with l7-filter provides no security, since any reasonably determined person can easily circumvent it.
Instead of dropping packets you don't like, we recommend using Linux QoS to restrict their bandwidth usage. If you insist on using l7-filter to drop packets, make sure you have investigated other options first, such as the features of your HTTP proxy (useful for worms).

2. Bandwidth Restriction

To control the bandwidth that a protocol uses, you can use Netfilter to "mark" the packets and QoS to filter on that mark. To mark:
iptables -t mangle -A POSTROUTING -m layer7 --l7proto imap -j MARK --set-mark 3
The number "3" is arbitrary. It can be any integer. Then use tc to filter on that mark (tc is "traffic control", the userspace tool for Linux QoS, part of the iproute2 package):
tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 3 fw flowid 1:3
Did you understand that last command? You can try reading The Linux Advanced Routing and Traffic Control HOWTO for enlightenment. You should do this so that you have some idea what you're doing, but unfortunately, tc is incredibly obtuse and you're likely to wish you just had a canned script. Well, we can help:
These may need to be modified if your setup is significantly different than mine, but it should provide a much better starting point than most other things you are likely to find.
Be prudent when choosing the amount of bandwidth you allow each protocol. Restricting a protocol to an unusably low bandwidth can have similar consequences to blocking it.

3. Accouting

If you just want to keep track of what's in use on your network, simply use the above command without any -j option. For example:

iptables -t mangle -A POSTROUTING -m layer7 --l7proto imap

You can then get statistics by using iptables -L. (See "man iptables" for details.)

More Information

Dealing with FTP, IRC, etc.

Some protocols open child connections to transfer data. FTP is the most familiar example. If you have loaded the ip_conntrack_ftp or nf_conntrack_ftp kernel module, l7-filter will classify FTP and all its child connections as FTP. The same goes for IRC/IRC-DCC, etc.
If you wish to classify the children differently, use the standard iptables "helper" match. You can use "-m --helper ftp" to match ftp child connections. Of course, once you've done this, it's silly to involve l7-filter, at least for the children.

The "unset" and "unknown" matches

l7-filter marks unmatched connections that it is still trying to match as "unset". The first few packets of all TCP connections as well as those of some UDP connections will match this. Similarly, l7-filter marks connections that it has given up trying to match as "unknown". These are matched just like normal protocols:
iptables -A FORWARD -m layer7 --l7proto unset
iptables -A FORWARD -m layer7 --l7proto unknown

The "unset" match is only supported by l7-filter 2.9 and up.

Upgrading the protocol definitions

The protocol definitions are simple text files with a format described in the Pattern-HOWTO. They can be updated as a package or individually.
If you update the protocol definitions, you need to clear the relevant iptables rules and re-enter them. This is because the pattern files are only read by iptables, not directly by the kernel.

Other things to know

  • By default, l7-filter looks at the first 10 packets or 2kB, whichever is smaller. These limits are somewhat conservative. It is well known that some HTTP connections (those that involve large cookies), for instance, need more packets to be matched.
    • You can alter the number of packets at any time through /proc/net/layer7_numpackets. (i.e. "echo 16 > /proc/net/layer7_numpackets".)
    • In l7-filter versions 2.0 and forward, you can alter the number of bytes at module load time: "modprobe xt_layer7 maxdatalen=N" (ipt_layer7 in old versions), where N is in bytes. This should be used cautiously, since performance may decrease drastically with larger data sizes. To prevent you from accidentally bringing down your network, there is an artificial limit of 65536 imposed. If you're sure you know what you're doing, you can remove this limit by editing ipt_layer7.c or xt_layer7.c in the kernel source.
  • It's possible (although rare) for a connection to be matchable by more than one pattern. The patterns are tested in the order you specified with iptables. After a match is made, l7-filter does not continue testing that connection, so changing the order of your rules may change what happens.
  • Sometimes important messages go only to the system log, not the terminal you are working at. Such messages include notifications that regular expressions failed to compile and various things that tc generates. A useful command is "tail -f /var/log/messages".
Please see the FAQ for more information.

How to use simple speedtest in RaspberryPi CLI

  pi@ChunchaiRPI2:/tmp $  wget -O speedtest-cli https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py --2023-06-26 10:4...