当前位置: 首页 > news >正文

门户网站建设要点东莞互联网

门户网站建设要点,东莞互联网,全球邮箱wordpress,怎么让百度搜索到自己的网站谈到什么是意义#xff0c;话题总显得很大#xff0c;近日每晚都和老城里的朋友聊老城的文化#xff0c;老城的老房子#xff0c;老城的叫卖声#xff0c;老城的方言…进行了很多的思考#xff0c;也挺充实。至于技术方面#xff0c;也有跟朋友以及前同事聊过#xff0…谈到什么是意义话题总显得很大近日每晚都和老城里的朋友聊老城的文化老城的老房子老城的叫卖声老城的方言…进行了很多的思考也挺充实。至于技术方面也有跟朋友以及前同事聊过这些都是意义。又到了周末早早起来写一篇技术总结至于老城的话题我会在朋友圈零零散散地写。本文关键词Linux策略路由nf_conntracksocket路由缓存再谈“哪里来的回哪里”当人们部署双线服务器时比如一根线接电信一根线接联通人们当然不希望同一个流的流量被跨运营商路由一个自然而然的需求就是哪里来的回哪里为了实现这个需求一般采用的技术是策略路由(Policy Routing)基于Linux我们可以通过下面的范式来实现iptables -t mangle -A PREROUTING -j CONNMARK --restore-markiptables -t mangle -A PREROUTING -m mark ! --mark 0 -j ACCEPTiptables -t mangle -A PREROUTING -i XXX .... -j MARK --set-mark Xiptables -t mangle -A PREROUTING -m mark ! --mark 0 -j CONNMARK --save-markiptables -t mangle -A OUTPUT -j CONNMARK --restore-markip rule add fwmark X table Xip route add $net/$mask via $gw dev $device table X这样我们就可以通过不同的标签来识别不同线路的流量从而通过策略路由配置多个不同的默认网关。以上这些在Linux运维圈子里几乎成了一个典型的认知但是仔细看上述的范式好像少了点什么…从一个错误的分析说起如果我通过电信的线路去telnet一个在服务器上并不存在的端口服务器会产生一条destination port unreachable的ICMP错误信息然而这条ICMP信息严格来讲并不属于这个telnet引发的TCP流因此貌似范式中的以下规则并不会起作用iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark因此后面的策略路由便不会被命中最终这条ICMP报错信息并不一定会通过电信的线路返回这完全不符合我们的预期怎么办事情将在此反转。如果你亲自试一下并且加入下面的规则调试iptables -A OUTPUT -m mark ! --mark 0x0 -j LOG发现ICMP消息也被打上了标签也就是说我们上述的担心并不真的存在难道上面的逻辑分析哪里不对吗在知识构成有缺失的时候逻辑分析非常不靠谱此时实际动手试一下更显的真实我之所以强调这句话是因为这是我2013年时面对上述问题最终解决后的总结它对我十分有用。上面看似严谨的逻辑分析之所以是错的是因为我当时根本就不知道nf_conntrack实现的细节更不晓得什么是RELATED状态…这个ICMP错误消息虽然不属于telnet引发的TCP流但它跟该TCP流却是RELATED的而RELATED的流会继承原始流的conntrack结构体表项这就是问题的根本如果缺失了这个细节就会带来错误的判断。在这里分析RELATED实现的细节会显得喧宾夺主而不合时宜我会在本文的附录中给出详细的解释。在初步理解了RELATED状态的流域引发它们的原始流之间的关系后我接下来给出另一个范式。另一个范式-把ICMP错误信息引流到固定的地方不要回答但要审计“不与陌生人说话”是信息安全领域的最高要求之一读过《三体-黑暗森林》的应该有所体会保持沉默永远是最安全的。如果有人伪造源IP地址发动了针对你的服务器的攻击你难道真的要给这个伪造的源回复一条ICMP报错消息吗不这么做相当于你给陌生人说话了伪造源的攻击者正等着收到你的ICMP信息呢至少他可以通过IP头的TTL字段知道你离他真正有多远吧…因此最好不要回答然而我们却可以把这个ICMP报错消息发送到我们自己特定的审计服务器里便于审计服务进行离线的模式分析所以说这个ICMP消息某种意义上还是有用的。实现这个需求的方案依然是策略路由和哪里来的回哪里范式不同的是这个新的范式只需要标记由于错误的IP报文引发的ICMP报错消息报文即可并不需要标记原始的数据包我先把范式列如下# 连接的第一个包记录mark到conntrackiptables -t mangle -A PREROUTING -m state --state NEW -j MARK --set-mark X# 短路规则iptables -t mangle -A PREROUTING -m mark --mark 0 -j ACCEPTiptables -t mangle -A PREROUTING -j CONNMARK --save-mark# 待将mark保存在conntrack中的任务完成后解除mark不影响原始流iptables -t mangle -A PREROUTING -j MARK --set-mark 0# 如果是ICMP related包就先restore标签这里会恢复mark标签到skbiptables -t mangle -A OUTPUT -p icmp -j CONNMARK --restore-mark# 配置策略路由ip rule add fwmark X table X# 审计服务器的路由ip route add $net/$mask via $gw dev $device table X嗯以上的范式可以完美做到将发生的ICMP错误消息路由给审计服务器值得注意的是在部署审计服务器的时候最好将其部署在独立的区域即通过服务器的某个网口仅能够到达审计服务器。虽然我们完成了任务然而当需求满足了的时候便要考虑性能优化了。好吧又一次我们遇到了conntrack不可避免地有人要问“如果不用conntrack如何满足上述两个范式中满足的需求我真是受够了conntrack了能不用它就不用它”这里先给出答案完全可以诚然说conntrack不好的人可能并不是真的知道conntrack到底差在哪里更别说它为什么差劲了大多数情况这些人都是听别人说的因此这并不能作为不用conntrack的理由这就好比说别人说奥迪烧机油不要买我听了之后就彻底看扁这个品牌了不不是这样在说一个东西不好之前你首先要了解它。conntrack的毛病到底在哪儿我可以客观的说conntrack完全没毛病说它有性能问题完全是胡扯因为既然你想到了用conntrack帮你解决的问题那就说明你还没有到拼性能的时候如果真到了拼性能的地步别说conntrack连整个内核协议栈都需要被绕过去君不见诸多DPI(深度包解析)平台有哪个是基于传统的Linux内核协议栈的一般的思路难道不是众核平台结合DPDK吗我个人认识到以上这一点是经历了一个比较久的过程的起初我也尝试着用conntrack来完成一个诸如短路信息分析和记录这种事后来我发现使用nf_queue来将skb上推到用户态在用户态处理后再注入会更方便也更稳定这个时候conntrack又退回到它本来的位置了在接下来的优化中我发现几个锁的开销是绕不开的在一番深思熟虑之后我为conntrack加入了percpu的cache性能得到了大幅提升然而此时的瓶颈成了路由查表或者socket查表…总之如果追求极致的性能Linux内核协议栈可能是无法胜任的在2014年初的时候我接触到了Tilera平台跟DPDK一样的原理只是没有后者通用基于这些平台的解决方案无一例外地都是绕过传统的内核协议栈直接从网卡中把数据包拉到用户态充分利用核数越来越多的CPU这是一种新的模式它解决了传统协议栈无法解决的在多核平台上锁的问题。做个比喻DPDK的方式不仅仅是一辆代步的质量好的轿车而是一辆不以代步为目的的专用跑车可能它很便宜但它仍然是跑车。简简单单说conntrack性能差就跟说宝马3系比奥迪A4L要好一样无聊。插曲在这里说正合适。近期老婆要换车主要在宝马3系/4系和奥迪A4L/A5之间选择大多数人千篇一律地说什么宝马操控上要比奥迪好什么什么的我相信除了极少数人绝大多数人都是听别人说的后来老婆的一个懂车的朋友推荐买奥迪并说了句实话“前驱或四驱或更稳一些应对路况的突变或者雨雪天会更好至于操控你以为你开赛车玩漂移啊”是的也就30万40万的车还没到拼百公里加速的层次就是个普通的质量好一些的代步工具而已这个价位的车子主要功能就是代步而不是品玩简单点说它们都是差不多的对手车之间差别不可能太大人人也都不是傻子安全舒适好看要比比拼那些相差毫厘的参数更重要。所以买哪个还看自己的品牌认同感以及看哪个顺眼了。我不懂车还没我老婆懂关于换车的事我就不掺和了但我懂Linux协议栈和内嵌的nf_conntrack下文中我就说说conntrack如果有问题那么它的问题到底在哪里。和内核协议栈其它的部分一样影响conntrack机制性能的罪魁祸首简单点说就是该机制的实现中内置的1把全局自旋锁(请注意自旋锁问题并不是conntrack机制独有的但凡多核平台这就是个恶魔)即nf_conntrack_lock该自旋锁在3个地方会被lock我分别说。1. conntrack表项初始化时当一个数据包进入协议栈并且没有关联任何conntrack表项时会为其初始化一个conntrack表项结构体虽然它还没有必要被立即confirm然而还是会被置入一个链表整个过程大致如下init_conntrack(){spin_lock_bh(nf_conntrack_lock);// 这个expect机制我会在附录里详述这里仅仅了解到所有expect流都在一个全局链表中即可exp nf_ct_find_expectation(net, zone, tuple);if (exp) {__set_bit(IPS_EXPECTED_BIT, ct-status);ct-master exp-master;}// 为了管理方便所有刚刚初始化的conntrack结构体都要置入一个叫做unconfirmed的链表中hlist_nulls_add_head_rcu(ct-tuplehash[IP_CT_DIR_ORIGINAL].hnnode,net-ct.unconfirmed);spin_unlock_bh(nf_conntrack_lock);}2. conntrack表项被confirm时记住unconfirmed链表仅仅是为了让一个conntrack结构体可被追溯而不至于脱离管理而游离当它最终被confirm的时候就意味着它要加入全局conntrack链表了此时便可以将它从unconfirmed链表中安全摘除了。在confirm例程中大致的逻辑如下__nf_conntrack_confirm(){spin_lock_bh(nf_conntrack_lock);// 从unconfirmed链表摘除hlist_nulls_del_rcu(ct-tuplehash[IP_CT_DIR_ORIGINAL].hnnode);// 加入全局的confirm链表__nf_conntrack_hash_insert(ct, hash, repl_hash);spin_unlock_bh(nf_conntrack_lock);}3. conntrack销毁删除的时候这个不多说非常显然。—————————————以上几处需要lock/unlock自旋锁的地方意味着什么呢首先只有conntrack结构体在初始化创建或者confirm的时候才会lock/unlock这把自旋锁如果说当前系统中的连接都是既有的且稳定的时候这把自旋锁根本就不会被触动因此执行流便根本不会落入它所带来的串行化瓶颈区域这就意味着这种情况下conntrack机制的瓶颈是不存在的至少说是不严重的懂了吗那么什么时候使用conntrack才会影响性能很简单有大量连接新建或删除的时候比如说遭遇了DDoS攻击的时候比如说大量短链接的时候比如说同时大量TCP timewait连接的时候…对于另外的情况也是有很多方案可化解的比如汗牛充栋的解决TCP timewait的方案比如HTTP协议将短链接聚合成长连接的方案(多个HTTP请求重用单独的TCP连接)…只要我们避免了这类情况就不必担心conntrack带来的性能损耗然而理想归理想你永远也不能预料什么时候会有一个什么样的数据包到达你的服务器就像你永远不能预料什么时候有什么人会敲你家的门一样所以说这个全局自旋锁的开销平均下来是非常可观的。Netfilter开发社区的猛士当然知道这个问题当广大使用者正在纠结于conntrack全局锁如何在应用层面避开的时候社区的内核开发者们早就在机制层面给予了优化这是一件多么幸运的事情。我们来看看优化的细节告诉大家Linux 3.10内核还没有这个优化但是发现4.3往后的内核就有了(我没有具体确认从哪个版本开始引入了这个优化手头上有一个4.3版本的内核确认了一下这个优化已经被引入)所以还是那句话尽量升级你的内核到最高版本吧。优化的本质在于自旋锁的细粒度拆分仔细想想unconfirmed链表需要全局锁吗它只是为了确保conntrack结构体不要脱缰因此只需要本地保存即可没必要搞成全局的。说再多不如看代码。所以说新的优化版本逻辑如下init_conntrack(){if (net-ct.expect_count) { // 这里加了一个条件确保只有在确实需要查询expect链表的时候才会锁定额外的全局自旋锁这是另一个优化// 注意这里仍然有个全局锁但是却不是每次都必进的分支因为新增了expect_count这个条件变量spin_lock(nf_conntrack_expect_lock);if (exp) {__set_bit(IPS_EXPECTED_BIT, ct-status);ct-master exp-master;}spin_unlock(nf_conntrack_expect_lock);}// 注意以下的inline函数将全局的spinlock分解成了局部的percpu spinlock{ct-cpu smp_processor_id();pcpu per_cpu_ptr(nf_ct_net(ct)-ct.pcpu_lists, ct-cpu);// 仅仅锁定本地的自旋锁spin_lock(pcpu-lock);// 仅仅将conntrack加入到本地的unconfirmed链表中hlist_nulls_add_head(ct-tuplehash[IP_CT_DIR_ORIGINAL].hnnode,pcpu-unconfirmed);spin_unlock(pcpu-lock);}}可以看到unconfirmed链表成了percpu本地链表了因此自旋锁的锁定粒度大大减小了这并不影响其它的执行逻辑比如当需要dump所有的unconfirmed表项时完全可以先锁定全局的自旋锁再获取要知道全局自旋锁是可以囊含本地自旋锁的。好了我们再看下优化后的confirm例程__nf_conntrack_confirm(){{// 从conntrack的cpu字段获取当初它加入的本地cpu(conntrack结构体中保留cpu字段是个创举)pcpu per_cpu_ptr(nf_ct_net(ct)-ct.pcpu_lists, ct-cpu);spin_lock(pcpu-lock);// 从conntrack当初加入的cpu的本地unconfirmed链表删除hlist_nulls_del_rcu(ct-tuplehash[IP_CT_DIR_ORIGINAL].hnnode);spin_unlock(pcpu-lock);}{// 全局链表的自旋锁也分解成了orig以及reply两个方向的锁spin_lock(nf_conntrack_locks_orig);spin_lock(nf_conntrack_locks_reply);__nf_conntrack_hash_insert(ct, hash, repl_hash);spin_unlock(nf_conntrack_locks_reply);spin_unlock(nf_conntrack_locks_orig);}}通过以上的事实以及针对这些事实的论述会发现影响conntrack性能的就是自旋锁然而随着自旋锁在不断的细粒度化分解这些问题将越来越不是问题我相信未来追究会解决所有关于conntrack的性能问题的。也许你会说除了链表插入删除的自旋锁开销难道不得不做的查询行为没有开销吗哈哈开销肯定是有的但是你难道就不会变通一下吗查什么不是查就算你避开了查conntrack链表难道你能避开查路由表或者socket链表吗所以说干嘛不把conntrack当成一个cache呢把路由表以及socket表的查询结果都保存在conntrack表项中这样就可以只查conntrack链表了顺带取出的还有路由(转发时)以及socket(本地接收时)这个优化我亲自实现过效果非常好并且conntrack是所有包括路由表和socket链表在内第一个被查询的所有这样的优化非常容易实现没有实际操作过的人就不要人云亦云地诟病conntrack了先试试我的方案再说Together with L4_early_demux!看到conntrack在持续优化我就欣慰了因为这样我就可以将下文的方案作为另一种稍微好的做法而不至于作为不得已的退避手段了。好了接下来让我们看一下如何不使用conntrack来实现‘哪里来哪里去’不使用conntrack实现“哪里来哪里去”范式接着上一节的最后论调继续说。conntrack连接跟踪记录了一个五元组而对于一个服务器而言一个socket在全部意义上就扮演了conntrack的角色因此在服务器上即那些非转发设备上可以让socket替代conntrack表项来保存一些必要的信息。在这些信息中对于策略路由而言最关键的信息就是mark昔日我们用iptables为匹配的skb打上mark然后将mark保存在conntrack结构体中此后对于reply方向的包就可以将conntrack的mark给restore到skb中对于服务器而言我们完全可以把匹配的skb的mark保存在socket中更加轻松的是一旦socket有了mark只要是本socket发出的skb就会被自动打上相应的socket的mark根本连iptables的restore-mark规则都不需要这简直是如鱼得水全程没有使用conntrack让某些诟病conntrack的吃瓜群众放了心。在具体实现上上一节同样说过查什么不是查只要保证查一次即可既然在early demux以及L4 recv函数中都能查socket那么我们自己写一个iptables的target在该target中实现如下的逻辑岂不是妙哉sk nf_tproxy_get_sock_v4(net, skb, hp, iph-protocol, iph-saddr, laddr, hp-source, lport, skb-dev, NFT_LOOKUP_LISTENER);if (sk) {sk-sk_mark mark_value;}请注意mark并没有为skb来打而是直接打给了socket这是为了该socket往外发包时这些数据包会自带该mark这里的socket就完全扮演了conntrack的角色。如此一来只要当进入的数据包匹配了iptables的规则那么既定的mark就会被打入socket然后该socket在发包的时候会自动继承这个mark从而去匹配特定于mark的策略路由表等。这是一种实现“哪里来哪里去”范式的良好手段然而对于实现第二个范式即为ICMP错误消息设定策略路由这种事就不好办了因为ICMP消息的发送完全是内核来自动完成的并不是通过某个socket来发送的。这个并没有好的手段来实现因此必然要修改代码才能实现我侧重于修改icmp_send函数void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info){...// 这里在查路由表时并没有体现出mark的意义rt icmp_route_lookup(net, fl4, skb_in, iph, saddr, tos, type, code, icmp_param);...}因此我只需在icmp_route_lookup增加mark就好了也比较简单就是取skb_in的mark字段作为参数传入即可…本来我正准备改代码并编译呢在此之前我看了4.9/4.14的代码…所有这些都已经实现了void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info){...mark IP4_REPLY_MARK(net, skb_in-mark);sk-sk_mark mark;rt icmp_route_lookup(net, fl4, skb_in, iph, saddr, tos, mark,type, code, icmp_param);...}代码就不用注释了。关键在于IP4_REPLY_MARK宏#define IP4_REPLY_MARK(net, mark) \((net)-ipv4.sysctl_fwmark_reflect ? (mark) : 0)啊哈抓住了大鱼就是sysctl_fwmark_reflectsysctl参数名是net.ipv4.fwmark_reflect是不是在高版本中我只需要把net.ipv4.fwmark_reflect设置成1就OK了呢答案显然是肯定的。因此使用sysctl的fwmark_reflect参数来实现第二范式可以完美解决那么第一范式呢显然刚才我们就知道第一范式可以通过重新编写一个target模块来解决而不是用参数来解决但是既然可以用参数解决ICMP消息的标记问题是不是也有参数能满足第一范式的需求呢即便没有我觉得应该也不难自己实现的话最多也就一天吧原因很简单只需要把conntrack中转交mark的逻辑置于socket中即可。无比幸运的是就连这也都不需要我自己来做了系统针对TCP早就有了这样的支持机制这就是net.ipv4.tcp_fwmark_accept所起的作用。net.ipv4.tcp_fwmark_accept参数实现“哪里来哪里去”范式我先给出范式的配置方法吧列如下# 开启mark转交功能sysctl -w net.ipv4.tcp_fwmark_accept1# 仅仅为新入的SYN包来进行标记后续包无需标记因为fwmark_accept会将mark赋值给socketiptables -t mangle -A PREROUTING -i $dev1 -p tcp --syn -j MARK --set-mark $mark_dev1iptables -t mangle -A PREROUTING -i $dev2 -p tcp --syn -j MARK --set-mark $mark_dev2# 配置策略路由ip rule add fwmark $mark_dev1 tab dev1ip rule add fwmark $mark_dev1 tab dev1# 分别添加路由项ip route add default via $gateway1 dev $dev1 tab dev1ip route add default via $gateway2 dev $dev2 tab dev2我打算本节就此打住但是还是忍不住想再多说一点。tcp_fwmark_accept这个参数带来的功能是如何实现的呢非常简单TCP连接在初始化一个request socket的时候会调用以下函数来为这个将来的客户端socket选择一个markstatic inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb){if (!sk-sk_mark sock_net(sk)-ipv4.sysctl_tcp_fwmark_accept)return skb-mark;return sk-sk_mark;}可见skb上的mark在tcp_fwmark_accept参数启用的情况下成为首选。本节毕socket上的路由cache很久以前在我想到将路由查询的结果放在conntrack结构体中的同时我就想到在作为服务器的场景下把路由查询结果放在socket中了但其实Linux在实现四层协议时天然地就支持一个路由cache。对于TCP而言系统会将SYN-ACK的结果路由缓存到socket中这是通过下面的代码实现的tcp_v4_syn_recv_sock(){// 接上一节在tcp_fwmark_accept开启时req中便已经有了mark了会影响接下来的路由查找dst inet_csk_route_child_sock(sk, newsk, req);// 缓存路由到socketsk_setup_caps(newsk, dst);}非常干净直接的一个逻辑但是同样要考虑到的是既然是缓存就有什么时候过期删除的问题TCP和IP很好的处理了这一点在使用这个路由缓存的时候会进行判断我们来看下ip_queue_xmit函数ip_queue_xmit(){rt skb_rtable(skb);if (rt) // 这是已经路由好的数据包goto packet_routed;// 这里是重点在使用socket的路由cache前首先要check一下。rt (struct rtable *)__sk_dst_check(sk, 0);if (!rt) {}有两种情况会导致socket的路由缓存失效1. 系统路由表发生了变动这是很好理解的在实现上也很精妙。系统维护了一个全局计数器每次路由表变动时都会递增而每一个路由缓存都有一个ID字段其值就等于当前的全局计数器的值在使用路由缓存前发现缓存的ID和全局计数器不一致便可将缓存废了说明路由表发生了变化要重新路由了。2. TCP连接发生了超时重传一般情况下除了尾部丢包和链路完全堵死TCP在丢包时都会触发快速重传机制的一旦发生超时重传意味着发生了严重的事情下层的IP层路由发生了变化只是原因之一但是发生了严重事情后的行为需要更加保守所以这个时候废除socket的路由缓存是一个好主意。附录附1RELATED实现的细节什么是RELATED流所谓的RELATED流并不是自发产生的流而是由别的流引起的流典型地我将RELATED流分为两类1. 可预期的带内流这类的典型例子就是FTP协议在一个连接中发起另一个连接另外还有H.323协议SIP协议等等也属于这类。也就是说通过解析原始的数据包就能知道后面会有什么样的流通过换句话说就是这些RELATED流是可预期的。2. 不可预期的带外控制流如果一个数据包在某跳发生了路由不可达事件当前节点会向源端发送一个ICMP消息鉴于IP是无连接无状态的对于它已经经过的所有节点而言这个ICMP完全是不可预期的只能通过分析这个ICMP数据包的内容来判断它和哪个流相关联。以上两类都属于RELATED流那么Linux是如何处理它们的呢我们先看数据包进入conntrack处理逻辑后第一个要干的事即nf_conntrack_in里面发生的事nf_conntrack_in(){l4proto __nf_ct_l4proto_find(pf, protonum);// 首先调用特定四层协议的error函数if (l4proto-error ! NULL) {ret l4proto-error(net, tmpl, skb, dataoff, pf, hooknum);if (ret 0) {return ret;}}// 然后再关联conntrack表项ret resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,l3proto, l4proto);...}从error回调的调用来看如果收到的数据包是一个ICMP包且ICMP协议有error回调的话它是一定会被调用的。ICMP当然有error回调icmp_error(){struct nf_conntrack_tuple innertuple...innertuple ICMP包内容中解析出来的引发它的原始数据包的元组ctinfo IP_CT_RELATED;h nf_conntrack_find_get(net, zone, innertuple);// 关联RELATED包到原始的conntrack表项nf_ct_set(skb, nf_ct_tuplehash_to_ctrack(h), ctinfo);}这意味着对于ICMP错误消息而言并不产生新的conntrack表项而是重用引发它的原始conntrack表项但这并不是RELATED的全部对于可预期的RELATED流而言事情远没有这么简单。假设来了一个新的流并为其创建了一个新的conntrack表项内核是怎么知道这个新的流是真正独立的新流还是由前面某个旧的流引发的预期中的流呢为了实现上述的判断系统需要把所有预期中的流全部保存到一个容器中然后每到来一个新流都会去检索这个预期流容器只要能在这个容器中被检索到就为其打上RELATED标签说明这个流并不是独立的。新流的检索逻辑如下init_conntrack(){... // 省略例行创建部分这里只关注expect流if (net-ct.expect_count) {// 全局自旋锁spin_lock(nf_conntrack_expect_lock);// 检索预期中的流表exp nf_ct_find_expectation(net, zone, tuple);if (exp) {// 打上RELATED标签过程省略...}spin_unlock(nf_conntrack_expect_lock);}...}虽然在理论上每到来一个新流都要去检索预期表但是内核在这里做了一个大大的优化如果你知道你的预期表是空的你还要去检索它吗虽然查一个空表也不费什么事儿但问题的关键在于这个全局的自旋锁在多核环境下100个CPU同时锁一下再释放玩呢所以说这个优化在于如果没有查表的必要就不去查了。这个优化依托于这样一个事实即内核在往预期流表中添加或者删除一个项时它是知道这件事的也就是说内核知道预期表的当前项目数量如果项目数量为0那便可以避开全局自旋锁了撸一下代码就知道expect_count这个变量在nf_ct_expect_insert(当特定协议【比如FTP】的helper回调中发现了一个可以预期的流时会创建一条预期流项插入到一个expect流表中)中递增这正是新建一个预期表项的时刻。这个优化太有深意了几乎是一个通用的范式言归正传但也没几句话了在预期的流和不可预期的流都被打上了RELATED标识后就可以用以下的iptables规则识别了iptables -t mangle -A PREROUTING -m state --state RELATED ...以上就是RELATED机制实现的全部了。附2local路由表可以添加删除啦曾经我抱怨过一个事实那就是数据包到达首先要无条件判断的就是这个包是不是发给本机的如果是发给本机的除非用iptables重新折腾它便被本机无条件接收而根本就没有机会去查策略路由表。但是现在事情起了变化local表现在可以删除和重新添加了ip ru del pref 0 tab local从而路由表排序可以变成下面的样子10: from all fwmark 0x7b lookup 12332765: from all lookup local32766: from all lookup main32767: from all lookup default这不知给多少玩家带来了福音啊后记通过世俗的方式将宿命转化为连续把偶然转化为意义本文原创作者Bomb250
http://www.zqtcl.cn/news/996511/

