🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 1. 基础概念 1. iptables是Linux防火墙工具,用来定义数据包操作规则(用户空间),用来操作netfilter规则 2. netfilter组件:称为内核空间,是内核的一部分,由一些信息包过滤表组成,这些表是内核用来控制信息包过滤处理的规则集, 3. iptables和firewall是给用户操作netfilter的工具,真正起到防火墙作用的是netfilter组件 # 2. table、chain和rule ## 2.1 三张表 1. 最常用的有三个表,分别是`filter`,`nat `和`mangle`.其中每个表又有各自包含不同的操作链(chains): **filter**用于过滤数据包,进入本机(input)、从本机出去(output),转发的数据 **nat**用于转发数据包,转入(prerouting)和转出(postrouting) ![](https://img.kancloud.cn/72/82/72824116f26302c1f4425ccbbb65375f_612x142.png) 2. iptables的表与链的工作流程,如图想要修改input链,只能在filter(过滤)表和Mangle表上进行,同理其他链操作参考下图 ![](https://img.kancloud.cn/4d/34/4d348100c672225714e867ce7084afe2_673x291.png) ## 2.2 五种链 1. **input**: 匹配目标ip 是本机的数据包时,进入此链 2. **output**: 出口数据包,从本机发出的数据包,进入此链 3. **forward**: 匹配流经本机的数据包,nat转发 4. **prerouting**: 可以**用来修改目的地址**用来做DNAT,如把内网的80端口映射到路由器外网端口上,然后内核的”路由模块”-`route`根据”数据包目的IP”以及”内核中的路由表”判断是否需要转送出去(注意,这个时候数据包的DestIP有可能已经被修改过了) 5. **postrouting**: 用来修改源地址用来做SNAT,如内网通过路由器NAT转换功能实现内网PC机通过一个公网ip地址上网 > 入站数据:prerouting -> input > 转发数据:prerouting -> forward -> postrouting > 出站数据:putput -> postrouting **包处理流程** 1. 首先进入preruteing,决定是进入本机还是转发 2. 若果目的地址是本机的(数据包的目的ip是本机的网口ip),进入input链,到达input链后,任何的进程都有可能得到这个数据包 3. 如果数据包是要转发出去的(即目的IP地址不再当前子网中),**且内核允许转发**,数据包就会向右移动,经过FORWARD链,然后到达POSTROUTING链输出(选择对应子网的网口发送出去) -》源ip不变,目的ip变内网,记录nat表,数据包返回是参照nat表,数据返回给外网,达到暴露服务的目的 4. 本机上运行的程序也可以发送数据包,这些数据包经过OUTPUT链,然后到达POSTROTING链输出(注意,这个时候数据包的SrcIP有可能已经被我们修改过了) -》改变源ip,目的IP不变,记录nat表,数据包回来参照nat表,又回到了内网,达到上网的目的 ## 2.3 包处理规则target **防火墙处理数据包的方式(规则):** 1. `ACCEPT`:允许数据包通过 2. `DROP`:直接丢弃数据包,不给任何回应信息 3. `REJECT`:拒绝数据包通过,必要时会给数据发送端一个响应的信息。 4. `SNAT`:源地址转换。在进入路由层面的route之前,重新改写源地址,目标地址不变,并在本机建立NAT表项,当数据返回时,根据NAT表将目的地址数据改写为数据发送出去时候的源地址,并发送给主机。**解决内网用户用同一个公网地址上网的问题**。 5. `MASQUERADE`,是SNAT的一种特殊形式,适用于像adsl这种临时会变的ip上 6. `DNAT`:目标地址转换。和SNAT相反,IP包经过route之后、出本地的网络栈之前,重新修改目标地址,源地址不变,在本机建立NAT表项,当数据返回时,根据NAT表将源地址修改为数据发送过来时的目标地址,并发给远程主机。可以隐藏后端服务器的真实地址。 (暴露内网地址和端口) 7. `REDIRECT`:是DNAT的一种特殊形式,将网络包转发到本地host上(不管IP头部指定的目标地址是啥),方便在本机做端口转发。 8. `LOG`:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则 除去最后一个`LOG`,前3条规则匹配数据包后,该数据包不会再往下继续匹配了,所以编写的规则顺序极其关键。 # 3. iptables命令使用 ## 3.1 命令格式 > iptable是给用户调用netfilter的工具,用来修改防火墙规则 ``` iptables [-t 表名] 管理选项 [链名] [条件匹配] [-j 目标动作或跳转] ``` 1 ) 不指定表名时,默认表示filter表 2 ) 不指定链名时,默认表示该表内所有链 3 ) 除非设置规则链的缺省策略,否则需要制定匹配条件 **1. command 选项,操作链上的规则** ~~~ -A :增加 -D: 删除 -I : 插入 -R -L:列出表的规则,默认是filter表 -F: 清空规则 -Z -N:用于新建一个自定义链 -X:清空引用为0的自定义链规则 -P : 设置某个链的默认规则,链的默认规则最后触发 ~~~ **2. parameter选项,数据包过滤,协议端口ip** ~~~ -P:协议类型 -s:来源地址 -d:目的地址 -i:流入 -o:流出 -sport:来源端口 -dport:目标端口 ~~~ **3. target** 包处理方式 ~~~ -j ACCEPT -j DROP -j REJECT ... ~~~ ## 3.2 例子 > 查看默认策略 ``` iptables -L ``` ![](https://img.kancloud.cn/f4/70/f470138064a878864d88553565428f9c_1033x454.png) > 拒绝所有连接,没有指定规则则,则匹配所有 ``` iptables -t filter -A INPUT -j DROP ``` > 删除规则 -D 按照序号展示 `iptables -L --line-numbers` ``` Chain INPUT (policy ACCEPT) num target prot opt source destination 1 KUBE-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes service portals */ 2 KUBE-EXTERNAL-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes externally-visible service portals */ 3 KUBE-FIREWALL all -- anywhere anywhere Chain FORWARD (policy ACCEPT) num target prot opt source destination 1 KUBE-FORWARD all -- anywhere anywhere /* kubernetes forwarding rules */ 2 KUBE-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes service portals */ 3 DOCKER-USER all -- anywhere anywhere 4 DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere 5 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED 6 DOCKER all -- anywhere anywhere ``` 删除filter表的input 链的第一条规则 ``` iptables -t filter -D INPUT 1 ``` 方式2,按内容 > 删除filter表的input链中内容为 "-s 192.168.0.1 -j DROP" 的规则 ``` iptables -t filter -D INPUT -s 192.168.0.1 -j DROP ``` > 设置某个链的默认规则 `iptables -P INPUT DROP` > 清空规则 -F 清空filter表INPUT链的所有规则 ``` iptables -t filter -F INPUT ``` > 清空filter表的所有链的规则 ``` iptables -t filter -F ``` 注意事项 -F 不清除默认规则 -P 设置了DROP后,使用-F 一定要小心 如不写链名,默认清空某表里所有链里的所有规则 ### 3.2.2 nat 表 > PREROUTING 链的所有规则 ``` iptables -t nat -vnL PREROUTING ``` **1. 按流入网络接口匹配(-i)** > -i 匹配数据进入网络接口 #主要用于nat表 例子 -i eth0 匹配是否从网络接口eth0进来 -i ppp0 匹配是否从网络接口ppp0进来 2. 按流出网络接口匹配(-o) `iptables -t nat -o eth0 条件 动作` 3. 按来源地址匹配(-s) -s 匹配来源地址,可以是ip,net,domain ,也可空(任何地址) 例如: ``` -s 192.168.0.1 匹配来自192.168.0.1的数据包 -s 192.168.1.0/24 匹配来自192.168.1.0/24 的数据包 -s 192.168.0.0/16 匹配来自192.168.0.0/16 的数据包 ``` 4. 按目的地址匹配(-d) -d 匹配来源地址,可以是ip,net,domain ,也可空(任何地址) 例如: ``` -d 192.168.0.1 匹配去往192.168.0.1的数据包 -d 192.168.1.0/24 匹配去往192.168.1.0/24 的数据包 -d 192.168.0.0/16 匹配去往192.168.0.0/16 的数据包 ``` 5. 按协议匹配(-p) -p 匹配来源地址,可以是TCP、UDP,ICMP,也可为空 例如: ``` -p tcp 匹配协议为 tcp的数据包 -p udp 匹配协议为 udp的数据包 -p icmp 匹配协议为 icmp的数据包 ``` 6. 按来源端口匹配(sport) 例如: ``` --sport 1000 匹配源端口是1000的数据包 --sport 1000:3000 匹配源端口是1000-3000的数据包 --sport :3000 匹配源端口是3000以下的数据包 --sport 1000: 匹配源端口是1000以上的数据包 ``` 7. 按目的端口匹配(dport) ``` --dport 1000 匹配目的端口是1000的数据包 --dport 1000:3000 匹配目的端口是1000-3000的数据包 --dport :3000 匹配目的端口是3000以下的数据包 --dport 1000: 匹配目的端口是1000以上的数据包 ``` 注意: 1. --sport 和 --dport 必须和 -p 配合使用 2. 条件越多,匹配越精确,范围越小 数据包结构 目标端口 目标ip地址 内容址 源端口 源ip地址 80 192.168.1.64 xxx 3211 192.168.1.65 ### 动作(处理方式) #### ACCEPT(接受) 通过,允许数据包通过本链而不拦截 格式: -j ACCEPT > 允许所有访问本机ip的数据包通过 ``` iptables -A INPUT -j ACCEPT ``` #### DROP (丢弃,不给对方任何回应) 丢弃,不允许数据包通过本链而丢弃它 格式: -j DROP 阻止来源地址为192.168.80.39的数据包通过本机 ``` iptables -A FORWARD -s 192.168.80.39 -j DROP ``` #### REJECT (拒绝,给对方一个回应) #### SNAT(上网) 原地址转化,snat 支持转化为单ip,也支持转化到ip地址池 > 格式: -j SNAT --to IP[-IP][:端口-端口] 适用范围: nat表的 postrouting 单个地址情况 1. 将内网 192.168.0.0/24的源地址修改为公网IP地址 1.1.1.1 ``` iptables -t nat -A POSTROUNTING -s 192.168.0.0/24 -j SNAT --to 1.1.1.1 ``` 2. 将内网 192.168.0.0/24的源地址修改为公网IP地址 1.1.1.1- 1.1.1.10 iptables -t nat -A POSTROUNTING -s 192.168.0.0/24 -j SNAT --to 1.1.1.1-1.1.1.10 #### DNAT(端口映射) 目标地址转化,DNAT 支持转化为单ip,也支持转化到ip地址池 > 格式: -j DNAT --to IP[-IP][:端口-端口] > 适用范围: nat表的 prerouting **1. 暴露端口** > 把eth0进来的要访问TCP/80的数据包目的地址改为192.168.0.1 ``` iptables -t nat -A PREROUNTING -i eth0 -p tcp -dport 80 -j SNAT --to 192.168.0.1 ``` 多个地址情况 **2. 把eth0进来的要访问TCP/80的数据包目的地址改为192.168.0.1-192.168.0.10** ``` iptables -t nat -A PREROUNTING -i eth0 -p tcp -dport 80 -j DNAT --to 192.168.0.1-192.168.0.10 ``` #### MASQUERADE(伪装ip地址) > 动态源地址转换(动态ip的情况下使用) 将源地址是192.168.0.0/24的数据包进行地址伪装,转换成eth0上的ip地址,eth0为路由器外网IP地址 ``` iptables -t nat -A POSTROUNTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE ``` ## 附加模块 ### 按包状态匹配 -m state --state 状态 状态:NEW、RELATED、ESTABLIShED、INVALID ``` NEW: 有别于tcp的syn RELATED: 衍生态 ESTABLISHED: 连接状态 INVALID: 不能被识别属于哪个连接或没有任何状态 ``` > 将连接状态为RELATED 和ESTABLISHED 的访问数据包通过 ``` iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT ``` ### 按来源MAC匹配 格式 -m mac --mac-source mac地址 > 阻断来自某mac 地址数据包通过本机 ``` iptables -A FORWARD -m mac --mac-source xxxx -j DROP ``` ### 按包速率匹配 > 格式 -m limit --limit 匹配速率 [--burst 缓冲数量] > 只允许192.168.0.1 一秒发送50个数据包 ``` iptables -A FORWARD -d 192.168.0.1 -m limit --limit 50/s -j ACCEPT iptables -A FORWARD -d 192.168.0.1 -j DROP ``` ### 多端口匹配 格式 ``` -m multport <--sports|--dports|--ports> ``` 一次行匹配多个端口,可以区分源端口,目的端口或不制定端口 > 允许所有客户端访问本服务器的21、22、 25和 80端口的服务 ``` iptables -A INPUT -p tcp -m multiport --dports 21,22,25,80 -j ACCEPT ``` 注意: 必须与 -p 参数一起使用 三、网络基本拓扑图 graph LR 终端用户--> 互联网 互联网--> 防火墙 防火墙--> 路由器 路由器--> 交换机 交换机--> 服务器 # 4. 案例 ## 4.1 对web服务器保护 > 匹配规则,自上而下,只要匹配到一条就停止,无论是通过还是不通过 ``` iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p tcp -m mutiport --dports 22,80 -j ACCEPT iptables -A INPUT -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A INPUT DROP ``` ## 4.2 让内网pc机上网 可连接外网主机|,有两块网卡 ``` 内网ip:192.168.56.10 外网ip: 10.0.2.15 ``` 内网主机 ``` 内网ip: 192.168.56.13 ``` **1. 在可上外网主机配置路由规则,转发数据包到外网网卡接口** ``` iptables -t filter -P FORWARD DROP iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -s 192.168.56.10/24 -j ACCEPT iptables -t nat -A POSTROUTING -s 192.168.56.1/24 -j SNAT --to 10.0.2.15 ``` **2. 外网机器打开数据包转发** ``` vim /etc/sysctl.conf # 配置=1,开启转发 net.ipv4.ip_forward=1 ``` **3.在内网机器上,设置其网关为外网主机ip,将外网请求发送到网关** ![](https://img.kancloud.cn/15/74/157466669f5e1a6f3450ece836fc2fb6_817x454.png) 重启网络 `service network restart` **4. 配置域名解析** ``` vi /etc/resolv.conf nameserver 114.114.114.114 nameserver 8.8.8.8 ``` ![](https://img.kancloud.cn/14/8b/148b6203168dd4d61b7d6ab64de3aeaa_814x263.png) ## 4.3 暴露端口