iptables详解(8):iptables扩展模块之state扩展

  • A+
所属分类:iptables  linux基础

在本博客中,从理论到实践,系统的介绍了iptables,如果你想要从头开始了解iptables,可以查看iptables文章列表,直达链接如下

iptables零基础快速入门系列

 

当我们通过http的url访问某个网站的网页时,客户端向服务端的80端口发起请求,服务端再通过80端口响应我们的请求,于是,作为客户端,我们似乎应该理所应当的放行80端口,以便服务端回应我们的报文可以进入客户端主机,于是,我们在客户端放行了80端口,同理,当我们通过ssh工具远程连接到某台服务器时,客户端向服务端的22号端口发起请求,服务端再通过22号端口响应我们的请求,于是我们理所应当的放行了所有22号端口,以便远程主机的响应请求能够通过防火墙,但是,作为客户端,如果我们并没有主动向80端口发起请求,也没有主动向22号端口发起请求,那么其他主机通过80端口或者22号端口向我们发送数据时,我们可以接收到吗?应该是可以的,因为我们为了收到http与ssh的响应报文,已经放行了80端口与22号端口,所以,不管是"响应"我们的报文,还是"主动发送"给我们的报文,应该都是可以通过这两个端口的,那么仔细想想,这样是不是不太安全呢?如果某些与你敌对的人,利用这些端口"主动"连接到你的主机,你肯定会不爽的吧,一般都是我们主动请求80端口,80端口回应我们,但是一般不会出现80端口主动请求我们的情况吧。

 

你心里可能会这样想:我知道哪些主机是安全的,我只要针对这些安全的主机放行对应的端口就行了,其他IP一律拒绝,比如,我知道IP为123的主机是安全的,所以,我对123主机开放了22号端口,以便123主机能够通过22号端口响应我们的ssh请求,那么,如果你需要管理的主机越来越多呢?你是不是每次都要为新的主机配置这些规则呢?如果有30台主机呢?如果有300台主机呢?80端口就更别提了,难道你每次访问一个新的网址,都要对这个网址添加信任吗?这显然不太合理。

 

你心里可能又会想:针对对应的端口,我用--tcp-flags去匹配tcp报文的标志位,把外来的"第一次握手"的请求拒绝,是不是也可以呢?那么如果对方使用的是UDP协议或者ICMP协议呢?似乎总是有一些不完美的地方。

 

那么我们仔细的思考一下,造成上述问题的"根源"在哪里,我们为了让"提供服务方"能够正常的"响应"我们的请求,于是在主机上开放了对应的端口,开放这些端口的同时,也出现了问题,别人利用这些开放的端口,"主动"的攻击我们,他们发送过来的报文并不是为了响应我们,而是为了主动攻击我们,好了,我们似乎找到了问题所在?

问题就是:怎样判断这些报文是为了回应我们之前发出的报文,还是主动向我们发送的报文呢?

 

我们可以通过iptables的state扩展模块解决上述问题,但是我们需要先了解一些state模块的相关概念,然后再回过头来解决上述问题。

 

从字面上理解,state可以译为状态,但是我们也可以用一个高大上的词去解释它,state模块可以让iptables实现"连接追踪"机制。

那么,既然是"连接追踪",则必然要有"连接"。

咱们就来聊聊什么是连接吧,一说到连接,你可能会下意识的想到tcp连接,但是,对于state模块而言的"连接"并不能与tcp的"连接"画等号,在TCP/IP协议簇中,UDP和ICMP是没有所谓的连接的,但是对于state模块来说,tcp报文、udp报文、icmp报文都是有连接状态的,我们可以这样认为,对于state模块而言,只要两台机器在"你来我往"的通信,就算建立起了连接,如下图所示

iptables详解(8):iptables扩展模块之state扩展

而报文在这个所谓的链接中是什么状态的呢?这是我们后面讨论的话题。

 

