iptables
原理
由来
ipfw -> ipchains -> iptables
组成
iptables/netfilter netfilterIP/TCP协议栈内核本身具备的 framework:netfilter提供钩子hooks function iptables是一个规则管理工具,负责增删查改netfilter规则的工具,工作在用户进程
表(功能)
filter 包过滤
nat 网络地址转换
mangle 拆解报文,做出修改,封装报文
raw 关闭nat表上启动的连接追踪机制
链(内置)
PREROUTING
INPUT
FORWARD
OUTPUT
POSTROUTING
报文流入
PREROUTING -> INPUT
报文流出
OUTPUT -> POSTROUTING
报文转发
PREROUTING -> FORWARD -> POSTROUTING
各功能实现
filter
INPUT, OUTPUT, FORWARD
nat
PREROUTING(DNAT),OUTPUT , POSTROUTING(SNAT)
mangle
PREROUTING, INPUT, OUTPUT ,POSTROUTING, FORWARD
raw
OUTPUT, PREROUTING(追踪通常在进入本机时关闭)
路由发生的时刻
报文进入主机后
判断目标主机
报文发出之前
判断经由哪个接口送往下一跳
iptables:四表五链
# 添加规则时的考量点 1. 要实现哪些功能,判断添加在哪张表上? 2. 报文流经的路径,判断添加在哪个链上? # 链,链上的规则次序,即为检查的次序,因此隐含一定的法则 1. 同类规则,匹配规则小的放上面 2. 不同类规则,匹配频率大的放上面 3. 将可以合并的同种规则合并为一个 4. 设置默认策略
链功能生效次序
对于PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING链
raw -> mangle -> nat -> filter
规则
组成:报文的匹配条件 + 匹配到之后的处理动作
匹配条件:根据协议报文特征指定
基本匹配条件
扩展匹配条件
处理动作
内建处理机制
自定义处理机制
报文不会经过自定义链,只能在内置链上通过规则引用后生效
链管理
-F:flush,清空规则链,省略链,表示清空指定表上的所有链 iptables [-t table] -F [chain [rulenum]] [options...] -N:new,创建新的自定义规则链 iptables [-t table] -N chain -X:drop,删除用户自定义的空的规则链 iptables [-t table] -X [chain] -Z:zero,清零,置零规则计数器 iptables [-t table] -Z [chain [rulenum]] [options...] -P:Policy,为指定链设置默认策略,对于filter表中的链而言,默认策略有ACCEPT,DROP,REJECT iptables [-t table] -P chain target -E:rename,重命名自定义链,被引用的链(引用计数不为0)无法改名,也无法删除 iptables [-t table] -E old-chain-name new-chain-name
规则管理
-A:append,将新规则添加到指定链的尾部 iptables [-t table] -A chain rule-specification -I:insert,将新规则插入指定链的指定位置,不指定rulenum为1 iptables [-t table] -I chain [rulenum] rule-specification -D:delete,删除指定链上的指定规则 1. 指定匹配条件 iptables [-t table] -D chain rule-specification 2. 指定规则编号 iptables [-t table] -D chain rulenum -R:replace,替换指定链上的指定规则 iptables [-t table] -R chain rulenum rule-specification -L:list,列出指定链上的所有规则 -n:numberic,以数字格式显示地址和端口 -v:verbose,显示详细信息 --line-numbers:显示规则编号 -x:exactly,显示计数器计数结果的精确值 iptables -L {-n|-v|--line-numbers|-x}
匹配条件
基本条件
[!] -s, --src, --source IP|Netaddr:检查报文中的源IP地址是否符合此处指定的地址范围 [!] -d, --dst, --destination IP|Netaddr:检查报文中源IP地址是否符合此处指定的地址范围 -p, --protocol{tcp|udp|icmp}:检查报文中的协议,即IP报文首部中procotol标识的协议 -i, --in-interface IFACE:数据报文的流入接口,仅能用于INTPUT,PREROUTING,FORWARD链 -o, --out-intfacle IFACE:数据报文的流出接口,仅能用于FORWARD,OUTPUT,POSTROUTING链
TARGET
-j TARGET:jump至指定TARGET
ACCEPT(接受)
DROP(丢弃)
REJECT(拒绝)
RETURN(返回调用链)
REDIRECT(端口重定向)
LOG(记录日志)
MARK(做防火墙标记)
DNAT(目标地址转换)
SNAT(源地址转换)
MASQUERADE(地址伪装)
...
自定义链(由自定义链上的规则匹配)
扩展匹配 -m match_name --spec_options
隐式扩展(如果-p已经指明相应的协议了,那么-m可以不用指了)
-p tcp --dport PORT[-PORT]:目标端口,可以是单个端口或者连续多个端口 --sport PORT[-PORT]:源端口,可以是单个端口或者连续多个端口 --tcp-flags LIST1 LIST2:检测LIST1所指明的所有标志位,LIST2所指明的所有标志位必须为1,其余不LIST1中的必须为0,LIST1中没有指明的不检查 LIST1 SYN, ACK, FIN, RST, PSH, URG LIST2 [SYN,ACK,FIN,RST,PSH,URG] 例子 --tcp-flags SYN,ACK,FIN,URG SYN (--syn 检查1,0,0,0,) -p udp -p icmp --icmp-type 0: echo-reply 8: echo-request 例子:只允许自己ping别人,不允许别人ping自己 iptables -A OUTPUT -s 192.168.1.1 -p icmp --icmp-type 8 -j accept iptables -A INPUT -d 192.168.1.1 -p icmp --icmp-type 0 -j accept
显示扩展(必须使用-m指定使用的扩展)
multiport:以离散的方式定义多端口匹配,最多指定15个端口 指明多个源端口 [!] --source-ports,--sports port[,port|,port:port]... 指明多个目标端口 [!] --destination-ports,--dports port[,port|,port:port]... 同时指明源端口和目标端口 [!] --ports port[,port|,port:port]... 例子:同时开放22、80号端口 iptables -I INPUT -s 192.168.1.0/24 -d 192.168.1.1 -p tcp -m multiport --dport 22,80 -j ACCEPT iptables -I OUTPUT -s 192.168.1.1 -d 192.168.1.0/24 -p tcp -m multiport --sport 22,80 -j ACCEPT iprange:指明连续的(但一般是不能扩展整个网络)ip地址范围时使用 指明连续的源IP地址范围 [!] --src-range from[-to] 指明连续的目标IP地址范围 [!] --dst-range from[-to] 例子:同时允许192.168.1.1-192.168.1.200的IP地址访问22,23,80号端口 iptables -I INPUT -d 192.168.1.1 -p tcp -m multiport --dport 22:23,80 -m iprange --src-range 192.168.1.1-192.168.1.200 -j ACCEPT iptables -I OUTPUT -s 192.168.1.1 -p tcp -m multiport --sport 22:23,80 -m iprange --dst-range 192.168.1.1-192.168.1.200 -j ACCEPT string:匹配传送字节流中的字符串 --algo {bm|kmp} (bm = Boyer-Moore, kmp = Knuth-Pratt-Morris) [!] --string pattern [!] --hex-string pattern 例子 iptables -A INPUT -p tcp --dport 80 -m string --algo bm --string 'GET /index.html' -j LOG iptables -p udp --dport 53 -m string --algo bm --from 40 --to 57 --hex-string '|03|www|09|netfilter|03|org|00|' time:基于时间放行数据包 --datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]] --datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]] --timestart hh:mm[:ss] --timestop hh:mm[:ss] [!] --monthdays day[,day...] [!] --weekdays day[,day...] 例子 -m time --weekdays Sa,Su -m time --datestart 2007-12-24 --datestop 2007-12-27 -m time --datestart 2007-01-01T17:00 --datestop 2007-01-01T23:59:59 -m time --timestart 12:30 --timestop 13:30 -m time --weekdays Fr --monthdays 22,23,24,25,26,27,28 connlimit:根据每个客户端IP(也可以是地址块)做并发连接数量匹配 限制连接的数量小于n --connlimit-upto n 限制连接的数量大于n --connlimit-above n 限制匹配IP地址的掩码长度 --connlimit-mask prefix_length 限制源IP地址 --connlimit-saddr 限制目标IP地址 --connlimit-daddr 例子 # allow 2 telnet connections per client host iptables -A INPUT -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT # you can also match the other way around: iptables -A INPUT -p tcp --syn --dport 23 -m connlimit --connlimit-upto 2 -j ACCEPT # limit the number of parallel HTTP requests to 16 per class C sized source network (24 bit netmask) iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 16 --connlimit-mask 24 -j REJECT # limit the number of parallel HTTP requests to 16 for the link local network (ipv6) ip6tables -p tcp --syn --dport 80 -s fe80::/64 -m connlimit --connlimit-above 16 --connlimit-mask 64 -j REJECT # Limit the number of connections to a particular host: ip6tables -p tcp --syn --dport 49152:65535 -d 2001:db8::1 -m connlimit --connlimit-above 100 -j REJECT limit:基于收发报文的速率做检查,一种令牌桶过滤器 最大平均匹配率:指定为数字,可选“/秒”、“/分钟”、“/小时”或“/day”后缀;默认是3 /小时 --limit rate[/second|/minute|/hour|/day] 匹配的数据包的最大初始数量,默认值是5,空闲时峰值 --limit-burst number 例子:限制ping自己的速率,刚开始允许一下子ping5个,多了每2Sping接收一次ping iptables -A INPUT -d 192.168.1.1 -p icmp --icmp-type 8 -m limit --limit-burst 5 --limit-rate 30/minute -j ACCEPT iptables -A OUTPUT -s 192.168.1.1 -p icmp --icmp-type 0 -j ACCEPT state:根据连接追踪机制,检查连接状态 [!] --state STATE1,STAT2... 内核参数:/proc/sys/net/nf_conntrack_max,默认65536 当前已经追踪的连接 /proc/net/nf_conntrack 不同协议或连接类型追踪的时长 /proc/sys/net/netfilter/ 可追踪的链接状态 NEW:新发出的请求,连接追踪文件中不存在此连接相关的信息条目,因此,将其识别为第一次发出的请求 ESTABLISHED:NEW状态之后,连接追踪文件中为其建立的条目失效之前期间内所进行的通信的状态 RELATED:相关的连接状态,如ftp协议的命令连接与数据连接之间的关系 INVALIED:无法识别的连接 例子:对于Web服务,只接受外部连接的请求,不让内部80端口出去的请求(防止服务器内部木马程序,使用80端口和远端通信,反弹式木马) iptables -I INPUT -d 192.168.1.1 -p tcp -m dport 80 state --state NEW,ESTABLISHED -j ACCEPT iptables -I OUTPUT -s 192.168.1.1 -p tcp -m sport 80 state --state ESTABLISHED -j ACCEPT 例子:优化,只要此前访问过都允许数据包进来和出去 iptables -I INPUT state --state ESTABLISHED -j ACCEPT iptables -I OUTPUT state --state ESTABLISHED -j ACCEPT 例子:开放被动模式的ftp服务 1. 装载ftp追踪时的专用模块 modprobe nf_conntrack_ftp lsmod | grep ftp 2. 放行请求连接 命令连接:NEW,ESTABLISHED 数据连接:RELATED,ESTABLISHED iptables -I INPUT -d 192.168.1.1 -p tcp -m multiport 21:22,80 -m state --state NEW -j ACCEPT iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 3. 放行响应报文 ESTABLISHED iptables -I OUTPUT state --state ESTABLISHED -j ACCEPT 例子:优化连接追踪 1. 加大ip_conntrack_max值 vim /etc/sysctl.conf net.ipv4.ip_conntrack_max = 393216 net.ipv4.netfilter.ip_conntrack_max = 393216 2. 降低ip_conntrack_timeout时间 vim /ect/sysctl.conf net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 300 net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120 net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60 net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120
nat规则
SNAT:只修改请求报文的源地址
DNAT:只修改请求报文的目标地址
nat表
PREROUTING:目标地址转换(DNAT)
OUTPUT
POSTROUTING:源地址转换(SNAT)
# 例子:源地址转换 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 ! -d 192.168.1.0/24 -j SNAT --to-sourse 172.16.1.1 # 例子:目标地址转换(访问内网服务器) iptables -t nat -A PREROUTING -d 172.16.1.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.1:8080 # 例子:地址伪装(自动寻找一个合适的外网地址,作为源地址使用,IDSL拨号上网) iptables -t nat -A POSTROUTING -s 192.168.1.0/24 ! -d 192.168.1.0/24 -j MASQUERADE
自定义规则链使用
iptables -N clean_in iptables -A clean_in -d 255.255.255.255 -p icmp -j DROP iptables -A clean_in -d 192.168.1.254 -p icmp -j DROP iptables -A clean_in -p tcp ! --syn -m state --state NEW -j DROP iptables -A clean_in -p tcp --tcp-flags ALL ALL -j DROP iptables -A clean_in -p tcp --tcp-flags ALL NONE -j DROP iptables -A clean_in -d 192.168.1.1 -j RETURN iptables -A INPUT -d 192.168.1.1 -j clean_in
例子:利用iptables的recent模块来抵御DOS攻击
1. 利用connlimit模块将单IP的并发设置为3,会误杀使用NAT上网的用户,可以根据实际情况增大该值 iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP 2. 利用recent和state模块限制单IP在300S内只能与本机建立2个新连接,被限制五分钟后即可恢复访问 (--set,记录数据包的来源IP,如果IP存在将更新已经存在的IP条目) iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH (--update,每次建立连接都更新列表。iptables的记录/proc/net/xt_recent/SSH) iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --second 300 --hitcount 3 --name SSH -j LOG --log-prefix "SSH Attach:" iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --second 300 --hitcount 3 --name SSH -j DROP
管理防火墙配置
保存防火墙配置 iptables-save > /root/iptables_1.bak 重新加载防火墙配置文件 iptables-restore < /root/iptables_1.bak iptables -L -v -n CentOS6: service iptables save ---> iptables-save > /etc/sysconfig/iptables service iptables restart ---> iptables-restore < /etc/sysconfig/iptables CentOS7: firewall-cmd 命令行管理工具 firewalld-config 图形管理工具 * 为了持久应用防火墙规则,需要在开机启动时,应用规则脚本,使其生效
firewalld使用: https://www.ibm.com/developerworks/cn/linux/1507_caojh/index.html