基础-Linux的netfilter和iptables

iptables是什么?你为啥要学?

Linux的网络控制模块在内核中,叫做netfilter。而iptables是位于用户空间的一个命令行工具,它作用在OIS7层网络模型中的第四层,用来和内核的netfilter交互,配置netfilter进而实现对网络的控制、流量的转发 。

那iptables既然是个命令行工具,那么是不是有和它类似的其他工具呢?有的,比如的我们常听到的firewalld,还有比较少见的nftables。

毫不夸张的说,整个linux系统的网络安全就是基于netfilter构建起来的。

iptables安装

安装、启动、查看、开启启动

yum install -y iptables-services && \
systemctl enable iptables && \
systemctl start  iptables && \
systemctl status iptables
## systemctl start|restart|reload|stop|status iptables
## 卸载firewalld
systemctl stop firewalld && \
systemctl mask firewalld && \
systemctl status firewalld

iptables默认配置文件位置 /etc/sysconfig/iptables

centos7.x默认用的是 firewalld ,所以你是看不到这个配置文件的

五表五链

iptables中总共有4张表还有5条链,我们可以在链上加不同的规则。

五张表:filter表、nat表、mangle表、raw表、security表

五条链:prerouting、input、output、forward、postrouting

你可以通过iptables -t ${表名} -nL查看表上的链

流量走向

看流量走向前先看下面这个图,这是维基上介绍Linux网络模块的数据包流向图。根据这个图我们可以总结出下面那个图。

下面是流量进入iptables的流转过程,这个图很重要,网上也有很多这种图,我贴上了一个我认为最准确(也不一定对)。

图片

稍微解析一下上图:

  1. 绿分别代表上一小节中提到的iptables的四张表。如果你开启着SELinux,还会多出一个security
  2. 上图左上角写的:incoming packet,表示这是从互联网其他设备中来的流量。它大概的走向是:先经过各个表的prerouting阶段,再经由routing decision(可以理解成查路由表,做路由选择)决定这些流量是应该交由本机处理,还是该通过其他网口forword转发走。
  3. 再看上图中的左上部分,incoming packet在做routing decision之前会先经过nat preroutings阶段,我们可以在这个阶段做dnat (目标地址改写),简单来说就是:比如这个数据包原来的dst ip是百度的,按理说经过routing decision之后会进入forward转发阶段,但是在这里你可以把目标地址改写成自己,让数据流入input通路,在本机截获这个数据包。
  4. 上图右上角写的:locally generated packet,表示这是本机自己生成的流量。它会一路经过各个表的output链,然后流到output interface(网卡)上。你注意下,流量在被打包成outgoing packet之前,会有个localhost dest的判断,如果它判断流量不是发往本机的话,流量会经过nat表的postrouting阶段。一般会在这里做DNAT源地址改写。

所以经过对上图的简单分析,如果咱想自定义对流量进行控制,那该怎么办?

这并不复杂。但是在这想该怎么办之前,我们得先搞清楚,通常情况下我们会对流量做那些控制?无非如下:

  1. 丢弃来自xxx的流量
  2. 丢弃去往xxx的流量
  3. 只接收来自xxx的流量
  4. 在刚流量流入时,将目标地址改写成其他地址
  5. 在流量即将流出前,将源地址改写成其他地址
  6. 将发往A的数据包,转发给B