对于state模块的连接而言,"连接"其中的报文可以分为5种状态,报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED

那么上述报文的状态都代表什么含义呢?我们先来大概的了解一下概念,然后再结合示例说明。

注意:如下报文状态都是对于state模块来说的。

NEW:连接中的第一个包,状态就是NEW,我们可以理解为新连接的第一个包的状态为NEW。

ESTABLISHED:我们可以把NEW状态包后面的包的状态理解为ESTABLISHED,表示连接已建立。

或许用图说话更容易被人理解

iptables详解(8):iptables扩展模块之state扩展

RELATED:从字面上理解RELATED译为关系,但是这样仍然不容易理解,我们举个例子。

比如FTP服务,FTP服务端会建立两个进程,一个命令进程,一个数据进程。

命令进程负责服务端与客户端之间的命令传输(我们可以把这个传输过程理解成state中所谓的一个"连接",暂称为"命令连接")。

数据进程负责服务端与客户端之间的数据传输 ( 我们把这个过程暂称为"数据连接" )。

但是具体传输哪些数据,是由命令去控制的,所以,"数据连接"中的报文与"命令连接"是有"关系"的。

那么,"数据连接"中的报文可能就是RELATED状态,因为这些报文与"命令连接"中的报文有关系。

(注:如果想要对ftp进行连接追踪,需要单独加载对应的内核模块nf_conntrack_ftp,如果想要自动加载,可以配置/etc/sysconfig/iptables-config文件)

INVALID:如果一个包没有办法被识别,或者这个包没有任何状态,那么这个包的状态就是INVALID,我们可以主动屏蔽状态为INVALID的报文。

UNTRACKED:报文的状态为untracked时,表示报文未被追踪,当报文的状态为Untracked时通常表示无法找到相关的连接。

 

上述5种状态的详细解释可以参考如下文章的"User-land states"章节

http://www.iptables.info/en/connection-state.html

 

好了,我们已经大致了解了state模块中所定义的5种状态,那么现在,我们回过头想想刚才的问题。

刚才问题的根源就是:怎样判断报文是否是为了回应之前发出的报文。

刚才举例中的问题即可使用state扩展模块解决,我们只要放行状态为ESTABLISHED的报文即可,因为如果报文的状态为ESTABLISHED,那么报文肯定是之前发出的报文的回应,如果你还不放心,可以将状态为RELATED或ESTABLISHED的报文都放行,这样,就表示只有回应我们的报文能够通过防火墙,如果是别人主动发送过来的新的报文,则无法通过防火墙,示例如下。

iptables详解(8):iptables扩展模块之state扩展

当前主机IP为104,当放行ESTABLISHED与RELATED状态的包以后,并没有影响通过本机远程ssh到IP为77的主机上,但是无法从104上使用22端口主动连接到77上。

对于其他端口与IP来说,也是相同的,可以从104主动发送报文,并且能够收到响应报文,但是其他主机并不能主动向104发起请求。

 

好了,state模块就总结到这里,希望这篇文章能够对你有所帮助。

 