相关文章:

  • 建设银行网站背景图片温州做网站哪家比较好
  • 网站架设建设如何做网站电话
  • 团购网站怎么推广app平台搭建步骤
  • 沂水建设局网站郑州企业微网站建设
  • 免费企业网站空间wordpress目录主题
  • 做网站的销售话术苏州网站设计哪家公司好
  • 足球梦网站建设的基本思路网站介绍词
  • 森马网站建设情况网站推广中应注意哪些事项
  • 简单网站vs2008不能新建网站
  • 牌具做网站可以吗海外广告投放公司
  • 响应式单页网站模板宁波企业自助建站
  • 网站广告收费标准装饰设计公司起名
  • 网站开发人员构成中国兰州网官网
  • 网站设计的提案旅游网站建设风格
  • 成都网站建设的公司做高大上分析的网站
  • 专业企业网站建设公司成都的网站
  • 广东省建设教育协会官方网站首页怎么设置wordpress头像
  • 图书网站建设论文页游中心
  • 建网站的流程及注意事项任务网站建设
  • 河北邯郸做网站的公司哪家好辽源市住房和城乡建设局网站
  • 网站系统建设技术服务费安康市网站建设
  • 网络运行管理系统seo关键词优化方法
  • 西安学校网站建设价格徐州网页关键词优化
  • 上海哪个网站能应聘做家教的营销网站中最重要的部分是
  • 一个设计网站多少钱WordPress的简约博客主题
  • 普通的宣传网站用什么做济南市工程建设技术监督局网站
  • 合肥网站建设公司还有不dw如何制作表格网页
  • 讯美智能网站建设自己域名做网站
  • 自己做网站优化韩国外贸平台
  • 齐河建设局网站长沙市住房和建设局官方网站