等等等等,如果你足够敏感,你就能发现,上面这六条干预策略,filternat这两张表已经完全能满足我们的需求了,我们只需要在这两张表的不同链上加自己的规则就行,如下:

  1. 丢弃来自xxx的流量(filter表INPUT链
  2. 丢弃去往xxx的流量(filter表OUTPUT链
  3. 只接收来自xxx的流量(filter表INPUT链
  4. 在刚流量流入时,将目标地址改写成其他地址(nat表prerouting链
  5. 在流量即将流出前,将源地址改写成其他地址(nat表postrouting链
  6. 将发往A的数据包,转发给B(filter表forward链

数据包在iptables中的走向还可以简化成下面这张图

图片

参考:程序员白日梦(这篇文章是我看到的最好的一篇,一定要看)

iptables 命令

iptables -t ${表名}  ${Commands} ${链名}  ${链中的规则号} ${匹配条件} ${目标动作}

Usage

[root@localhost ~]# iptables -h
iptables v1.4.21

Usage: iptables -[ACD] chain rule-specification [options]
       iptables -I chain [rulenum] rule-specification [options]
       iptables -R chain rulenum rule-specification [options]
       iptables -D chain rulenum [options]
       iptables -[LS] [chain [rulenum]] [options]
       iptables -[FZ] [chain] [options]
       iptables -[NX] chain
       iptables -E old-chain-name new-chain-name
       iptables -P chain target [options]
       iptables -h 打印帮助信息

Commands

指令,

[root@localhost ~]# iptables -h
iptables v1.4.21

Commands:
Either long or short options are allowed.
  --append  -A chain            在链中添加追加规则
  --check   -C chain            检查链中是否存在指定规则 
  --delete  -D chain            删除链上的规则
  --delete  -D chain rulenum    删除链上的规则,rulenum默认为1
  --insert  -I chain [rulenum]  在指定链上添加一条规则,rulenum默认为1
  --replace -R chain rulenum    替换链上的规则,rulenum默认为1
  --list    -L [chain [rulenum]] 列出链上的所有(或者指定编号的)规则   
  --list-rules -S [chain [rulenum]] 打印链规则 ,以文本的形式
  --flush   -F [chain]          删除所有链或者指定链上的规则
  --zero    -Z [chain [rulenum]]  将链中的计数器清零
  --new     -N chain            新建一个用户定义的链
  --delete-chain  -X [chain]    删除链
  --policy  -P chain target     修改链的默认目标
  --rename-chain -E old-chain new-chain  修改链名

Options

[root@localhost ~]# iptables -h
iptables v1.4.21

Options:
    --ipv4      -4              Nothing (line is ignored by ip6tables-restore)
    --ipv6      -6              Error (line is ignored by iptables-restore)
[!] --protocol  -p proto        protocol: by number or name, eg. `tcp'
[!] --source    -s address[/mask][...]
                                source specification
[!] --destination -d address[/mask][...]
                                destination specification
[!] --in-interface -i input name[+]
                                network interface name ([+] for wildcard)
 --jump -j target
                                target for rule (may load target extension)
  --goto      -g chain
                              jump to chain with no return
  --match       -m match
                                extended match (may load extension)
  --numeric     -n              numeric output of addresses and ports
[!] --out-interface -o output name[+]
                                network interface name ([+] for wildcard)
  --table       -t table        table to manipulate (default: `filter')
  --verbose     -v              verbose mode
  --wait        -w [seconds]    maximum wait to acquire xtables lock before give up
  --wait-interval -W [usecs]    wait time to try to acquire xtables lock
                                default is 1 second
  --line-numbers                print line numbers when listing
  --exact       -x              expand numbers (display exact values)
[!] --fragment  -f              match second or further fragments only
  --modprobe=<command>          try to insert modules using this command
  --set-counters PKTS BYTES     set the counter during insert/append
[!] --version   -V              打印版本号.

练习

Commands

下面的命令实例只是为的练习指令,命令的内容都比较简单,更复杂的示例请查看Options相关练习。

--list -L

-L [chain [rulenum]] 列出链上的所有(或者指定编号的)规则

## 查看filter表INPUT链上的规则(带上编号)
[root@XUYUANSHENG ~]# iptables -t filter -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
## 查看filter表所有链上的规则(带上编号)
[root@XUYUANSHENG ~]# iptables -t filter -L --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
[root@XUYUANSHENG ~]# iptables -t filter -L newchain 2 --line-numbers
iptables: No chain/target/match by that name.

--new -N

-N chain 新建一个用户定义的链

## 在filter表上新建一个链, 名称为 newchain
[root@XUYUANSHENG ~]# iptables -t filter -N newchain
[root@XUYUANSHENG ~]# iptables -t filter -L newchain
Chain newchain (0 references)
target     prot opt source               destination

--rename-chain -E

-E old-chain new-chain 修改链名

[root@XUYUANSHENG ~]# iptables -t filter -E newchain INPUT1
[root@XUYUANSHENG ~]# iptables -t filter -E INPUT1 newchain
## 默认的链无法更改
[root@XUYUANSHENG ~]# iptables -t filter -E INPUT newchain11
iptables: No chain/target/match by that name.

--policy -P

-P chain target 修改链的默认目标

## 查看OUTPUT链(内置链),newchain链(用户链)的当前默认规则
[root@XUYUANSHENG ~]# iptables -t filter -L  OUTPUT
## OUTPUT链默认规则为 ACCEPT
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
[root@XUYUANSHENG ~]# iptables -t filter -L newchain
## newchain链没有默认规则
Chain newchain (0 references)
target     prot opt source               destination
## 修改用户链提示不是内置链,OUTPUT链的默认规则正确修改为 DROP
[root@XUYUANSHENG ~]# iptables -t filter -P newchain ACCEPT
iptables: Bad built-in chain name.
[root@XUYUANSHENG ~]# iptables -t filter -P OUTPUT DROP
[root@XUYUANSHENG ~]# iptables -t filter -L  OUTPUT
Chain OUTPUT (policy DROP)
target     prot opt source               destination

--append -A

-A chain 在链中添加追加规则

## 在filter表的newchain链上追加三条规则,编号分别为1,2,3
[root@XUYUANSHENG ~]# iptables -t filter  -A newchain -j ACCEPT
[root@XUYUANSHENG ~]# iptables -t filter  -A newchain -j DROP
[root@XUYUANSHENG ~]# iptables -t filter  -A newchain -s 192.168.1.1 -j DROP
[root@XUYUANSHENG ~]# iptables -t filter -L newchain --line-numbers
Chain newchain (0 references)
num  target     prot opt source               destination
1    ACCEPT     all  --  anywhere             anywhere
2    DROP       all  --  anywhere             anywhere
3    DROP       all  --  192.168.1.1          anywhere

--insert -I

-I chain [rulenum] 在指定链上添加一条规则,rulenum默认为1

## 在filter表的newchain链上插入一条规则,编号分别为 2 
[root@XUYUANSHENG ~]# iptables -t filter  -I newchain 2  -s 192.168.1.2 -j DROP
## 在filter表的newchain链上插入一条规则,编号不指定,默认为 1 
[root@XUYUANSHENG ~]# iptables -t filter  -I newchain  -s 10.1.1.1 -j DROP
[root@XUYUANSHENG ~]# iptables -t filter -L newchain --line-numbers
Chain newchain (0 references)
num  target     prot opt source               destination
## 编号为 1 的位置已经变成最新插入的规则了,老规则编号依次递增
1    DROP       all  --  10.1.1.1             anywhere
2    ACCEPT     all  --  anywhere             anywhere
## 编号为 3 的位置已经变成第一次插入的新规则了,因为在这之后又插入了一条规则,所以编号增加了 1 
3    DROP       all  --  192.168.1.2          anywhere
4    DROP       all  --  anywhere             anywhere
5    DROP       all  --  192.168.1.1          anywhere

--replace -R

-R chain rulenum 替换链上的规则,rulenum默认为1

[root@XUYUANSHENG ~]# iptables -t filter -R newchain 4 -s 192.168.1.4 -j ACCEPT
[root@XUYUANSHENG ~]# iptables -t filter -L newchain 4 --line-numbers
4    ACCEPT     all  --  192.168.1.4          anywhere

--check -C

-C chain 检查链中是否存在指定规则

[root@XUYUANSHENG ~]# iptables -t filter -C newchain  -s 192.168.1.4 -j ACCEPT
## 上面没有任何输出,说明存在这个规则,下面规则不存在,会提示在这条链上没有匹配上此规则 
[root@XUYUANSHENG ~]# iptables -t filter -C newchain  -s 192.168.1.110 -j ACCEPT
iptables: Bad rule (does a matching rule exist in that chain?).

--delete -D

-D chain 删除链上的规则
-D chain rulenum 删除链上的规则,rulenum默认为1

[root@XUYUANSHENG ~]# iptables -t filter -L newchain  --line-numbers
Chain newchain (0 references)
num  target     prot opt source               destination
1    DROP       all  --  10.1.1.1             anywhere
2    ACCEPT     all  --  anywhere             anywhere
3    DROP       all  --  192.168.1.2          anywhere
4    ACCEPT     all  --  192.168.1.4          anywhere
5    DROP       all  --  192.168.1.1          anywhere
## 删除newchain链上编号为5的规则 
[root@XUYUANSHENG ~]# iptables -t filter -D newchain 5
## 删除newchain链上内容为‘ -j  ACCEPT ’ 的规则 
[root@XUYUANSHENG ~]# iptables -t filter -D newchain -j  ACCEPT
[root@XUYUANSHENG ~]# iptables -t filter -L newchain  --line-numbers
Chain newchain (0 references)
num  target     prot opt source               destination
1    DROP       all  --  10.1.1.1             anywhere
2    DROP       all  --  192.168.1.2          anywhere
3    ACCEPT     all  --  192.168.1.4          anywhere

--zero -Z

-Z [chain [rulenum]] 将链中的计数器清零

[root@XUYUANSHENG ~]# iptables -t filter -L INPUT  --line-numbers -v
## 下面的 packets,bytes 都是有数值的
Chain INPUT (policy ACCEPT 1 packets, 240 bytes)
num   pkts bytes target     prot opt in     out     source               destination
[root@XUYUANSHENG ~]# iptables -t filter -Z INPUT
[root@XUYUANSHENG ~]# iptables -t filter -L INPUT   --line-numbers -v
## 下面的 packets,bytes 都已经被清零
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination

--list-rules -S

-S [chain [rulenum]] 打印链规则 ,以文本的形式

[root@XUYUANSHENG ~]# iptables -t filter -S newchain
-N newchain
-A newchain -s 10.1.1.1/32 -j DROP
-A newchain -s 192.168.1.2/32 -j DROP
-A newchain -s 192.168.1.4/32 -j ACCEPT
[root@XUYUANSHENG ~]# iptables -t filter -S newchain  2
-A newchain -s 192.168.1.2/32 -j DROP
[root@XUYUANSHENG ~]# iptables -t filter -S INPUT
-P INPUT ACCEPT

--flush -F

-F [chain] 删除所有链或者指定链上的规则

[root@XUYUANSHENG ~]# iptables -t filter -S INPUT
-P INPUT ACCEPT
-A INPUT -j DROP
[root@XUYUANSHENG ~]# iptables -t filter -S newchain
-N newchain
-A newchain -s 10.1.1.1/32 -j DROP
-A newchain -s 192.168.1.2/32 -j DROP
-A newchain -s 192.168.1.4/32 -j ACCEPT
[root@XUYUANSHENG ~]# iptables -t filter -S OUTPUT
-P OUTPUT DROP
-A OUTPUT -j DROP
## 查看现有链上的规则,INPUT有一条规则,newchain有三条规则,OUTPUT有一条规则
## 清空OUTPUT链上的规则 
[root@XUYUANSHENG ~]# iptables -t filter -F OUTPUT
[root@XUYUANSHENG ~]# iptables -t filter -S OUTPUT
-P OUTPUT DROP
## 清空filter表上所有链的规则 
[root@XUYUANSHENG ~]# iptables -t filter -F
[root@XUYUANSHENG ~]# iptables -t filter -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT DROP
-N newchain

--delete-chain -X

-X [chain] 删除链

## 查看filter表上现有的链
[root@XUYUANSHENG ~]# iptables -t filter -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT DROP
-N newchain
-N newchain1
-N newchain2
-N newchain3
## 删除 newchain2链
[root@XUYUANSHENG ~]# iptables -t filter -X newchain2
[root@XUYUANSHENG ~]# iptables -t filter -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT DROP
-N newchain
-N newchain1
-N newchain3

## 删除所有非内置链
[root@XUYUANSHENG ~]# iptables -t filter -X
[root@XUYUANSHENG ~]# iptables -t filter -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT DROP
## 内置链无法删除
[root@XUYUANSHENG ~]# iptables -t filter -X INPUT
iptables: Invalid argument. Run `dmesg' for more information.

Options

--version -V

[root@XUYUANSHENG ~]# iptables -V
iptables v1.4.21
[root@XUYUANSHENG ~]# iptables -t filter  -V
iptables v1.4.21

匹配条件-p协议、-4-6-s 源地址-d 目标地址-i 网络接口名

目标动作:拒绝访问-j REJECT、允许通过-j ACCEPT、丢弃-j DROP、记录日志 -j LOG、源地址转换-j snat、目标地址转换-j dnat、还有RETURNQUEUE

参考: 程序员白日梦 wiki Crazy_Tortoise

好了,我也是菜鸡,后续再补充上实际的练习案例

posted @ 2023-02-16 08:54  菜阿  阅读(313)  评论(0编辑  收藏  举报