linux_iptables_inside

Kernel

framework-table

Above lost conntrack table which is important for nat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
                                   netfilter hooks

+-----------> local +-----------+
| process |
| |
| |
| |
| v
MANGLE +-------------+--------+
FILTER | | +----------------------+ RAW
SECURITY | input | | | conntrack
SNAT | | | output | MANGLE
conntrack | | | |
+------+---------------+ | | DNAT
^ +-------+--------------+ routing
| | FILTER
| | SECURITY
| +---------------------+ | +-------------+
+-----------+ | | +-------> | |
+--> |pre routing+---- route -----> | forward | |post routing +---->
| | lookup | +------------> | |
+-----------+ +---------------------+ +-------------+

RAW MANGLE MANGLE
conntrack FILTER SNAT
conntrack
MANGLE SECURITY
DNAT
routing
# Security means selinux rules

framework
从逻辑上来说每个Hook Point, 可以有不同的Table,并且Table是有固定优先级的,在同一个Hook的同一个Table 内,rule 是按照添加的先后顺序执行的,但是实现上iptable的每个表只注册了一个公共entry(callback)在某些链表中,也就是虽然每个iptable table支持在不同的point(input,output etc),但是都是统一的入口函数, 然后在这个统一的函数如找到具体是point的rules。

Concept

iptables实现防火墙功能的原理:在数据包经过内核的过程中有五处关键地方,分别是PREROUTING、INPUT、OUTPUT、FORWARD、POSTROUTING(chain),称为钩子函数,iptables这款用户空间的软件可以在这5处地方写规则,对经过的数据包进行处理,规则一般的定义为“如果数据包头符合这样的条件,就这样处理数据包”, iptables中定义有5条链,说白了就是上面说的5个钩子函数,因为每个钩子函数中可以定义多条规则,每当数据包到达一个钩子函数时,iptables就会从钩子函数中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据该条规则所定义的方法处理该数据包;否则iptables将继续检查下一条规则,如果该数据包不符合钩子函数中任一条规则,iptables就会根据该函数预先定义的默认策略来处理数据包

iptables中定义的表,分别表示提供的功能,有filter表(实现包过滤, deny, drop etc)、nat表(实现网络地址转换)、mangle表(实现包修改)、raw表(实现数据跟踪),这些表具有一定的优先级, table priority is fixed at each Hook point.

raw–>mangle–>nat–>filter

Inside each table, rules are executed by order one by one

  • insert (head)
  • append (tail)

iptables command

iptables [-t 表] [操作命令] [链] [规则匹配器] [-j 目标动作]

Table
table

Operation
op

Condition
con

Target:

target

ACCEPT will terminate rule matching in the same table?
REJECT, DROP will terminate all, stop here.
one more target: 用户自定义的链名:跳转到这条链下,进行匹配

PS:

  • 目标地址转换一般在PREROUTING链上操作
  • 源地址转换一般在POSTROUTING链上操作
  • if without -t, default use filter table

example

show commands

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# Please NOTE this may not show all rules!!! as user may create custom chain like docker does
# show all rules at DOCKER chain(can be used as target)
$ iptables -nv -L PREROUTING -t nat
Chain PREROUTING (policy ACCEPT 24 packets, 2840 bytes)
pkts bytes target prot opt in out source destination
6 272 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}...";iptables -nvL DOCKER -t $table;done

# show all rules at PREROUTING chain
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}..."; iptables -nvL PREROUTING -t $table;done
# show command used by iptable to add the rule
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}..."; iptables -S PREROUTING -t $table;done

# show all rules at INPUT chain
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}..."; iptables -nvL INPUT -t $table;done
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}..."; iptables -S INPUT -t $table;done

# show all rules at FORWARD chain
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}..."; iptables -nvL FORWARD -t $table;done
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}..."; iptables -S FORWARD -t $table;done

# show all rules at OUTPUT chain
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}..."; iptables -nvL OUTPUT -t $table;done
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}..."; iptables -S OUTPUT -t $table;done

# show all rules at POSTROUTING chain
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}..."; iptables -nvL POSTROUTING -t $table;done
$ for table in raw mangle nat filter security; do printf '=%.0s' {1..50}; echo -e "\n${table}..."; iptables -S POSTROUTING -t $table;done