weinxin
我的微信公众号
关注"实用运维笔记"微信公众号,当博客中有新文章时,可第一时间得知哦~
朱双印

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:19   其中:访客  13   博主  6

    • avatar maco_zhenqin 2

      这几天一直逛您的博客,受益良多.
      刚刚赞助了一下,小小心意,辛苦了~

      • avatar 追梦者 0

        开篇的例子是不是有问题啊,我理解客户端访问服务端80端口时是以本地的一个随机端口访问的,那么服务端回应客户端时,应该是回应到客户端的随机端口而不是80端口。所以客户端访问服务端的80端口并不需要放行自己的80端口。如果是我理解错了,请博主纠正,谢谢!

          • avatar 朱双印 Admin

            @追梦者 理解的没错,客户端使用随机端口,访问服务端80端口,服务端用80端口响应到客户端的随机端口,但是如果,我们是为了只接受80端口的“响应”报文,不是让服务端主动通过80端口向客户端发送数据时,我们该怎么办?一旦从客户端放行服务端的80端口,那么从服务端的80端口也能逆向主动访问客户端,当我们想要只让客户端主动访问服务端的80端口并接收响应报文时,而不是服务端也可以通过自己的80主动访问客户端时,才会用这个方法,开篇的例子是这个意思,是在客户端的防火墙上对服务端的80端口做限制,开篇的例子没有错,结尾的例子原来有问题,当时糊涂了,用服务端去请求客户端了(并不能真正的看到实验效果),不过在 @宇宙尽头 和 @简单粗暴 指出这个问题以后,已经把结尾的示例删了,所以你看到的开篇示例是没有问题的,开篇的示例想要表达的意思就是我刚才说的那样的意思

          • avatar 亦双弓 3

            这篇中的链接 User-land states 章节的链接已失效

            • avatar 宇宙尽头 2

              拜读,受教
              提个建议,本篇开头将的是客户端连接服务端的22端口,如果服务端或者其他主机通过自己的22端口向客户端发送数据包如何识别的问题。但是给的例子就是从服务端反向ssh客户端,没有展现出客户端–state的真实实力 :),貌似ssh也无法指定本端端口,可以找个其他工具指定从本端22端口发包。

                • avatar 简单粗暴 1

                  @宇宙尽头 对啊,这个例子不对,限制对方本身用22端口发出的链接才对,例子中连接本机的22端口,不是一回事

                    • avatar 朱双印 Admin

                      @简单粗暴 是的,错误已经修改,之后会抽空测试一下,感谢@宇宙尽头和@简单粗暴的指正

                  • avatar 随心 2

                    非常详细,感觉比马哥讲的都通俗易懂

                    • avatar network 1

                      state中的NEW状态,貌似没啥作用啊。 NEW为连接中的第一个包,并不能用他来做什么策略

                      • avatar network 1

                        朱兄 你的博客确实是实实在在适合刚接触iptables的人来看,没有只顾站在自己的层次来吧博文写成私人笔记,很不错。

                        • avatar qwer 0

                          朱双印新年快乐,嘿嘿大年初一 给你拜早年!没有加你微信 就在这留言了。 :mrgreen:
                          【文章有错别字】RELATED ==》ftp服务==》
                          数据进程负责服务端与客户端之前的数据传输(我们把这个过程赞成为“数据连接”)。
                          数据进程负责服务端与客户端之间的数据传输(我们把这个过程赞成为“数据连接”)。

                            • avatar 朱双印 Admin

                              @qwer 感谢客官指正,错别字已经修改,谢谢捧场~~新年快乐~~~

                            • avatar 浪卡, 0

                              你好,我想问一下第一次发送的udp数据应该是什么状态呢?为什么我锁了NEW 还是能收到数据

                              • avatar echo 6

                                已阅

                                  • avatar 朱双印 Admin

                                    @echo 兄弟,你是想说 朕已阅 吗 :grin: 哈哈

                                  • avatar yanan001 2

                                    看的过瘾啊

                                      • avatar 朱双印 Admin

                                        @yanan001 在写这篇文章的时候就想到你啦,哈哈~~本来还想去之前的留言中通知你呢,没想到你已经看到了,多谢兄弟关注哦, :grin: :grin:

                                          • avatar yanan001 2

                                            @朱双印 佩服你啊,我是先前在洞悉iptables的博客里看到你的文章链接的,感觉看完你的文章,再回过头看洞悉iptables轻松多了~我还把你的文章推荐给了我的同事他们~

                                              • avatar 朱双印 Admin

                                                @yanan001 :mrgreen: 谢了兄弟,有你们支持会写出更多的文章的,顺便做广告,关注微信公众号”实用运维笔记”,帮我推荐推荐啊 :wink: 谢谢啦 :mrgreen: