Linux入门攻坚——37、Linux防火墙-iptables-3
私网地址访问公网地址的问题,请求时,目标地址是公网地址,可以在公网路由器中进行路由,但是响应报文的目的地址是私网地址,此时在公网路由器上就会出现问题。公网地址访问私网地址的问题,需要先访问一个公网的地址,由公网地址在转换为私网地址。解决的方法有:nat和proxy。
NAT:Network Address Translation,此技术最初是为了安全性,隐藏本地网络主机。网络层+传输层;
proxy:代理,应用层;
NAT:
SNAT:只修改请求报文的源地址;
DNAT:只需改请求报文的目标地址;
iptables中的nat表三个链:
PREROUTING:DNAT在这个链上,否则目标地址是nat服务器本身,直接到INPUT去了,所以一进入就要进行地址转换。
OUTPUT:
POSTROUTING:只有确定了路由后,才进行地址转换(如果是访问NAT服务器本身,则不需要转换),所以SNAT在这个链上。
关于SNAT与DNAT:
SNAT是源地址转换,DNAT是目标地址转换,都是从请求报文方面来说的,因为对于一个SNAT,都会对应一个响应报文的DNAT,对于一个DNAT,都会有一个响应报文的SNAT。上图中实线是请求报文流,虚线是响应报文流。
对于SNAT,主要用于内网主机访问外网服务器,从上图可以看出,如果不经过地址转换,请求报文是可以到达外网服务器的,但是外网服务器的响应报文,因为其目的地址是内网地址CIP,所以是无法在外网中路由的,无法返回响应报文,这就是需要SNAT的原因;另一个关键问题是对于防火墙来说,这个地址转换的位置在哪?如果是在PREROUTING转换,那如果这个请求报文就是给NATServer本身的,就会出现问题,此时根本不需要转换,都在一个内网中,所以,SNAT是在路由之后,在发出报文前进行地址转换,即在POSTROUTING将CIP转换为NATServer的外网地址FIP;此时的响应报文,其目的地址就是转换后的源地址FIP,可以到达NATServer,在到达NATServer后,第一步要进行目的地址转换,将FIP转换为CIP,即在PREROUTING转换,否则,进行路由后在转换,路由的结果可能就是错误的。
对于DNAT,主要用于内网主机提供服务的情景,外网主机访问内网主机服务器,从上图可以看出,内网主机提供的服务是映射在NATServer上,外网主机访问NATServer,如果不进行目的地址转换,请求报文达到NATServer后,NATServer根本就没有这个服务,请求失败,所以要在请求报文达到NATServer时,根据转换规则,先进行目的地址转换,即将请求报文的目的地址FIP转换为CIP,转换位置在PREROUTING上,然后通过路由达到内网主机CIP,而响应报文,其源地址是内网主机的地址CIP,在路由之后,响应报文发出NATServer前,要进行源地址的转换,由CIP转换为FIP,如果不转换,响应报文是能够到达外网主机的,但是因为其响应报文的源地址是CIP,外网主机根本没给这个地址发过请求,这个响应报文会被作为异常报文,可能就丢弃了。
所以,源地址转换都是在POSTROUTING,目的地址转换都是在PREROUTING。
proxy:代理,工作于应用层,获取客户端的请求报文,完全拆解报文后,获取请求内容,在自己构建一个请求,发送给服务器,然后接收服务器的响应报文,拆解报文,在重新构建一个响应报文给客户端。
NAT实现方式:
还是使用前面的拓扑:
SNAT实现:
F2上有httpd服务器,将其假设为外网服务器,F1为内网主机,F1要访问F2上的服务。
F1(内网主机)上的路由:
7.9(NATServer)上的路由:
F2(外网服务器)上的路由:
从F1访问F2的WEB服务,在F2上抓包:
访问的结果是在F1上无法访问F2上的httpd服务的页面:
F2上的抓包:
从抓包的结果可以看到,F1的请求报文到达了F2,F2也向F1发送了响应报文,但是因为F2没有F1的路由,即没有192.168.61.0的路由,送给了默认网关192.168.147.2,响应报文无法返回。这里要注意的是请求报文的源地址是192.168.61.129,响应报文的目的地址是192.168.61.129。
想要能够访问,需在F2上增加路由:
route add -net 192.168.61.0/24 gw 192.168.147.128
此时访问成功。
从F2的httpd日志中也能看到请求访问的主机地址:
现在将F2上的路由去掉:route del -net 192.168.61.1/24 gw 192.168.147.128
此时,F1又无法访问了,请求报文能够到达F2,F2的响应报文无法返回。
在7.9上(NATServer),做SNAT:
iptables -t nat -A POSTROUTING -s 192.168.61.0/24 ! -d 192.168.61.0/24 -j SNAT --to-source 192.168.147.128
此时,在F1上又可以访问F2的WEB服务了,但是在F2上抓包:
访问的源地址变为NATServer的地址192.168.147.128,而不是F1的地址,响应报文的目的地址也变为192.168.147.128,而不是F1的地址。这就是SNAT。
DNAT测试:
清空nat表规则:
现在假定F2是内网的主机,提供web服务,而外网的主机F1要访问内网的服务,F1是无法通过内网的IP地址直接访问F2的服务。此时需要进行目的地址转换,即DNAT。
在网关上,即NATServer上声明
iptables -t nat -A PREROUTING -d 192.168.61.128 -p tcp --dport 80 -j DNAT --to-destination 192.168.147.129
在F2上增加默认路由,route add default gw192.168.147.128
此时,F1可以访问F2的服务,即外网访问内网的服务。curl http://192.168.61.128,在F2上抓包:
可以看到,访问的目的地址是192.168.147.129,而不是192.168.61.128。这就是DNAT,目的地址转换。
因为我们只是对80端口进行了转换,所以如果F1上访问ssh服务:ssh 192.168.61.128,则访问的是NATServer本身:
将22端口进行转换:
iptables -t nat -A PREROUTING -d 192.168.61.128 -p tcp --dport 22 -j DNAT --to-destination 192.168.147.129
再次访问:
这个应该是安全的原因,类似中间人攻击。在F2上抓包:
目的地址已经进行了转换。
端口转换:将第一条规则修改为192.168.61.128转换为192.168.147.129:8080
iptables -t nat -R PREROUTING 1 -d 192.168.61.128 -p tcp --dport 80 -j DNAT --to-destination 192.168.147.129:8080
对于源地址转换,有时候外网的地址经常变动,如ADSL拨号上网,此时可以使用MASQUEREAD,进行地址伪装,此时NATServer会找到合适的IP地址进行源地址转换:
iptables -t nat -A POSTROUTING -s 192.168.147.0/24 !-d 192.168.147.0/24 -j MASQUEREAD
自定义规则链及其使用,以及常用的一些规则:
iptables -N clean_in
iptables -A clean_in -d 255.255.255.255 -p icmp -j DROP
iptables -A clean_in -d 192.168.255.255 -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.147.128 -j RETURN
iptables -A INPUT -d 192.168.147.128 -j clean_in
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -i eth0 -m multiport -p tcp --dports 53,113,135,137,139,445 -j DROP
iptables -A INPUT -i eth0 -m multiport -p udp --dports 53,113,135,137,139,445 -j DROP
iptables -A INPUT -i eth0 -p udp --dport 1026 -j DROP
iptables -A INPUT -i eth0 -m multiport -p tcp --dports 1433,4899 -j DROP
iptables -A INPUT -p icmp -m limit --limit 10/second -j ACCEPT
tcp_wrapper:tcp包装器
对基于tcp协议开发并提供服务的应用程序,提供的一层访问控制工具;tcp_wrapper是基于库调用实现其功能:libwrap库。
只能对本机内部程序(服务)进行访问控制。
判断服务是否能够由tcp_wrapper进行访问控制:
1)动态编译:ldd命令;
2)静态编译:strings命令查看应用程序文件,其结果中如果出现:hosts.allow和hosts.deny
在配置文件在为各服务分别定义访问控制规则实现访问控制:
/etc/hosts.allow
/etc/hosts.deny
先检查hosts.allow,后检查hosts.deny;
服务检查逻辑:
client --> /etc/hosts.allow --> (Y) --> ALLOW
client --> /etc/hosts.allow --> (N) --> /etc/hosts.deny --> (Y) --> DENY
--> (N) --> ALLOW
配置文件语法:
daemon_list:client_list [:options]
daemon_list:
应用程序的文件名称,而非服务名;
用用程序文件名称列表,彼此间使用逗号分隔;
例如:sshd,vsftpd; ALL表示所有服务;
client_list:
IP地址;
主机名;
网络地址:必须使用完整格式的掩码,不使用前缀格式掩码;类似192.168.0.0/16不合法;
简短格式的网络地址:如192.168. 表示192.168.0.0/255.255.0.0
ALL:所有主机;
KNOWN:
UNKNOWN:
PARANOID:
例如:vsftpd服务不允许192.168.147.129访问:在/etc/hosts.deny中,
vsftpd:192.168.147.129
在hosts.allow中匹配到的,允许访问,没有匹配到的,默认拒绝,然后在hosts.deny中进行匹配,deny中匹配到,则拒绝,否则,允许访问,即默认允许。
EXCEPT:除了
hosts.allow
vsftpd:172.16. EXCEPT 192.16.100.1
vsftpd:172.16. EXCEPT 172.16.100.0/255.255.255.0 EXCEPT 172.16.100.1
[:options]
deny:拒绝,主要用于hosts.allow文件中,实现deny的功能
allow:允许,用于hosts.deny文件中,实现allow的功能
spawn:启动额外应用程序;
vsftp:ALL :spawn /bin/echo `date` login attempt from %c to %s,%d >>/var/log/vsftpd.log
%c:client ip 、%s:server ip 、%d:daemon name
对于telnet服务,因为在CentOS6上,是xinetd超级服务控制的,使用的deamon即不是xinetd,也不是telnetd,而是in.telnetd,是程序名。