######################## Another way to show all rules#######################################################################################
# show all nat table at different chains(target or hook point)
$ iptables -nvL -t nat
# show command to replay the rule
$ iptables -S -t nat

$ iptables -nvL -t filter
$ iptables -nvL -t security
$ iptables -nvL -t raw
$ iptables -nvL -t mangle

# show nat table at given chain(target)
$ iptables -nvL PREROUTING -t nat
# show command to replay the rule
$ iptables -S PREROUTING -t nat
######################## Another way to show all rules#######################################################################################

show iptable rules in particular network namespace

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# show all rules in mangle under network namespace bb2fdae4-44bf-40a3-8acc-dfb554d79d76
$ alias nsc='ip netns exec'

root@dev:~/ping# nsc bb2fdae4-44bf-40a3-8acc-dfb554d79d76 iptables -nvL -t mangle
Chain PREROUTING (policy ACCEPT 111K packets, 5802K bytes)
pkts bytes target prot opt in out source destination
1788K 399M DIVERT all -- * * 0.0.0.0/0 0.0.0.0/0 socket
8121 268K DIVERT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 0

Chain INPUT (policy ACCEPT 1792K packets, 399M bytes)
pkts bytes target prot opt in out source destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 2614K packets, 196M bytes)
pkts bytes target prot opt in out source destination

Chain POSTROUTING (policy ACCEPT 2614K packets, 196M bytes)
pkts bytes target prot opt in out source destination

Chain DIVERT (2 references)
pkts bytes target prot opt in out source destination
1796K 399M MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0x1
1796K 399M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0


Only show PREROUTING rules in mangle table

root@dev:~/ping# nsc bb2fdae4-44bf-40a3-8acc-dfb554d79d76 iptables -nv -L PREROUTING -t mangle
Chain PREROUTING (policy ACCEPT 111K packets, 5806K bytes)
pkts bytes target prot opt in out source destination
1789K 399M DIVERT all -- * * 0.0.0.0/0 0.0.0.0/0 socket
8121 268K DIVERT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 0

DIVERT is self-defined chain like a hook point

root@dev:~/ping# nsc bb2fdae4-44bf-40a3-8acc-dfb554d79d76 iptables -nv -L DIVERT -t mangle
Chain DIVERT (2 references)
pkts bytes target prot opt in out source destination
1797K 400M MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0x1
1797K 400M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0

show rules with number
root@dev:~/ping# nsc bb2fdae4-44bf-40a3-8acc-dfb554d79d76 iptables -nv -L DIVERT -t mangle --line-number
Chain DIVERT (2 references)
num pkts bytes target prot opt in out source destination
1 1798K 400M MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0x1
2 1798K 400M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0


root@dev:~/ping# nsc bb2fdae4-44bf-40a3-8acc-dfb554d79d76 iptables -nvL -t mangle --line-number
Chain PREROUTING (policy ACCEPT 111K packets, 5811K bytes)
num pkts bytes target prot opt in out source destination
1 1791K 400M DIVERT all -- * * 0.0.0.0/0 0.0.0.0/0 socket
2 8121 268K DIVERT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 0

Chain INPUT (policy ACCEPT 1795K packets, 399M bytes)
num pkts bytes target prot opt in out source destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 2618K packets, 197M bytes)
num pkts bytes target prot opt in out source destination

Chain POSTROUTING (policy ACCEPT 2618K packets, 197M bytes)
num pkts bytes target prot opt in out source destination

Chain DIVERT (2 references)
num pkts bytes target prot opt in out source destination
1 1799K 400M MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0x1
2 1799K 400M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0


# Delete rule by rule number
root@dev:~/ping# nsc bb2fdae4-44bf-40a3-8acc-dfb554d79d76 iptables -D PREROUTING 1 -t mangle

root@dev:~/ping# nsc bb2fdae4-44bf-40a3-8acc-dfb554d79d76 iptables -nvL -t mangle --line-number
Chain PREROUTING (policy ACCEPT 93 packets, 5580 bytes)
num pkts bytes target prot opt in out source destination
1 8121 268K DIVERT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 0

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 52 packets, 3120 bytes)
num pkts bytes target prot opt in out source destination

