Iptables加固服务器安全
包过滤防火墙(四层)、状态防火墙 主要针对网络访问
一、安全体系概览
Firewalls --->TCP Wrappers ---> Xinetd ---> PAM ---> SELinux ---> Server specific
二、预备知识:OSI 七层模型
HOST_A firefox(封装)------------------------------> httpd server(解封装)HOST_B
应用层------- ftp http smtp pop3 nfs cifs ssh dns ------- 应用层
表示层 表示层
会话层 会话层
传输层 TCP、UDP s_port:xxxx --> d_port:80 传输层
网络层 IP、ICMP、ARP s_IP:192.168.9.9 --> d_IP:192.168.9.99 网络层
数据链路层 s_mac:xxxxxxxxx --> d_mac:xxxxxxxxx 数据链路层
物理层 物理层
TCP: 面向连接,可靠的传输协议 类似于三次握手,四次挥手,window,确认,重传......
UDP:非面向连接,不可靠的传输协议
三、Firewall: netfilter/iptables
netfilter组件 内核空间,是内核一部分
iptables组件 用户空间,提供管理防火墙的手段,通过iptables插入、删除、修改规则
四、四张表、五条链
raw ---> mangle ---> nat ---> filter
raw 主要做连接追踪 PREROUTING、OUTPUT
mangle 对数据包进行修改,例如给数据包打标记MARK INPUT、OUTPUT、FORWARD、PREROUTING、POSTROUTING
nat 主要修改数据包的地址和端口,例如源地址或目标地址 INPUT、OUTPUT、PREROUTING、POSTROUTING
filter 实现对数据包的过滤 INPUT、OUTPUT、FORWARD
示例:
iptables -L
iptables -t filter -L
iptables -t nat -L
iptables -t raw -L
iptables -t mangle -L
五、iptables 语法
iptables [-t 要操作的表] <操作命令> [要操作的链] [规则号码] [匹配条件] [-j 匹配后的动作]
小写 大写 大写 小写 大写
表及应用顺序:raw ---> mangle ---> nat ---> filter
常用操作命令:
-L 查看,v详细,n不反解 --line-number 加行号
-A 追加,放置到最后一条
-I 插入,默认插入到第一条
-D 删除
-F 清空flush
-X 删除空的自定义链
-P 设置默认策略
-Z 计数器归零
-m 匹配
要操作的链:
INPUT
OUTPUT
FORWARD
PREROUTING
POSTROUTING
基本匹配:
-s xx.xx.xx.xx 源地址
-d xx.xx.xx.xx 目标地址
-p tcp|udp|icmp 协议
-i eth0 input从eth0接口进入的数据包
-o eth0 output从eth0接口出去的数据包
-p tcp --sport 80 源端口是80的数据包
-p tcp --dport 80 目标端口是80,必须和-p tcp|udp 连用
基本动作Target
filter:
-j ACCEPT 接受 filter
-j REJECT 拒绝 filter
-j DROP 丢弃 filter
-j LOG 记录日志 filter
nat:
-j SNAT 源地址转换 nat POSTROUTING链
-j MASQUERADE 伪装 nat
-j DNAT 目标地址转换 nat 目标地址及端口映射(转换) PREROUTING链
-j REDIRECT 端口转换 nat 本地端口转换(本机)
mangle:
-j MARK 标记 mangle
示例:# iptables -t filter -A INPUT -s 192.168.1.0/24 -j SNAT --to 1.1.1.1 错误 因为filter 表不支持SNAT源地址转换动作
六、iptables 应用示例
iptables -F 清空filter表链上的所有规则。默认表是filter表
iptables -A INPUT -j REJECT filter表input链拒绝所有 先堵后通
iptables -A INPUT -j ACCEPT 先通后堵
iptables -I INPUT -p tcp --dport 80 -j ACCEPT 访问80端口的允许,插入到链第一条,默认用拒绝所有。
iptables -I INPUT -p tcp --dport 22 -j ACCEPT 访问22端口的允许,插入到链第一条
iptables -I INPUT -p icmp -j ACCEPT 允许使用icmp协议,可以ping.
iptables -I INPUT 2 -p tcp --dport 20:21 -j ACCEPT 允许TCP 20 21端口,插入到第二条 FTP主动模式可用,被动模式不可用
service iptables save 保存
本机无法访问本机无法ping通:iptables -I INPUT -i lo -j ACCEPT
本机无法主访问其他主机ssh不通:iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
FTP无法访问:被动模式:
iptables -I INPUT -p tcp --dport 20:21 -j ACCEPT 指定FTP pasv端口 50000-60000
iptables -I INPUT -p tcp --dport 50000:60000 -j ACCEPT
或使用连接追踪模块:
iptables -I INPUT -p tcp --dport 20:21 -j ACCEPT
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
modprobe nf_conntrack_ftp 加载连接追踪模块(临时)
vim /etc/sysconfig/iptables-config 开机自动加载
IPTABLES_MODULES="nf_conntrack_ftp"
nf_conntrack_ftp:针对数据端口连接时,将三次握手第一次的状态由NEW识别成RELATED
七、扩展匹配 MATCH EXTENSIONS
iptables -m icmp -h //从后往前查看 icmp 所有状态
iptables -m iprange -h //从后往前查看 iprange 所有状态
yum -y install vsftpd httpd //安装vsftpd httpd两个服务举例
service httpd start; service vsftpd start; service sshd start //启动服务
iptables -F 清空防火墙
iptables -A INPUT -j REJECT
• -m icmp
# iptables -t filter -I INPUT -p icmp -m icmp --icmp-type echo-reply -j ACCEPT //允许icmp协议的echo-reply状态回应
• -m iprange
# iptables -t filter -I INPUT -m iprange --src-range 192.168.2.20-192.168.2.100 -j REJECT //允许此IP段的源IP地址INPUT
• -m multiport
# iptables -t filter -I INPUT -p tcp -m multiport --dports 20,21,22,25,80,110 -j ACCEPT //多端口访问允许
• -m state 跟TCP中的状态没有关系
NEW 新生态
ESTABLISHED 连接态
RELATED 衍生态
INVALID 无效态
# iptables -t filter -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT //允许此三个状态的访问通过
实验: 使用状态防火墙,放行本机FTP服务[被动模式]
# iptables -t filter -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -t filter -I INPUT -p tcp --dport 20:21 -j ACCEPT
# iptables -t filter -A INPUT -j REJECT
# modprobe nf_conntrack_ftp
# vim /etc/sysconfig/iptables-config
IPTABLES_MODULES="nf_conntrack_ftp"
小结: 该内核模块的作用是在<连接数据端口时>,将第一次握手的数据包状态由原来的 NEW 识别成 RELATED
• -m tos //ip协议头部type of service
# iptables -F
# tcpdump -i eth0 -nn port 22 -vvv //抓取远程主机访问本机ssh数据包,分 别于输入密码前和后观察TOS值
# tcpdump -i eth0 -nn port 22 -vvv //抓取远程从本机rsync或scp复制文件, 分别于输入密码前和后观察TOS值
小结:都是使用22/tcp,但可以通过IP报文中的TOS值来区分应用
ssh: tos 0x0 0x10
scp: tos 0x0 0x8
rsync: tos 0x0 0x8
# iptables -m tos -h
# iptables -t filter -A INPUT -p tcp --dport 22 -m tos ! --tos 0x10 -j ACCEPT //仅拒绝客户端ssh到本机
# iptables -t filter -A INPUT -j REJECT
• -m tcp 按TCP标记匹配
Flags are: SYN ACK FIN RST URG PSH ALL NONE
# iptables -t filter -A INPUT -p tcp -m tcp --tcp-flags SYN,ACK,FIN,RST SYN -dport 80 -j ACCEPT
# iptables -t filter -A INPUT -p tcp --syn --dport 80 -j ACCEPT --tcp-flags SYN,ACK,FIN,RST SYN // 检查四个标记位SYN,ACK,FIN,RST,但只有SYN标记位才匹配 则允许三次握手中的第一次握手,等价于 --syn
• -m limit 限制
实验:从客户端ping本机,观察序列号
# iptables -F
# iptables -t filter -A INPUT -p icmp -m limit --limit 20/minute -j ACCEPT
# iptables -t filter -A INPUT -j REJECT
进入本机INPUT链的ICMP,如果匹配第一条则放行,不匹配的将被第二条拒绝,默认前5个 不限
16/second
16/minute
16/hour
16/day
# iptables -t filter -A INPUT -p tcp --syn --dport 80 -m limit --limit 50/second j ACCEPT
# iptables -t filter -A INPUT -j REJECT
• -m connlimit 限同一IP最大连接数
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A INPUT -p tcp --syn --dport 22 -m connlimit ! --connlimit-above 2 -j ACCEPT //仅允许每个客户端有两个ssh连接
等价于:# iptables -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 2 -j REJECT //超过两个连接拒绝
# iptables -A INPUT -p tcp --syn --dport 80 -m connlimit ! --connlimit-above 100 -j ACCEPT //仅允许每个客户端有100个requests
# iptables -A INPUT -j REJECT
• -m time
# iptables -A INPUT -m time --timestart 12:00 --timestop 13:00 -j ACCEPT
# iptables -A INPUT -p tcp --syn --dport 22 -m time --timestart 12:00 -timestop 13:00 -j ACCEPT
# iptables -A INPUT -j REJECT
• -m comment
# iptables -A INPUT -s 172.16.130.7 -m comment --comment "cloud class" -j REJECT //按照描述匹配
• -m mark
# iptables -t filter -A INPUT -m mark --mark 2 -j REJECT
八、动作扩展 TARGET EXTENSIONS
• filter:
-j ACCEPT
-j DROP
-j REJECT
-j LOG
• nat:
-j SNAT //转换源地址
-j MASQUERADE //转换源地址
-j DNAT //转换目标地址及端口
-j REDIRECT //转换目标端口(重定向)
• mangle:
-j MARK
• -j LOG
# grep 'kern.*' /etc/rsyslog.conf
kern.* /var/log/kernel.log //确定内核日志功能开启并把Log文件放在/var/log/kernel.log
# service rsyslog restart //重启日志服务
# iptables -j LOG -h //
# iptables -t filter -A INPUT -p tcp --syn --dport 22 -j LOG --log-prefix " tianyun_ssh " //满足条件的日志加前缀
# iptables -t filter -A INPUT -p tcp --syn --dport 22 -j ACCEPT //实际允许规则,上一条只是日志规则,日志必须放上实际规则上面
# iptables -t filter -A INPUT -j REJECT
• -j REJECT
当访问一个未开启的TCP端口时,应该返回一个带有RST标记的数据包
当访问一个未开启的UDP端口,结果返回port xxx unreachable
当访问一个开启的TCP端口,但被防火墙REJECT,结果返回port xxx unreachable
# iptables -j REJECT -h 查看帮助
# iptables -t filter -A INPUT -p tcp --dport 22 -j REJECT --reject-with tcpreset //返回一个自定义消息类型
• -j MARK
# iptables -t mangle -L
# iptables -j MARK -h
# iptables -t mangle -A PREROUTING -s 192.168.2.110 -j MARK --set-mark 1
# iptables -t mangle -A PREROUTING -s 192.168.2.25 -j MARK --set-mark 2
# iptables -t filter -A INPUT -m mark --mark 1 -j ACCEPT //按照标记匹配
# iptables -t filter -A INPUT -m mark --mark 2 -j REJECT
• NAT表:
POSTROUTING: SNAT, MASQUERADE
PRETROUTING: DNAT, REDIRECT
OUTPUT: DNAT,针对本机
• 让KVM虚拟机访问外部网络(默认):-j SNAT/MASQUERADE [必须开启kernel ip_forward]
# iptables -t nat -F
# iptables -F
路由之后做源地址转换:
# iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j SNAT --to 外部地址 //不常用
# iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE //常用规则
• 暴露KVM虚拟机的服务(端口映射): -j DNAT [必须开启kernel ip_forward]
# iptables -t nat -A PREROUTING -d 172.16.30.30 -p tcp --dport 80 -j DNAT -to 192.168.122.66:80
# iptables -t nat -A PREROUTING -d 172.16.30.30 -p tcp --dport 8080 -j DNAT --to 192.168.122.77:80
# iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to 192.168.122.66:22
# iptables -t nat -A PREROUTING -d 172.16.30.240 -p tcp --dport 80 -j DNAT -to 192.168.122.66
# iptables -t nat -A PREROUTING -d 172.16.30.240 -p tcp --dport 22 -j DNAT -to 192.168.122.66
# iptables -t nat -A PREROUTING -d 172.16.30.241 -p tcp --dport 80 -j DNAT -to 192.168.122.67
# iptables -t nat -A PREROUTING -d 172.16.30.241 -p tcp --dport 22 -j DNAT -to 192.168.122.67
为接口绑定地址
# ip addr add dev eth0 172.16.30.240/24
# ip addr add dev eth0 172.16.30.241/24
• -j REDIRECT //本地端口转发
# iptables -t nat -A PREROUTING -s 172.16.130.0/24 -p tcp --dport 8888 -j REDIRECT --to-ports 22