iptables其实不是真正的防火墙,可以把它理解成一个客户端代理,用户通过iptables这个代理,将用户的安全设定执行到对应的netfilter安全框架"中,netfilter位于内核空间。

一、四表五链理论

iptables 其实是多个表(table)的容器,每个表里包含不同的链(chain),链里边定义了不同的规则(policy),我们通过定义不同的规则,来控制数据包在防火墙的进出。

1、四表

  • raw表:关闭nat表上启用的连接追踪机制(决定数据包是否被状态跟踪机制处理);内核模块:iptable_raw
  • mangle表:拆解报文,做出修改,并重新封装的功能(如修改数据包的服务类型、TTL、并且可以配置路由实现QOS内核模块);内核模块:iptable_mangle
  • nat表:网络地址转换功能;内核模块:iptable_nat
  • filter表:负责包过滤功能,防火墙;内核模块:iptables_filter

2、五链

  • PREROUTING:在进行路由选择前处理数据包(做目标地址转换)
  • INPUT:处理入站数据包
  • FORWARD:处理转发数据包
  • OUTPUT:处理出站数据包
  • POSTROUTING:在进行路由选择后处理数据包(对数据链进行源地址修改转换)

报文到达链后匹配表的优先顺序:

Raw ==> mangle ==> nat ==> filter

每一条链其实就是众多规则中的一个检查清单,每一条链中可以有一条或数条规则。当一个数据包到达一个链时,iptables就会从链中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据 该条规则所定义的方法处理该数据包;否则iptables将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables就会根据该链预先定义的默认策略来处理数据包。

3、表包含的链路

Filter 是默认的主机防火墙,过滤流入流出主机的数据包。里边包含INPUT,OUTPUT,FOWARD三个链

INPUT 过滤进入主机的数据包

OUTPUT 处理从本机发出去的数据包

FOWARD 处理流经本主机的数据包,与NAT有关系

Filter表是企业实现防火墙功能的重要手段

NAT  负责网络地址转换(来源于目的地址的IP与端口的转换),一般用于局域网的共享上网,与网络交换机acl类似,包含OUTPUT,PREROUTING,POSTROUTING三条链

OUTPUT 改变主机发出去的数据包的目标地址

PREROUTING 数据包到达防火墙时进行分路由判断之前执行的规则,改变数据包的目的地址,目的端口

POSTROUTING 数据包离开防火墙时进行分路由判断之前执行的规则,改变数据包的源的地址,源的端口

mangle 表的系统 chain: PREROUTING,OUTPUT

iptables传输数据包的过程

① 当一个数据包进入网卡时,它首先进入PREROUTING链,内核根据数据包目的IP判断是否是发往本机的。

② 如果数据包就是进入本机的,它就会沿着图向下移动,到达INPUT链。数据包到了INPUT链后,任何进程都会收到它。本机上运行的程序可以发送数据包,这些数据包会经过OUTPUT链,然后到达POSTROUTING链输出。

③ 如果数据包是要转发出去的,且内核允许转发,数据包就会流向FORWARD链进行处理(是否转发或拦截),然后到达POSTROUTING链(是否修改数据包的地 址等)进行处理。

报文的链流向:

  • 到本机某进程的报文:PREROUTING --> INPUT
  • 由本机转发的报文:PREROUTING --> FORWARD --> POSTROUTING
  • 由本机的某进程发出报文(通常为响应报文):OUTPUT --> POSTROUTING

二、iptables规则

1、写法

iptables  [ -t 表名 ] 命令选项 [链名][匹配规则][-j 处理动作]

# 表名 必须是 raw, nat,filter,mangle 中的一个。默认指filter表
# 不指定链名时,默认指表内的所有链
# 除非设置链的默认策略,否则必须指定匹配条件
# 命令选项、链名、处理动作使用大写字母,其余均为小写

①命令选项

规则管理命令选项:

  • -A:在指定链的末尾添加(append)一条新的规则
  • -D:删除(delete)指定链中的某一条规则,可以按规则序号和内容删除
  • -I : 在指定链中插入(insert)一条新的规则,默认在第一行添加
  • -R:修改、替换(replace)指定链中的某一条规则,可以按规则序号和内容替换

查看命令选项:

  • -L :列出(list)指定链中所有的规则进行查看
  • --line-numbers:查看规则时,显示规则的序号
  • -n :使用数字形式(numeric)显示输出结果
  • -v:以更详细的方式显示规则信息
  • -S:--list-rules  列出规则

链管理命令(这都是立即生效的):

  • -E :重命名用户定义的链,不改变链本身
  • -F :清空(flush)
  • -N:新建(new-chain)一条用户自己定义的规则链
  • -X :删除指定表中用户自定义的规则链(delete-chain)
  • -P :设置指定链的默认策略(policy)
  • -Z :将所有表的所有链的字节和数据包计数器清零

②匹配规则

1) 通用匹配

###反向匹配

# 只需在选项前面使用 ! 即可,如: ! -s 192.168.0.0/16 表示除 192.168/16 外的源 IP

  • 协议匹配: -p [协议名]
  • 地址匹配
    • -s [源地址]
    • -d [目标地址]
  • 接口匹配
    • -i [入站网卡]
    • -o [出站网卡]

2) 隐含匹配

  • 端口匹配

    • -sport [源端口]
    • -dport [目标端口]
  • TCP连接标记匹配:--tcp-flags [列表1:检查范围] [列表2:被设置的标记]

    • 有两个参数列表,列表内部用逗号为分隔符,两个列表之间用空格分开
    • LIST1用作参数检查,LIST2用作参数匹配。
    • 可用标志有:

      • SYN( 同步; 表示开始会话请求 ),
      • ACK(应答),
      • FIN(结束; 结束会话),
      • RST(复位;中断一个连接)
      • PSH(推送; 数据包立即发送),
      • URG(紧急 ),
      • ALL(指选定所有的标记),
      • NONE(指未选定任何标记)
iptables -A INPUT -p tcp –tcp-flags SYN,FIN,ACK SYN
# 表示SYN、ACK、FIN的标志都检查,但是只有SYN匹配
iptables -A FROWARD -p tcp –tcp-flags ALL SYN,ACK
# 表示ALL(SYN,ACK,FIN,RST,URG,PSH)的标志都检查,但是只有设置了SYN和ACK的匹配。
  • ICMP类型匹配:--icmp-type [ICMP类型]

③处理动作

动作也可以分为基本动作和扩展动作

ACCEPT:允许数据包通过。

DROP:直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求泥牛入海了,过了超时时间才会有反应。

REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息。

iptables -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset

SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题。

iptables -t nat -A POSTROUTING -p tcp-o eth0 -j SNAT --to-source 194.236.50.155-194.236.50.160:1024-32000

MASQUERADE:地址伪装。是SNAT的一种特殊形式,适用于动态的、临时会变的ip上。

iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE --to-ports 1024-31000

DNAT:目标地址转换。

iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10:80-100

REDIRECT:在本机做端口映射。将包重新导向到另一个端口(PNAT),进行完此处理动作后,将会继续比对其它规则。 这个功能可以用来实作通透式porxy 或用来保护 web 服务器。

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

MASK : 做防火墙标记

RETURN : 返回调用链

LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配。

--log-level LEVEL : 日志的等级

--log-prefix FREFIX : 日志的提示语句的前缀

2、规则管理

①查看规则

# -S: 列出选定链的规则,
# -t : 对指定的table进行操作。raw,nat,filter,mangle中的一个。默认是filter #查看所有的规则
iptables -L -v -n # 查看表中的规则
iptables -L -t filter -L参数用于列出IPtables规则
-v参数用于显示详细信息
-n参数用于显示IP地址和端口号,而不是显示对应的服务名称
iptables -t filter -L INPUT -v -n # 查看链中的规则
iptables -L INPUT
iptables -L FORWARD --line-numbers #列出nat表的规则链
iptables -S -t nat
iptables -t nat -nvL --line-numbe # 查看POSTROUTING链nat表中的规则
iptables -L POSTROUTING -t nat
iptables -L PREROUTING -t nat --line-numbers 删除一条nat表中含POSTROUTIN的第一条规则
iptables -t nat -D POSTROUTING 1 #删除多余的规则(规则混乱,可能互相影响)
# 删除input分组里边的第二条
iptables -L -n --line-number
iptables -D INPUT 2

②删除规则

#清除原有的filter有中的规则
iptables -F #清除原有的nat表中的规则
iptables -t nat -F # 删除链中指定的规则
iptables -D FORWARD 1 # 删除链中指定表的规则
iptables -D POSTROUTING -t nat 1 #缺省允许IP转发
iptables -P FORWARDACCEPT #利用iptables 实现nat MASQUERADE 共享上网
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

③添加规则

# 在指定链的末尾添加(append)一条新的规则
iptables -A FORWARD -s 10.8.0.10 -d 192.168.1.5 -j DROP
# 在指定链中插入(insert)一条新的规则,默认在第一行添加
iptables -I FORWARD -s 10.8.0.10 -d 192.168.1.5 -j DROP

3、规则的匹配顺序

①按自上而下的顺序依次匹配,匹配即停止(LOG策略例外)

②若找不到相匹配的规则,则按该链的默认策略处理

三、iptables的显示扩展模块

官方文档:https://ipset.netfilter.org/iptables-extensions.man.html

必须使用-m选项手动加载模块, 其扩展模块路径为:/lib64/xtables,其中大写的为目标扩展,小写的为规则扩展

1、模块管理

①查看Iptables已加载的模块

cat /proc/net/ip_tables_matches
# 查看内核已编译的模块

②查看内核支持的模块

ls /lib/modules/$(uname -r)/kernel/net/netfilter/*
# 或者
ls /lib/modules/nf_*
# 或者
ls /usr/lib/iptables/

③加载模块

modprobe 模块名

CentOS/Redhat

编辑/etc/sysconfig/iptables-config

IPTABLES_MODULES="模块1 模块2"

然后重启iptables

systemctl restart iptables

2、模块语法

-m 扩展模块 --模块参数

查看模块的支持的参数:

iptables -m <match/module name> --help
# 如果不显示模块的详细参数,则说明该模块没有加载,无法使用

3、常见条件匹配模块示例

①multiport:多端口匹配模块

-m multiport --sport | --dport [端口列表]

iptables -A INPUT -p tcp -m multiport --dport 22,25,80,443 -j ACCEPT

②iprange:IP范围匹配模块

-m iprange --src-range [IP范围]

iptables -A FORWARD -p tcp -m iprange --src-range 192.168.1.10-192.168.1.20 -j ACCEPT

③mac:MAC地址匹配模块

-m mac --mac-range [MAC地址]

iptables -A INPUT -m mac --mac-source 00:01:02:03:04:cc -j DROP

④state:报文状态匹配模块

--state [报文状态]:多个state可以使用,号分隔

支持配置的报文状态:

  • ESTABLISHED:第一个成功穿越防火墙的报文之后所有的报文;
  • NEW:一个连接的第一个报文,例如TCP连接中的SYN报文;
  • RELATED:伴随连接的报文,即某个已经处于ESTABLISHED的连接所产生的报文,这些报文不属于第一条连接,但是的确是由第一条连接产生的;
  • INVALID:如果一个包没有办法被识别,或者这个包没有任何状态,那么这个包的状态就是INVALID,我们可以主动屏蔽状态为INVALID的报文
  • UNTRACKED:报文的状态为untracked时,表示报文未被追踪,当报文的状态为Untracked时通常表示无法找到相关的连接。
iptables -A INPUT -d 172.168.100.67 -p tcp -m multiport --dport 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT

⑤string:字符串匹配模块

--algo {匹配算法: bm|kmp}

--string "字符串"

iptables -I OUTPUT -s 192.168.1.0/24 -m string --algo kmp --string "qq" -j REJECT
#使用kmp算法限制拒绝源地址192.168.1.0/24带有"qq"字符串的请求
iptables -I INPUT -m string --string "export/*" --algo bm -j DROP

⑥limit:连接数匹配模块

—limit: 平均速率,单位:个数/second ,个数/minute,个数/hour

--limit-burst: 峰值数量,默认5个

iptables -I INPUT -d 172.16.100.7 -p tcp --dport 22 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
# 当达到100个连接后,才启用上述25/minute限制

⑦connlimit:连接数匹配模块

--connlimit-upto n : 当现在的连接数量低于或等于这个数量(n),就匹配 --connlimit-above n : 当现有的连接数量大于这个数量, 就匹配

iptables -A INPUT -d 172.16.36.61 -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT

⑧time:时间限制匹配模块

-m time --datestart --datestop --timestart --timestop

iptables -A INPUT -p tcp --dport 21 -s 192.168.1.0/24 -m time ! --weekdays 6,7 -m time --timestart 8:30 --timestop 18:00 -m connlimit --connlimit-above 5 -j ACCET
# 在工作时间,即周一到周五的8:30-18:00,开放本机的ftp服务给 192.168.1.0网络中的主机访问;并且数据下载请求的次数每分钟不得超过 5 个;

⑨set: 地址集合模块

  • 普通的iptables链是线性的存储和过滤,在进行规则匹配时,是从规则列表中从头到尾一条一条进行匹配。这像是在链表中搜索指定节点费力
  • ipset 提供了把这个 O(n) 的操作变成 O(1) 的方法:就是把要处理的 IP 放进一个集合,对这个集合设置一条 iptables 规则。存储在带索引的数据结构中,这种结构即使集合比较大也可以进行高效的查找

  • ipset是iptables的扩展,允许创建管理匹配整个地址集合的规则。命令详解参考附录第2章节

-m set –match-set 地址集合名称

iptables -I INPUT -m set –match-set 集合名称 src -p tcp -j DROP

⑩Owner:用户模块

  • –uid-owner 和 –gid-owner 这两个选项用来匹配数据包由哪个用户和哪个用户组所产生,它们的功能由 xt_owner.ko 模块提供,且仅适用在 OUTPUT 链 POSROUTING 链中。

    • –uid-owner userid | username 该选项用来匹配数据包由哪个用户产生,因此可以利用这来限制该用户只能访问某些特定的网络服务,
    • –gid-owner groupid | groupname 该选项和 –uid-owner 类似,它用来匹配某个用户组所产生的数据包。
groupadd no-internet
iptables -I OUTPUT 1 -m owner --gid-owner no-internet -j DROP
useradd -g no-internet username

https://serverfault.com/questions/550276/how-to-block-internet-access-to-certain-programs-on-linux

四、iptables的内核调优

1、iptables的conntrack连接追踪优化

  • conntrack是netfilter的核心。有许多增强的功能,例如,地址转换(NAT),基于内容的业务识别(l7, layer-7 module)都是基于连接跟踪。

  • nf_conntrack模块在kernel 2.6.15(2006-01-03发布) 被引入,支持ipv4和ipv6,取代只支持ipv4的ip_connktrack,用于跟踪连接的状态,供其他模块使用。

  • iptables的连接追踪表最大容量是/proc/sys/ipv4/ip_conntrack_max设置的, 链接达到各种状态的超时后,会从表中删除,当模板满载时, 后续的链接可能会超时

  • 跟踪的连接用哈希表存储,每个桶(bucket)里都是1个链表,默认长度为4KB。netfilter的哈希表存储在内核空间,这部分内存不能swap

  • 哈希表大小 :64位的最大连接数/8; 32位的最大连接数/4

  • 在64位下,当CONNTRACK_MAX为 1048576,HASHSIZE 为 262144 时,最多占350多MB

  • 连接跟踪调优计算公式

    • CONNTRACK_MAX(最大几率的连接条数) = 内存个数*1024*1024*1024/16384/2 = ***

    • Buckets(哈希表大小) = CONNTRACK_MAX / 4 = ***(Byte字节)

    • 跟踪数暂用最内存大小 = CONNTRACK_MAX * 300(Byte字节)= ***(Byte字节)
  • 异常现象:

    • 丢包
  • 可调优参数

    • 哈希表桶大小

      注:net.netfilter.nf_conntrack_buckets 不能直接改(报错)

    • # 临时生效
      echo 262144 > /sys/module/nf_conntrack/parameters/hashsize # 重启永久生效
      新建文件:/etc/modprobe.d/iptables.conf
      options nf_conntrack hashsize = 32768
    • 最大追踪连接数

    • 注:加大max值, 也会加大内存的压力
    • # 临时生效
      sysctl -w net.nf_conntrack_max = 393216
      sysctl -w net.netfilter.nf_conntrack_max = 393216 # 永久生效
      echo "net.nf_conntrack_ma=393216" >> /etc/sysctl.conf
      echo "net.netfilter.nf_conntrack_max=393216" >> /etc/sysctl.conf
      sysctl -p

      响应时间

    • net.netfilter.nf_conntrack_tcp_timeout_close_wait:
      # CLOSE_WAIT是被动方收到FIN发ACK,然后会转到LAST_ACK发FIN,除非程序写得有问题,正常来说这状态持续时间很短。默认 60 秒 # 临时生效
      sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=300
      sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=120
      sysctl -w net.netfilter.nf_conntrack_tcp_timeout_close_wait=60
      sysctl -w net.netfilter.nf_conntrack_tcp_timeout_fin_wait=120 # 永久生效
      echo "net.netfilter.nf_conntrack_tcp_timeout_established=300" >> /etc/sysctl.conf
      echo "net.netfilter.nf_conntrack_tcp_timeout_time_wait=120" >> /etc/sysctl.conf
      echo "net.netfilter.nf_conntrack_tcp_timeout_close_wait=60" >> /etc/sysctl.conf
      echo "net.netfilter.nf_conntrack_tcp_timeout_fin_wait=120" >> /etc/sysctl.conf
      sysctl -p

五、iptables应用

1、防火墙

①防止ACK欺骗

拒绝TCP标记为SYN/ACK但连接状态为NEW的数据包,

iptables -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j DROP

②防止TCP Null扫描

iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

③防止Xmas扫描

iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP

④限流/防止端口DoS攻击

iptables -A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
# -m limit: 启用limit扩展,限制速度。
# --limit 25/minute: 允许最多每分钟25个连接
# --limit-burst 100: 当达到100个连接后,才启用上述25/minute限制

⑤限制主机服务时间

在工作时间,即周一到周五的8:30-18:00,开放本机的ftp服务给 192.168.1.0网络中的主机访问;并且数据下载请求的次数每分钟不得超过 5 个;

iptables -A INPUT -p tcp --dport 21 -s 192.168.1.0/24 -m time ! --weekdays 6,7 -m time --timestart 8:30 --timestop 18:00 -m connlimit --connlimit-above 5 -j ACCET

⑥丢弃无效数据包

iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

⑦关键词屏蔽

iptables -I FORWARD -p udp --dport 53 -m string --string "tencent" -m time --timestart 8:15 --timestop 20:30 --days Mon,Tue,Wed,Thu,Fri,Sat -j DROP
iptables -I FORWARD -p udp --dport 53 -m string --string "TENCENT" -m time --timestart 8:15 --timestop 20:30 --days Mon,Tue,Wed,Thu,Fri,Sat -j DROP
iptables -I FORWARD -p udp --dport 53 -m string --string "qq.com" -m time --timestart 8:15 --timestop 20:30 --days Mon,Tue,Wed,Thu,Fri,Sat -j DROP iptables -I FORWARD -s 10.113.0.0/24 -m string --string "ay2000.net" -j DROP # 关键词屏蔽
iptables -I FORWARD -s 10.113.0.0/24 -m string --string "eroticism" -j DROP

⑧防止外网使用内网IP欺骗

iptables -t nat -A PREROUTING -i eth0 -s 10.0.0.0/8 -j DROP
iptables -t nat -A PREROUTING -i eth0 -s 172.16.0.0/12 -j DROP
iptables -t nat -A PREROUTING -i eth0 -s 192.168.0.0/16 -j DROP

⑨禁Ping

# 允许本机ping别的主机;但不开放别的主机ping本机;
iptables -A OUTPUT -p icmp --icmp-type 8 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT

2、NAT网络地址转换

iptable上中包含一个NAT表,其中有两条缺省的PREROUTING和 POSTROUTING 链,在这两条链上配置规则可以实现NAT功能。

①SNAT源地址目标转换

概念

SNAT(Source Network Address Translation)是指在数据包从网卡发送出去的时候,把数据包中的源地址部分替换为指定的IP。

适用于由局域网中的主机发起连接的情况。报文在经过NAT路由器时,将IP报文中的源IP地址转换为一个有效的广域网地址;在服务器给一个在私有网络中的主机返回响应报文时,目的IP地址就是这个局域网对外的广域网地址。报文到达NAT路由器的时候,路由器要将该报文分发给对应的主机,将IP报文的目的IP地址转换为私有网络地址

涉及到iptables中的链表

POSTROUTING链中的nat表

应用场景

局域网主机共享单个公网IP地址接入Internet

做法:

设置能上外网的那一台主机(192.168.1.2)的iptables,一旦接收到来自局域网(192.168.1.0/24)的数据,修改数据包的源IP地址为本机IP地址,然后就转发出去。

前提

  • 有公网IP地址绑定

  • 内核设置net.ipv4.ip_forward=1,开起路由转发功能

  • # 查看内核是否启用路由转发功能
    sysctl -a | grep "ip_forward" 或者 sysctl net.ipv4.ip_forward
    # “net.ipv4.ip_forward=1”即可表示成功开启 # 临时设置内核启用路由转发功能。重启失效
    sysctl -w net.ipv4.ip_forward=1 或者 echo 1 >/proc/sys/net/ipv4/ip_forward # 永久设置内核启用路由转发功能。
    echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p

Iptables 设置

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to 192.168.1.2

局域网内想上外网的主机或者路由器想添加自定义路由策略

route add 0.0.0.0 gw 192.168.1.2

②DNAT目标网络地址转换

DNAT(Destination Network Address Translation)是又称为“端口转发”,适用于由广域网上的主机发起连接的情况。当广域网的主机访问NAT路由器的广域网端口时,可以将NAT路由器的广域网的端口映射到局域网内的某个IP地址的某个端口,这样就可以实现广域网主机访问局域网内的资源。

iptables -t nat -I PREROUTING  -d 公网IP -p tcp  -m tcp  --dport 公网port  -j DNAT  --to-destination  10.10.223.12-10.10.223.20:8080(内网)

# 对于在云上绑定公网IP地址的ECS主机做DNAT,公网IP地址要写成ECS的内网地址。因为云厂商的公网IP也是使用SNAT实现的,通过公网IP访问ECS的所有流量请求,已经将目标地址改成ECS的内网地址啦。
# 例如阿里云上一台ECS绑定弹性公网IP地址123.11.12.13,内网地址为192.168.1.8,还有一台ECS,内网地址为192.168.1.9,上面部署了MYSQL。想通过弹性公网IP地址访问MySQL。则在192.168.1.8这台ECS中做DNAT的时候,可以这样配置
# iptables -t nat -I PREROUTING -d 192.168.1.8 -p tcp --dport 33306 -j DNAT --to-destination 192.168.1.9:3306

3、使用SystemD管理iptables规则

bash -c 'cat > /etc/systemd/system/iptables-nat.service << EOF
[Unit]
Before=network.target [Service]
Type=oneshot # DNAT iterms
ExecStart=/sbin/iptables -t nat -A PREROUTING -d 192.168.1.2 -p tcp --dport 3308 -j DNAT --to-destination 192.168.1.6:3306
# SNAT iterms
ExecStart=/sbin/iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to 192.168.1.2 # Delete DNAT and SNAT iterms
ExecStop=/sbin/iptables -t nat -D PREROUTING -d 192.168.1.2 -p tcp --dport 3306 -j DNAT --to-destination 192.168.1.6:3306
ExecStop=/sbin/iptables -t nat -D POSTROUTING -s 192.168.1.0/24 -j SNAT --to 192.168.1.2 [Install]
WantedBy=multi-user.target
EOF' && \
systemctl daemon-reload && \
systemctl start iptables-nat.service && \
iptables -L PREROUTING -t nat --line-numbers && \
iptables -L POSTROUTING -t nat --line-numbers && \
systemctl enable iptables-nat.service

4、ipset命令(ipset是通过IP集合的方式管理itables,提高iptables的控制效率)

六、常用设置

1、放行ssh端口:

  1 iptables -A INPUT -p tcp –dport 22 -j ACCEPT
2 iptables -A OUTPUT -p tcp –sport 22 -j ACCEPT

注:/etc/rc.d/init.d/iptables save,否则直接执行service iptables restart命令后, 刚才添加的将丢失.

2、解决iptables导致的脑裂问题

  1 iptables -A INPUT -i lo -j ACCEPT  允许来自于lo接口的数据包
2 iptables -A OUTPUT -o lo -j ACCEPT 允许向lo接口发送数据包
3 iptables -A INPUT -s 192.168.1.0/24 -d 224.0.0.18 -j ACCEPT #允许组播地址通信
4 iptables -A INPUT -s 192.168.1.0/24 -p vrrp -j ACCEPT #允许VRRP(虚拟路由器冗余协)通信

lo 是 loopback 的缩写,也就是环回地址网卡,linux主机向自身发送数据包时,实际上的数据包是通过虚拟的lo接口来发送接受的,而不会通过你的物理网卡 eth0/eth1。

3、将目的地址为gongan网10.11.1.18的8090端口的流量转到内网地址的192.168.1.100,目的端口为80。

需求:从windos终端(gonganwang主机)访问一个内网地址的服务

前提条件:

1、10.11.1.18所在服务器有个内网ip地址与192.168.1.100同网段,从10.11.1.18可以ping通192.168.1.100

2、远程windos终端可以ping通10.11.1.18

##开启路由转发

##临时
sysctl -w net.ipv4.ip_forward=1
echo "1" > /proc/sys/net/ipv4/ip_forward ##永久
vim /etc/sysctl.conf
net.ipv4.ip_forward=1

##目标地址转换

sudo iptables -t nat -A PREROUTING -p tcp -m tcp --dport 8090 -j DNAT --to-destination 192.168.1.100:80

##源地址转换(192.168.1.100/32:80网段的数据包SNAT成10.196.11.57的ip然后发出去)

sudo iptables -t nat -A POSTROUTING -d 192.168.1.100/32 -p tcp -m tcp --sport 80 -j SNAT --to-source 10.196.11.57

##MASQUERADE,地址伪装,算是snat中的一种特例,可以实现自动化的snat。

作用:从服务器的网卡上,自动获取当前ip地址来做NAT

sudo iptables -t nat -A POSTROUTING -j MASQUERADE
iptables -t nat -A PREROUTING -d 192.168.1.189 -p tcp --dport 80 -j DNAT --to-destination 1.1.1.2:80

iptables -t nat -A PREROUTING -d 192.168.1.189 -j DNAT --to-destination 1.1.1.2   将所有流量转发到内网主机

最终结果

(-A POSTROUTING -j MASQUERADE要放在最后)

 sudo  iptables  -S  -t nat
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P POSTROUTING ACCEPT
-P OUTPUT ACCEPT
-A PREROUTING -p tcp -m tcp --dport 8090 -j DNAT --to-destination 192.168.1.100:80
-A PREROUTING -p tcp -m tcp --dport 8500 -j DNAT --to-destination 192.168.1.100:8500
-A PREROUTING -p tcp -m tcp --dport 172 -j DNAT --to-destination 192.168.1.100:172
-A POSTROUTING -d 192.168.1.100/32 -p tcp -m tcp --sport 172 -j SNAT --to-source 10.196.12.56
-A POSTROUTING -d 192.168.1.100/32 -p tcp -m tcp --sport 80 -j SNAT --to-source 10.196.12.56
-A POSTROUTING -j MASQUERADE

xshell 隧道映射访问内网服务器也可实现相同的效果

4、禁止、放行ip

要封停一个IP(-I :插入规则)

iptables  -I  INPUT  -s  192.168.21.3  -j  DROP

要解封一个IP(-D :删除规则)

iptables  -D  INPUT  -s  IP地址  -j  DROP

七、iptables脚本

脚本1

# vim iptables.sh
#!/bin/bash #清空 filter 表和 nat 表
iptables -F
iptables -t nat -F #关掉 firewalld
systemctl stop firewalld &>/dev/null
systemctl disable firewalld &>/dev/null #以下两行允许某些调用 localhost 的应用访问
iptables -A INPUT -i lo -j ACCEPT #规则1
iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT #规则2 #以下一行允许从其他地方 ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT #规则3 #以下一行允许从其他主机、网络设备发送 MTU 调整的报文
#在一些情况下,例如通过 IPSec VPN 隧道时,主机的 MTU 需要动态减小
iptables -A INPUT -p icmp --icmp-type fragmentation-needed -j ACCEPT #规则4 #以下两行分别允许所有来源访问 TCP 80,443 端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT #规则5
iptables -A INPUT -p tcp --dport 443 -j ACCEPT #规则6 #以下一行允许所有来源访问 UDP 80,443 端口
iptables -A INPUT -p udp -m multiport --dports 80,443 -j ACCEPT #规则7 #以下一行允许 192.168.1.63 来源的 IP 访问 TCP 22 端口(OpenSSH)
iptables -A INPUT -p tcp -s 192.168.1.63 --dport 22 -j ACCEPT #规则8 #以下一行允许 192.168.1.3(发起SSH连接的系统对应网卡的IP) 来源的 IP 访问 TCP 22 端口(OpenSSH)
#如果是在远程终端跑本脚本,最好开启以下一行以防被踢掉
#另一种更加简便的方式:iptables -I INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.1.3 --dport 22 -j ACCEPT #规则9 #以下一行允许 192.168.1.26 来源的 IP 访问 UDP 161 端口(SNMP)
iptables -A INPUT -p udp -s 192.168.1.26 --dport 161 -j ACCEPT #规则10 #配置 NAT
#启用内核路由转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.conf
sysctl -p &>/dev/null #配置源地址转换 SNAT
#将 192.168.2.0/24 转换成 192.168.1.63
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -j SNAT --to 192.168.1.63 #规则11 #配置目的地址转换 DNAT
#将 192.168.1.63 的 80 端口请求转发到 192.168.2.2 的 80 端口
iptables -t nat -A PREROUTING -d 192.168.1.63 -p tcp --dport 80 -j DNAT --to 192.168.2.2:80 #规则12 我们期望10.0.10.62为用户访问目标,而不是web服务192.168.0.110,但62上是没有web服务的,所以有人访问62的web服务必须将其转换到110上
iptables -t nat -A PREROUTING -d 10.0.10.62 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.110 #以下一行禁止所有其他的进入流量
iptables -A INPUT -j DROP #规则13 #以下一行允许本机响应规则编号为 1-12 的数据包发出
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT #规则14 #以下一行禁止本机主动发出外部连接
iptables -A OUTPUT -j DROP #规则15 #以下一行禁止本机转发数据包
iptables -A FORWARD -j DROP #规则16 #固化 iptables
iptables-save > /etc/sysconfig/iptables

脚本2

#!/bin/bash
#先允许
iptables -P INPUT ACCEPT #清除规则
iptables -F
#清除用户自定义规则 iptables -X
#清除链的计数器 iptables -Z
#开启回环网络
iptables -A INPUT -i lo -j ACCEPT && iptables -A OUTPUT -o lo -j ACCEPT #允许ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT #允许2-7访问
iptables -A INPUT -p tcp -m iprange --src-range 192.168.202.2-192.168.202.7 -j ACCEPT #允许163-168访问22端口(ssh连接)
iptables -A INPUT -p tcp -m iprange --src-range 137.64.70.163-137.64.70.168 --dport 22 -j ACCEPT #4A地址
iptables -A INPUT -p tcp -m iprange --src-range 137.64.35.151-137.64.35.156 -j ACCEPT #只允许主机共享rpc服务
iptables -A INPUT -p tcp -m iprange --src-range 192.168.202.2-192.168.202.7 --dport 111 -j
ACCEPT #只允许主机访问es
iptables -A INPUT -p tcp -m iprange --src-range 192.168.202.2-192.168.202.7 --dport 9200 -j ACCEPT #允许主机访问2375端口
iptables -A INPUT -p tcp -m iprange --src-range 192.168.202.2-192.168.202.7 --dport 2375 -j ACCEPT #只在164执行
iptables -A INPUT -p tcp -m iprange --src-range 137.64.76.179 --dport 28081 -j ACCEPT #开发8080端口(只在164执行)
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT #在屏蔽
iptables -P INPUT DROP #所有出站一律绿灯
iptables -P OUTPUT ACCEPT #所有转发一律丢弃
iptables -P FORWARD ACCEPT #保存
iptables-save

脚本3、iptables自动封查IP、解禁ip
iptables是采用数据包过滤机制工作的,所以它会对请求的数据包的包头数据进行分析,并根据我们预先设定的规则进行匹配来决定是否可以进入主机。

# more nginx_ip.sh
#!/bin/bash
. /etc/init.d/functions
conut=100
Path=/usr/local/nginx/logs/access.log function ipt(){
awk '{print $1}'$Path|sort|uniq -c|sort -rn >/tmp/tmp.log
exec < /tmp/tmp.log
while read line
do
ip=echo $line|awk '{print $2}'
if [ echo $line|awk '{print $1}' -ge $conut -a iptables -L -n|grep "$ip"|wc -l -lt 1 ]
then
iptables -I INPUT -s $ip -j DROP
RETVAL=$?
if [ $RETVAL -eq 0 ]
then
action "iptables -I INPUT -s $ip -j DROP" /bin/true
echo "$ip" >>/tmp/ip_$(date +%F).log
else
action "iptables -I INPUT -s $ip -j DROP" /bin/false
fi
fi
done
}
function del(){
[ -f /tmp/ip_$(date +%F -d '-1 day').log ]||{
echo "log is not exist"
exit 1}
exec </tmp/ip_$(date +%F -d '-1 day').log
while read line
do
if [ iptables -L -n|grep "$line"|wc -l -ge 1 ]
then
iptables -D INPUT -s $line -j DROP
fi
done
}
function main(){
flag=0
while true
do
sleep 180
((falg++))
ipt
[ $flag -ge 480 ] && del && flag=0
done
}
main

更好的方法:nginx+lua拦截IP,或者搭建软件防火强的方法。

脚本4:iptables自动屏蔽访问网站频繁的IP

场景:恶意访问,安全防范

1)屏蔽每分钟访问超过200的IP
方法1:根据访问日志(Nginx为例)
#!/bin/bash
DATE=$(date +%d/%b/%Y:%H:%M)
ABNORMAL_IP=$(tail -n5000 access.log |grep $DATE |awk '{a[$1]++}END{for(i in a)if(a[i]>100)print i}')
#先tail防止文件过大,读取慢,数字可调整每分钟最大的访问量。awk不能直接过滤日志,因为包含特殊字符。
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done 方法2:通过TCP建立的连接
#!/bin/bash
ABNORMAL_IP=$(netstat -an |awk '$4~/:80$/ && $6~/ESTABLISHED/{gsub(/:[0-9]+/,"",$5);{a[$5]++}}END{for(i in a)if(a[i]>100)print i}')
#gsub是将第五列(客户端IP)的冒号和端口去掉
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done 2)屏蔽每分钟SSH尝试登录超过10次的IP
方法1:通过lastb获取登录状态:
#!/bin/bash
DATE=$(date +"%a %b %e %H:%M") #星期月天时分 %e单数字时显示7,而%d显示07
ABNORMAL_IP=$(lastb |grep "$DATE" |awk '{a[$3]++}END{for(i in a)if(a[i]>10)print i}')
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done 方法2:通过日志获取登录状态
#!/bin/bash
DATE=$(date +"%b %d %H")
ABNORMAL_IP="$(tail -n10000 /var/log/auth.log |grep "$DATE" |awk '/Failed/{a[$(NF-3)]++}END{for(i in a)if(a[i]>5)print i}')"
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -A INPUT -s $IP -j DROP
echo "$(date +"%F %T") - iptables -A INPUT -s $IP -j DROP" >>~/ssh-login-limit.log
fi
done

脚本5:根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁

#!/bin/bash
####################################################################################
#根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁
####################################################################################
logfile=/data/log/access.log
#显示一分钟前的小时和分钟
d1=`date -d "-1 minute" +%H%M`
d2=`date +%M`
ipt=/sbin/iptables
ips=/tmp/ips.txt
block()
{
#将一分钟前的日志全部过滤出来并提取IP以及统计访问次数
grep '$d1:' $logfile|awk '{print $1}'|sort -n|uniq -c|sort -n > $ips
#利用for循环将次数超过100的IP依次遍历出来并予以封禁
for i in `awk '$1>100 {print $2}' $ips`
do
$ipt -I INPUT -p tcp --dport 80 -s $i -j REJECT
echo "`date +%F-%T` $i" >> /tmp/badip.log
done
}
unblock()
{
#将封禁后所产生的pkts数量小于10的IP依次遍历予以解封
for a in `$ipt -nvL INPUT --line-numbers |grep '0.0.0.0/0'|awk '$2<10 {print $1}'|sort -nr`
do
$ipt -D INPUT $a
done
$ipt -Z
}
#当时间在00分以及30分时执行解封函数
if [ $d2 -eq "00" ] || [ $d2 -eq "30" ]
then
#要先解再封,因为刚刚封禁时产生的pkts数量很少
unblock
block
else
block
fi

上文用到的while读取文件的方法做一点补充

1、管道的方式

cat /tmp/a.log |while read LINE
do
echo $LINE
done

2、重定向的方式(速度较快)

while read LINE
do
echo $LINE
done < /tmp/a.log

3、文件描述符法

exec </tmp/a.log

while read line
do
echo $line
done

iptables详解 · Devops Roadmap (curiouser.top)    很全面

https://devopstack.cn/linux/871.html   Iptables 限制连接数(如SFTP) 以及 谨防CC/DDOS攻击的配置 ( connlimit模块)

 

iptables( < deb ufw)的更多相关文章

  1. ubuntu 中 iptables 和 ufw 的关系

    我突然发现,自己平常使用的 iptables 和 ufw 到底是啥关系?平常其实iptables和ufw在配置防火墙,开启端口是,还是偶尔会使用到的. 没去思考过这两者是啥关系,哎...,这就不够好了 ...

  2. ubuntu防火墙ufw使用教程

    查看ubuntu版本cat /etc/issue或者lsb_release -a 防火墙 由于Linux原始的防火墙工具iptables过于繁琐,所以ubuntu默认提供了一个基于iptable之上的 ...

  3. ubuntu ufw防火墙

    由于LInux原始的防火墙工具iptables过于繁琐,所以ubuntu默认提供了一个基于iptable之上的防火墙工具ufw. ubuntu 9.10默认的便是UFW防火墙,它已经支持界面操作了.在 ...

  4. ubuntu ufw相关命令

    引自:http://www.cnblogs.com/jiangyao/archive/2010/05/19/1738909.html 就这句话就够了,下面的可以不看 sudo  ufw enable| ...

  5. ubuntu 默认防火墙安装、启用、查看状态

    ubuntu 9.10默认的是UFW防火墙,已经支持界面操作了.在命令行运行ufw命令就可以看到提示的一系列可进行的操作. 最简单的一个操作:sudo ufw status可检查防火墙的状态,我的返回 ...

  6. ubuntu默认防火墙

    ubuntu 9.10默认的是UFW防火墙,已经支持界面操作了.在命令行运行ufw命令就可以看到提示的一系列可进行的操作. 最简单的一个操作:sudo ufw status可检查防火墙的状态,我的返回 ...

  7. Linux 命令详解(十三)如何启动、关闭和设置ubuntu防火墙

    sudo  ufw enable|disable 由于LInux原始的防火墙工具iptables过于繁琐,所以ubuntu默认提供了一个基于iptable之上的防火墙工具ufw. ubuntu 9.1 ...

  8. Ubuntu防火墙配置

    转载自:http://blog.csdn.net/sumer0922/article/details/7485584Ubuntu11.04默认的是UFW(ufw 即uncomplicated fire ...

  9. 如何启动、关闭和设置ubuntu防火墙

    如何启动.关闭和设置ubuntu防火墙 引自:http://www.cnblogs.com/jiangyao/archive/2010/05/19/1738909.html 就这句话就够了,下面的可以 ...

  10. Ubuntu 16.04搭建OpenVPN服务器以及客户端的使用

    说明:启动时注意用户权限,比如root用户启动. Ubuntu: 服务器环境:Ubuntu 16.04 64位系统 内网IP:10.143.80.116 外网IP:203.195.1.2 OpenVP ...

随机推荐

  1. P12_小程序API的3大分类

    小程序 API 概述 小程序中的 API 是由宿主环境提供的,通过这些丰富的小程序 API,开发者可以方便的调用微信提供的能力,例如:获取用户信息.本地存储.支付功能等. 小程序 API 的 3 大分 ...

  2. 安装CUDA

    https://developer.nvidia.com/cuda-toolkit-archive 使用deb安装的话,有时会报错: dpkg: 处理软件包 nvidia-driver-450 (-- ...

  3. rosdep update 一直失败问题

    1.排除网络问题 2.增加TIMEOUT的时间: 更改 /usr/lib/python2.7/dist-packages/rosdep2/下的三个文件sources_list.py.gbpdistro ...

  4. SQL性能优化的47个小技巧,你了解多少?

    大家好,我是哪吒. 1.先了解MySQL的执行过程 了解了MySQL的执行过程,我们才知道如何进行sql优化. 客户端发送一条查询语句到服务器: 服务器先查询缓存,如果命中缓存,则立即返回存储在缓存中 ...

  5. LeetCode 周赛 333,你管这叫 Medium 难度?

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 上周是 LeetCode 第 333 场周赛,你参加了吗?这场周赛质量很高,但难度标得不 ...

  6. 消息传递(news)题解

    代码 #include<cstdio> #include<algorithm> using namespace std; const int N = 200000; int f ...

  7. JZOJ 4320. 【NOIP2015模拟11.5】旅行

    题目 思路 不想写了,直接使用 没错,关键就在求第 \(k\) 小的路径 上述提到堆的做法,我们可以用 \(STL\) 的优先队列来实现 只不过常数有点大~~~ \(Code\) #include&l ...

  8. cowtransfer(奶牛快传)自动上传文件脚本—流程分析

    cowtransfer(奶牛快传)自动上传文件脚本-流程分析 序言: 距离上传发文也有几天了,这几天也是将这个脚本优化了一下.如果还不清楚这个脚本的效果是怎么样的小伙伴可以看看我上篇文章.话不多说,我 ...

  9. pat乙级 1017 A除以B 模拟除法

    #include <stdio.h> #define MAX_A 1000 int A[MAX_A]; int B; /* 除数 */ int num; /* A 被除数有多少位 */ v ...

  10. InputManager

    inputManger配置参数说明 https://www.cnblogs.com/xiaoyulong/p/10011256.html 配置方法 https://www.cnblogs.com/td ...