Chain POSTROUTING (policy ACCEPT 52 packets, 3120 bytes)
num pkts bytes target prot opt in out source destination

Chain DIVERT (1 references)
num pkts bytes target prot opt in out source destination
1 1799K 400M MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0x1
2 1799K 400M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0

set command

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# flush all rules in filter table(default)
$ iptables -F

# flush all rules in mangle table
$ iptables -F -t mangle

# set default policy in filter table for INPUT chain
$ iptables -P INPUT DROP

# 阻止来自IP地址x.x.x.x eth0 tcp的包
$ iptables -A INPUT -i eth0 -p tcp -s x.x.x.x -j DROP

# check rule exist or not
$ iptables -C OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
# if no rule $? == 1, otherwise 0
$ echo $?

# 允许所有来自外部的SSH连接请求,即只允许进入eth0接口,并且目标端口为22的数据包
$ iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
$ iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

save and restore

使用iptables-save可以保存到特定文件中

1
$ iptables-save >/etc/sysconfig/iptables_save

使用iptables-restore可以恢复规则

1
$ iptables-restore</etc/sysconfig/iptables_save

iptables match with module condition

As basic iptables only supports protocol, saddr, sport etc conditions when matching, so some extensions add more conditions when matching packet, these extensions are organized as module like (time, limit, socket, ttl, state, mark etc)

1
2
3
4
kernel files
net/netfilter/xt_time.c
net/netfilter/xt_socket.c
net/netfilter/xt_state.c

addrtype 地址类型

Format:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[!] --src-type type[,...]      Match source address type
[!] --dst-type type[,...] Match destination address type
--limit-iface-in Match only on the packet's incoming device
--limit-iface-out Match only on the packet's outgoing device

UNSPEC
UNICAST
LOCAL
BROADCAST
ANYCAST
MULTICAST
BLACKHOLE
UNREACHABLE
PROHIBIT
THROW
NAT

Here are some examples

$ iptables -A OUTPUT -m addrtype --src-type LOCAL -j ACCEPT
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere ADDRTYPE match src-type LOCAL

$ iptables -A INPUT -m addrtype --dst-type LOCAL -j ACCEPT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere ADDRTYPE match dst-type LOCAL

LOCAL means the address is one the interface, say host has eth0(10.172.1.32), if address is 10.172.1.32 means LOCAL.

limit限制流量:

1
2
3
4
5
6
# -m limit --limit 1000/s               设置最大平均匹配速率
# -m limit --limit-burst 15 设置一开始匹配的最大数据包数量
# -m limit --limit 5/m --limit-burst 15 表示一开始能匹配的数据包数量为15个,每匹配到一个,limit-burst的值减1,所以匹配到15个时,该值为0,以后每过12s,limit-burst的值会加1,表示又能匹配1个数据包

$ iptables -A INPUT -i eth0 -m limit --limit 5/m --limit-burst 15 -j ACCEPT
$ iptables -A INPUT -i eth0 -j DROP

要点

  • –limit-burst的值要比–limit的大
  • limit本身没有丢弃数据包的功能,因此,需要第二条规则一起才能实现限速的功能

time :在特定时间内匹配

1
2
3
4
5
6
7
8
# -m time 	说明
# --monthdays day1[,day2] 在每个月的特定天匹配
# --timestart hh:mm:ss 在每天的指定时间开始匹配
# --timestop hh:mm:ss 在每天的指定时间停止匹配
# --weekdays day1[,day2] 在每个星期的指定工作日匹配,值可以是1-7

$ iptables -A INPUT -i eth0 -m time --weekdays 1,2,3,4 -jACCEPT
$ iptables -A INPUT -i eth0 -j DROP

ttl:匹配符合规则的ttl值的数据包

1
2
3
4
5
6
# 参数 	说明
# --ttl -eq 100 匹配TTL值为100的数据包
# --ttl -gt 100 匹配TTL值大于100的数据包
# --ttl -lt 100 匹配TTL值小于100的数据包

$ iptables -A OUTPUT -m ttl --ttl-eq 100 -j ACCEPT

multiport:匹配离散的多个端口

iptables –dport and –sport 只支持连续的端口.

