Linux Iptables

Linux Iptables shell Firewalld

Posted by gomyck on July 20, 2023

iptables 是 Linux 系统上的一个防火墙工具,它可以通过过滤和转发数据包来实现防火墙的功能。

iptables 匹配是从上至下的, 如果匹配, 则停止向下匹配, 这对于使用 -I 和 -A 来添加规则是有很大区别的

iptables -n nat -nL 和 iptables -n nat -L 有 DNS 解析上的区别, 不加 n 的指令, 在显示时会很慢

1
2
3
4
5
6
7
   iptables -ADC  指定链的规则  [-A  添加 -D 删除 -C 修改]
   iptables -t nat -I PREROUTING 2 [新规则内容]
   iptables -D chain rule num[option]        删除规则
   iptables -LFZ 链名 [选项]                  清空链
   iptables -[NX]                            指定链   N:添加链  X:删除链
   iptables -P [chain] [target][options]     iptables -P FORWARD DROP
   iptables -E old-chain-name new-chain-name

iptables

iptables -> tables -> chains -> rules

iptables 有五张表: filter、nat、mangle、raw、security, filter 是我们常用的表, 也是默认的操作表, 其内的 INPUT 和 OUTPUT 是常用链

每张表都有本身的作用, 比如 nat 用作地址转换用, 其中的链的生命周期也和 NAT 相关 比如 INPUT、OUTPUT、FORWARD、PREROUTING 和 POSTROUTING

1
$ iptables -t nat -nL | grep Chain

自定义的链, 必须被内置链引用才可生效, 具体要被哪条链引用, 取决于当前自定义的链要在请求的哪个阶段被使用, 比如想在出站时使用

1
2
3
$ iptables -N OUTBOUND_RULES
$ iptables -A OUTBOUND_RULES -d [目标IP] -p tcp --dport [目标端口] -j ACCEPT
$ iptables -A OUTPUT -j OUTBOUND_RULES

保存 iptables 的配置

1
$ iptables-save > /etc/iptables/rules.v4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 在 INPUT 链中添加 网卡 eth0 tcp 协议 22 端口的规则为放行
$ iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
# 在 INPUT 中添加丢弃其他包, 应放在 INPUT 最后一条
$ iptables -A INPUT -j DROP
# 查看所有链的 rules, 并显示行号
$ iptables -L --line-numbers
# 删除 docker 第一行规则, 这时第二行会变成第一行
$ iptables -D DOCKER 1
# 精确删除规则
$ iptables -D DOCKER -s ${ip} -p tcp --dport 5432 -j ACCEPT
# 清空规则
$ iptables -F
# 保存规则
$ iptables-save > /path/to/file
# 加载规则
$ iptables-restore < /path/to/file
# 允许拒绝 链所有流量
$ iptables -P <chain_name> ACCEPT | DROP
# 添加链
$ iptables -t filter -N <chain_name>
# 端口映射
$ iptables -t nat -A PREROUTING -i [接口名称] -p [协议] --dport [目标端口] -j DNAT --to-destination [目标IP]:[目标端口]

docker 会自动维护 iptables 规则, 名字是 DOCKER 的链, 对于端口映射的规则, 会在 DOCKER 链中添加规则

iptables 的规则会在 docker 重启之后重新生成, 并且覆盖 firewall 的规则

如果需要对指定的端口添加规则, 则需要使用 -I 来添加单独的规则

1
2
3
4
5
6
7
# 执行顺序不能乱, 否则会导致5432的拒绝规则在第一位

# 其他的 ip 禁止访问  5432:5432 可以简化成  5432  他是个区间范围
$ sudo iptables -I DOCKER  -p tcp --dport 5432:5432 -j DROP
# 向 docker第一行添加 5432 只允许 99 访问
$ iptables -I DOCKER  -p tcp --dport 5432 -s 192.168.99.99 -j ACCEPT

脚本:

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
#!/bin/bash

ips="
192.168.99.99
192.168.104.3
192.168.3.123
"

function init() {
  iptables -I DOCKER -p tcp --dport 5432 -j DROP
  iptables -I DOCKER -p udp --dport 5432 -j DROP

  for ip  in ${ips}
  do
    iptables -I DOCKER -s ${ip} -p tcp --dport 5432 -j ACCEPT
    iptables -I DOCKER -s ${ip} -p udp --dport 5432 -j ACCEPT
  done
}

function del() {
  iptables -D DOCKER -p tcp --dport 5432 -j DROP
  iptables -D DOCKER -p udp --dport 5432 -j DROP

  for ip  in ${ips}
  do
    iptables -D DOCKER -s ${ip} -p tcp --dport 5432 -j ACCEPT
    iptables -D DOCKER -s ${ip} -p udp --dport 5432 -j ACCEPT
  done
}

if [ "$1" == "init" ]; then
  echo '正在初始化...'
  init
elif [ "$1" == "del" ]; then
  echo '正在删除...'
  del
else
  echo "Usage: $0 [init|del]"
fi

端口映射

需要将外网访问本地IP(192.168.75.5)的80端口转换为访问192.168.75.3的8000端口,这就需要用到iptables的端口映射

实现:

需要先开启linux的数据转发功能

1
2
$ vi /etc/sysctl.conf,将net.ipv4.ip_forward=0更改为net.ipv4.ip_forward=1
$ sysctl -p  //使数据转发功能生效

更改iptables,使之实现nat映射功能

1
2
3
4
#将外网访问192.168.75.5的80端口转发到192.168.75.3:8000端口。
# iptables -t nat -A PREROUTING -d 192.168.75.5 -p tcp --dport 80 -j DNAT --to-destination 192.168.75.3:8000
#将192.168.75.3 8000端口将数据返回给客户端时,将源ip改为192.168.75.5
# iptables -t nat -A POSTROUTING -d 192.168.75.3 -p tcp --dport 8000 -j SNAT --to 192.168.75.5

查看nat,可以使用命令:iptables -t nat –list检查nat列表信息

以上是针对从一台机到另一台机的端口转发,如果要针对本机进行端口转发,就需要按如下操作:

1
2
3
4
5
6
# 将外网访问80端口的数据转发到8080端口
$ iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
# 将本机访问80端口的转发到本机8080
$ iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j DNAT --to 127.0.0.1:8080
$ iptables -t nat -A OUTPUT -p tcp -d 192.168.4.177 --dport 80 -j DNAT --to 127.0.0.1:8080

本地连接指的是在本机上,用 127.0.0.1 或者本机 IP 来访问本机的端口。本地连接的数据包不会通过网卡,而是由内核处理后直接发给本地进程。 这种数据包在 iptables 中只经过 OUTPUT 链,而不会经过 PREROUTING 链。所以需要在 OUTPUT 链中进行 DNAT。除了对 127.0.0.1 之外, 对本机 IP (即 192.168.4.177) 的访问也属于本地连接。