1
2
3
4
5
6
7
8
9
10
# 参数 	说明
# --sports port1[,port2,port3] 匹配源端口
# --dports port1[,port2,port3] 匹配目的端口
# --ports port1[,port2,port3] 匹配源端口或目的端口

# 连续的端口
$ iptables -A INPUT --sports 5000:5050 -j DROP

# 离散的端口
$ iptables -A INPUT -m multiport --sports 22,80,8080 -j DROP

state:匹配指定的状态数据包

1
2
3
4
# 参数 	说明
# --state value value可以为NEW、RELATED(有关联的)、ESTABLISHED、INVALID(未知连接)

$ iptables -A INPUT -m state --state NEW,ESTABLISHED -j ACCEPT

mark:匹配带有指定mark值的数据包

1
2
3
4
# 参数 	说明
--mark value 匹配mark标记为value的数据包

$ iptables -t mangle -A INPUT -m mark --mark 1 -j DROP

mac:匹配特定的mac地址

1
$ iptables -A FORWARD -m mac --mac-source 00:0C:24:FA:19:80 -j DROP

statistic: 负载均衡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--mode mode
Set the matching mode of the matching rule, supported modes are `random and nth`.

[!] --probability p
Set the probability for a packet to be randomly matched. It only works with the random mode. p
must be within 0.0 and 1.0. The supported granularity is in 1/2147483648th increments.

[!] --every n
Match one packet every nth packet. It works only with the nth mode (see also the --packet option).

--packet p
Set the initial counter value (0 <= p <= n-1, default 0) for the nth mode.

# RR
$ iptables -A PREROUTING -t nat -d 172.17.64.8 -m statistic --mode nth --every 2 --packet 0 -j DNAT --to-destination 192.168.100.160
$ iptables -A PREROUTING -t nat -d 172.17.64.8 -m statistic --mode nth --every 2 --packet 1 -j DNAT --to-destination 192.168.100.161

# random
$ iptables -A PREROUTING -t nat -d 172.17.64.8 -m statistic --mode random --probability 0.5 -j DNAT --to-destination 192.168.100.160
$ iptables -A PREROUTING -t nat -d 172.17.64.8 -m statistic --mode random --probability 0.5 -j DNAT --to-destination 192.168.100.161

iptables with extended target modules

Basically, iptables is very simple, only support ACCEPT, DROP, more targets are provided by modules
Here are frequently used target.

  • BALANCE
    This allows you to DNAT connections in a round-robin way over a given range of destination addresses.

    1
    $ iptables -A PREROUTING -t nat -j BALANCE --to-destination 192.168.1.1-192.168.1.10
  • DNAT

    1
    2
    $ iptables -A PREROUTING -t nat -j DNAT --to-destination 192.168.1.1-192.168.1.10
    $ iptables -A PREROUTING -t nat -j DNAT --to-destination 192.168.1.1-192.168.1.10:1000-2000

    Only valid in nat table at PREROUTING and OUTPUT chains

  • LOG
    Turn on kernel logging of matching packets

    1
    2
    $ iptables -A PREROUTING -t nat -j LOG --log-level info
    $ iptables -A PREROUTING -t nat -j LOG --log-level info --log-prefix tag1
  • MARK
    This is used to set the netfilter mark value associated with the packet. It is only valid in the mangle table
    iptables -A PREROUTING -t mangle -j MARK –set-mark 0x10

  • MASQUERADE
    This target is only valid in the nat table, in the POSTROUTING chain, like SNAT but use address of out dev as the source ip.

    1
    $ iptables -A POSTROUTING -t nat -j MASQUERADE
  • REDIRECT(change the receiving ip(port is optional))
    This target is only valid in the nat table, in the PREROUTING and OUTPUT chains, and user-defined chains which are only called from those chains. It redirects the packet to the machine itself by changing the destination IP to the primary address of the incoming interface, special DNAT without providing dest by admin!!

    1
    2
    3
    4
    # --to-ports port[-port]
    # This specifies a destination port or range of ports to use

    $ iptables --table nat --append PREROUTING --protocol tcp --dport 80 --jump REDIRECT --to-ports 8080
  • REJECT
    This is used to send back an error packet in response to the matched packet: otherwise it is equivalent to DROP so it is a terminating TARGET, ending rule traversal. This target is only valid in the INPUT, FORWARD and OUTPUT chains, and user-defined chains which are only called from those chains

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # --reject-with type
    # The type given can be
    # icmp-net-unreachable
    # icmp-host-unreachable
    # icmp-port-unreachable
    # icmp-proto-unreachable
    # icmp-net-prohibited
    # icmp-host-prohibited or
    # icmp-admin-prohibited (*)
  • SNAT
    This target is only valid in the nat table, in the POSTROUTING chain

    1
    # --to-source ipaddr[-ipaddr][:port-port]
  • comment to a rule
    For a single rule, you can add 256 characters for it to explain what is used for!

    1
    # -m comment --comment "comment for this rule"

FAQ

negative one condition add ! before it

1
2
$ iptables -t nat -I POSTROUTING  -s 172.17.0.0/16 ! -o  docker0 -j LOG --log-level info
$ iptables -t nat -I POSTROUTING ! -s 172.17.0.0/16 ! -o docker0 -j LOG --log-level info

what’s the rule order in one Chain

Let’s say there are several rules in one Chain, if the first rule doesn’t match, check next one, what about the rule matches, should we go to check next rule depends on the action of the matched rule.

1
2
3
4
- ACCEPT:           check next one in the chain
- REJECT/DROP: NOT check next one, return out of iptables
- SNAT/DANT: after SNAT or DNAT, check next one in the chain
- RETURN: just jump out the Chain, next one in this chain is not checked, check next chain

what’s conntrack table

nat is stateful, that means you should save info after nat, conntrack table is actually flow table, the initial use is for NAT, as when you do SNAT
after post routing, you need to save the 5 tuples to a flow entry
orig: src, dst, src_port, dst_port, protocol
nat change: m_src, dst, m_src_port, dst_port, protocol,
when reply packet comes back, it should match the nat_change port, then do DNAT
then goes routing.

In order to support this, conntrack table was introduced, it insert some callbacks
at NF_HOOK POINT with different priority.

let’s explain how conntrack fit the example, when you do SNAT after POSTROUTING, one entry is create
at conntrack table, when reply packet comes back, as conntrack table is examined before nat table, hence
we found a matched entry in conntrack table, will never check nat table at all at PREROUTING, skip nat table but check other table if insert rule at PREROUTING

Note: now conntrack is not only used for nat, but for all connection, even without NAT, you can also delete/create/update entry in this table by $conntrack command

show command used for each rule

dump the command used for all rules with

1
2
3
4
5
6
7
8
$ iptables-save
...
-A PREROUTING -j LOG --log-prefix nat-pre-jason --log-level 6
-A PREROUTING -d 172.17.0.1/32 -j LOG --log-prefix nat-pre --log-level 6
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN

how custom chain is used

custom chain is similar like other chains(INPUT, OUTPUT), belongs to a table(filter, nat etc) you can create rules in it, but it has some difference

  • must create custom chain before creating rule in it, unlike other chains, they are kernel built-in chains
  • custom chain has no fixed hook point unlike other built-in chains have fixed hook point in kernel, custom chain only works when a rule in other built-in chain refers to it by -j CUSTOM_CHAIN.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# create custom chain
$ iptables -t filter -N WEB_CHAIN
$ iptables --list
...
Chain WEB_CHAIN (0 references)
target prot opt source destination

# create a rule in the chain
$ iptables -t filter -I WEB_CHAIN -s 1.1.1.1 -j DROP
$ iptables -t filter -nvL WEB_CHAIN
Chain WEB_CHAIN (0 references)
pkts bytes target prot opt in out source destination
0 0 DROP all -- * * 1.1.1.1 0.0.0.0/0

# other rule refer to custom chain set target as custom chain
$ iptables -t filter -I INPUT -p tcp --dport 80 -j WEB_CHAIN

$ iptables -t filter -nvL INPUT
Chain INPUT (policy ACCEPT 154 packets, 11509 bytes)
pkts bytes target prot opt in out source destination
0 0 WEB_CHAIN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80

$ iptables -t filter -nvL WEB_CHAIN
Chain WEB_CHAIN (1 references)----> one reference
pkts bytes target prot opt in out source destination
0 0 DROP all -- * * 1.1.1.1 0.0.0.0/0

ref