Linux 4.10中两个新特性与我的一段故事

今早5点半起来没有开始写文章,而是去西湾红树林连跑带走折腾了将近20公里,回来后就8点多了...洗了个澡之后坐稳当,开始写一段关于我的故事。
        在2014年到2015年期间,我在负责研发一款无线安全网关,其实就是一个VPN,接入设备包括手机,xPad,盒子...这些设备的OS除了iOS之外,基本上都是基于Linux的Android。这个网关一般用于各种需要高性能加密通信的场合,在数据传输之前需要比较强的认证,服务端支持4G的加密带宽,支持复杂的接入控制和访问控制,支持复杂的Qos,另外,还可以将两台甚至多台VPN网关设备对接形成一个复杂的网状混合拓扑,支持网中网,功能非常强大...广告做到此为止。
        现在开始说说接入设备,也就是客户端的一些事。
        在研发以及部署期间,其实最头疼的不是网关端,而是接入设备端,也就是那些Android客户端。
        典型的需求是,为一组App构建一个沙盒,沙盒里的App走VPN通道到网关,而沙盒外的App不受任何影响。比方说,交警使用的移动警务App的数据显然要进行保护,而交警在轮班期间无聊时看看新浪微博则不应该受到影响,且移动警务App和新浪微博不能互访。
...
我曾经花了比较多的精力去跟客户解释我们的Android客户端多么的“智能”,可以保证特定的且仅仅是特定的App的数据才会进入VPN隧道,这其实是MDM厂商的活儿,对于我的产品,这只是个附加的功能。于是,为了实现这个功能,就不得不不断调研Android的某个版本在非root情况下是否可以操作路由表,操作iptables(这个可能性不大),可不可以NAT,如果可以的话,是不是通过一个本地监听的代理程序可以完成导流的工作...对于以TUN网卡实现的VPN而言,其实这一切工作归根结底只是一个需求:让特定的App数据发出时走特定的路由!
        可惜,在之前的Android内核版本中,这么一个简单的需求实现起来非常不易。现在Linux 4.10内核带来了一个新的特性,即为不同的uid配置不同的策略路由,这足以解决我的问题,只是晚了大概两三年:
Add support for per-UID routing. It allows the administrator to configure rules such as:
# ip rule add uidrange 100-200 lookup 123.
This functionality has been in use by all Android devices since 5.0. It is primarily used to impose per-app routing policies (on Android, every app has its own UID) without having to resort to rerouting packets in iptables, which breaks getsockname() and MTU/MSS calculation, and generally disrupts end-to-end  connectivity

另一个比较激动人心的特性来自于路由和iptables的联动。
        早在2014年年底,我在OpenVPN的程序里面内置了一张路由表,这是为了防止有人手工添加一条路由,这样就可以访问不该访问的资源了。也许你会觉得在服务端做足做够访问控制不是很好吗?是的,这个我也知道,我自诩精通OpenVPN,从源码到配置再到优化重构,怎么可能不知道这个。令我激动的是Linux内核终于提供了一个不依赖OpenVPN的通用机制来实现这个需求:
Introduce an nftables rt expression for routing related data with support for nexthop (i.e. the directly connected IP address that an outgoing packet is sent to), which can be used either for matching or accounting, e.g.
# nft add rule filter postrouting ip daddr 192.168.1.0/24 rt nexthop != 192.168.0.1 drop
this will drop any traffic to 192.168.1.0/24 that is not routed via 192.168.0.1
看吧,这是使用nftables而不是iptables配置的。这并不是我对nftables的又一个鼓噪点,而是想表达iptables已经逐步迁移到nftables了。要是在两年前,我肯定会写一个iptables的模块,但是现在不会了。
...
现在说说我的另一段故事,可从中窥见很多网络技术。
        曾经有四个难题让我没日没夜几个月,不过幸运的是,这些问题最终都被我用Netfilter解决了:
1.路由查找与转发开销比较大
起初我是借助优化后的nf_conntrack来解决问题的。总的来讲就是将IP层的处理进行短路,借鉴于Cisco的CEF技术分离出一个转发表,然后将表项保存在conntrack项中。后来我干脆抛弃了conntrack,而是直接使用了DxRPro这个结构来完成查找,具体参见《以DxR算法思想为基准设计出的路由项定位结构图解》。
当初之所以使用conntrack是因为它可以高效定位一个流并保存流信息,而转发项可以保存在流中...如果有一种比定位流更加高效的方式,那就不需要conntrack了,事实证明我找到了这种更高效的方式。
2.过滤条目太多,导致了收包性能急剧下降
饱受诟病的iptables filter被我彻底放弃了,取而代之的是nf-HiPac以及ipset,后来我又发现了更好的方式,当我在路由查找中把conntrack放弃了之后,我将其引入到了ACL匹配。具体来讲就是,我把流的首包ACL结果保存在conntrack表项中,后面直接使用,无需再匹配。当然,我的conntrack是被我优化过的,不是原生的。
3.Linux中无法配置双向静态NAT。
关于Linux的NAT,它本来就是保存在conntrack中的,仅对首包匹配NAT规则,然后对于后续的包直接从conntrack取出后使用。所以说就无法是静态的,也无法是双向的。我的做法是简单的实现了一个新的NAT机制:https://github.com/marywangran/static-stateless-2-way-NAT-on-Linux-with-iptables
        所有以上这三个问题,除了最后一个,总的思路,就是一次查找,保存后多次使用。
        面对这三个问题,解题思路以及解决方案几乎占据了我这个博客的大量的篇幅,我也因此得到了公司的认可以及新的工作机会。然而如果就此停步不前,那就可悲了。
        网络技术一直都在迅速发展,每天都有新的东西冒出来,必须不断学习才能永远被公司认可,永远不缺新的机会。
4.Linux Bridge问题
我清晰地记得我在2010年3月19日去我上一家公司面试时被问到的一个问题:你对Linux Bridge有了解吗?我说有了解,于是我就试着说说看...其实那个时候我也只是看过Linux Bridge的源码而已,好在面试官(后来成了我职业生涯中都要感谢并永远不会忘记的恩师...)所在的业务组并不以这个Bridge为主导,所以我也就蒙混过关了,充其量当时我也就知道Brdige的大致原理,更进一步的东西也说不清。
        我本以为从此以后再也与Linux网络无缘了,可是非也...到了2011年底,我要做的事情奠定了我今后的技术路线。
        说实话,我做的VPN产品可能囊括了所有的Linux网络技术,从下到上说吧,PCIE,MSI,软中断负载均衡,Bonding,Spanning Tree,Bridge调用IP Netfilter,IP层Netfilter,IP路由,策略路由,TCP分发,TUN字符设备,TLS加密解密(对称加密,非对称加密,摘要...),HTTP,HTTPS(我尽力去学习,却最终也没有学会http相关的应用层...),VRRP,HSRP,OSPF...期间我学会了ECC椭圆曲线算法,也知道了什么叫做双证书认证,但是我觉得对我最重要的是我在2013年就修改了Linux Bridge的逻辑,使得其符合了SDN的思想!
        What?Why?
        2013年的时候,SDN已经被提出很多年了,但是我并不知道这个概念,我确实是在2013年中下才知道的这个概念,好像当时还写了几篇软文(一般不懂装懂的人都会写软文),但是明白了SDN深意之时却在多年以后。
...
我关注SDN是因为我觉得它跟我当时正在做的东西的思路不谋而合。我当时在网络层需要一种集中的控制机制,不管是路由策略还是QoS,都需要在一个中心端来集中控制,然后把策略下发到各个子节点,子节点没有什么智能逻辑,它只是盲目执行中心端下发的策略而已,我这种做法看似是与分布式网络控制机制背道而驰的,但我厌倦了Spanning Tree,RIP这种不可控的东西,同时我也不喜欢TCP,不喜欢区块链,我需要找到一个理论依托来支持我的独裁式集中控制机制,后来在一天下班的路上,我用手机看技术网站,发现了SDN这个概念...
        这个跟Bridge有什么关系呢?
        我当时希望数据包绕过IP路由,直接执行集中式的VPN中心端下发的策略即可,这些策略不仅仅包括路由,还包括别的很多其它的,比如是二层透传还是三层路由。所以说我需要自定义一个匹配链,每一个数据包都要去匹配这个匹配链,一旦命中便执行该匹配项指示的动作,类似iptables那样。不过是直接借用了conntrack连接跟踪。这样匹配链就可以直接用conntrack本身了,然后在conntrack项中增加一个action字段,数据包进入内核协议栈之后会被无条件关联一个conntrack表项,然后直接执行该conntrack表项指示的动作即可。
        但是大家都知道,nf_conntrack是作用于PREROUTING点的,这已经位于IP层了。我希望的是在Bridge层就做匹配,然后根据匹配好的conntrack表项的action来决定是直接Bridge层转发还是broute到IP层。幸好,Linux Bridge有一个call ip netfilter机制(详见/proc/sys/net/bridge/bridge-nf-call-iptables),正合我意!可是这个call点是在决定了是否Redirect之后才执行的,于是我不得不颠倒二者的位置,参见《关于bridge-nf-call-iptables的设计问题》。
        在我的这个设计中,系统的IP路由机制几乎是不起作用的。子节点VPN守护进程会从中心节点接收转发策略,并注入到conntrack表项,然后就可以来包转发了。我编程编的不好,但我对Linux内核协议栈流程非常了解,所以我可以做到利用一切现成的东西,小修小改即可满足我的需求,我借用了conntrack,我借用了bridge-nf-call-iptables...
那个时候我还不知道OVS(即Openvswitch),要是知道有这么个玩意儿,我连conntrack,Bridge都不用了,仔细看看,OVS实现我上面的需求,是不是很直接呢?本质上来讲,OVS就是强化版的Linux Bridge,以前需要你前挪后移搬运的功能现在都集成在OVS内部了。OVS内部就有一个流表,而且还是多级的,可以接收SDN控制器注入的流表项,一切都是已经标准化的,现成的东西也多。我要是早几年知道有这么个OVS,那得减少多大的工作量啊。
        我还没提VxLAN呢,也没提LISP,其实本质上它们都是建立大二层的技术,我做事随意,崇尚草根之风,用OpenVPN建立了大二层,盖在了上海市的一个城域网中,这不就是Overlay么...
        至于NFV,也不过是一个名词。我很怀念我的那个花了无数个日日夜夜做成的东西,它里面包含了太多的东西,如果掌握了它,你也就掌握了网络的核心技术之脉络,在开发期间,接触了各种Linux内核网络的东西,在部署期间,有幸与CCNP/IE们各种交锋,掌握了核心网的很多东西,甚至在送货的路上,深夜回家的路上,都会突然冒出很多想法...故事还没有讲完,但我不想再讲下去了。对于给我机会做这事情的经理而言,除了感谢,还是感谢!
        下面准备说说BGP和DCI的事情...如果明天有时间的话。

时间: 2024-08-27 01:52:43

Linux 4.10中两个新特性与我的一段故事的相关文章

ArcGIS 10.3 for Desktop新特性介绍

ArcGIS 10.3是一个完整公布的ArcGIS平台,它包含新的产品(ArcGIS Pro),针对10.2版本号产品进行了功能增强和稳定性的改进. ArcGIS 10.3 for Server新特性介绍 http://blog.csdn.net/linghe301/article/details/31358733 ------------------------------------------------------------------ 版权全部,文章同意转载,但必须以链接方式注明源地

ArcGIS 10.1 for Desktop新特性之地质标记照片

原文地址:http://www.myexception.cn/cgi/550694.html ArcGIS 10.1 for Desktop新特性之地理标记照片 1. 地理标记照片简介 地理标记照片是指带有地理位置信息的照片,通常通过内置GPS的数码相机或智能手机拍摄得到. 如果能够在GIS软件中直接载入地理标记照片,并且自动生成对应的点,包含照片和时间等相关的属性信息,那么对于许多涉及外业数据采集.外业巡检的行业将十分有用.例如,环保执法人员可以手持移动设备到现场采集环保违规照片,然后将照片叠

VS2015 C#6.0 中的那些新特性

? VS2015 C#6.0 中的那些新特性 前言 ? ? ? VS2015在自己机器上确实是装好了,费了老劲了,想来体验一下跨平台的快感,结果被微软狠狠的来了一棒子了,装好了还是没什么用,应该还需要装Xarmain插件,配置一些参数吧,由于这块之前从未接触过,想了想还是先不把时间继续浪费在这里了,于是乎来体验一下新特性了. 本人个人博客原文链接地址为http://aehyok.com/Blog/Detail/66.html. ? ?本文参考http://roslyn.codeplex.com,

Oracle12c中数据泵新特性之功能增强(expdp, impdp)

Oracle12c中数据泵新特性之功能增强(expdp, impdp) Oracle的数据泵功能在10g中被引进.本文对数据泵在12c中的增强做一个概览. 1.   禁用日志选项(DISABLE_ARCHIVE_LOGGING) Impdp的TRANSFORM参数已经扩展为包括DISABLE_ARCHIVE_LOGGING选项.该选项的默认值为 "N",不会影响日志行为.将该选项设置为"Y",这将会使表和索引在导入前将日指属性设置为NOLOGGING,从而导入期间减

MVC中的其他新特性

MVC中的其他新特性 (GlobalImport全局导入功能) 默认新建立的MVC程序中,在Views目录下,新增加了一个_GlobalImport.cshtml文件和_ViewStart.cshtml平级,该文件的功能类似于之前Views目录下的web.config文件,之前我们在该文件中经常设置全局导入的命名空间,以避免在每个view文件中重复使用@using xx.xx语句.默认的示例如下: @using BookStore @using Microsoft.Framework.Optio

解读ASP.NET 5 & MVC6系列(17):MVC中的其他新特性

原文:解读ASP.NET 5 & MVC6系列(17):MVC中的其他新特性 (GlobalImport全局导入功能) 默认新建立的MVC程序中,在Views目录下,新增加了一个_GlobalImport.cshtml文件和_ViewStart.cshtml平级,该文件的功能类似于之前Views目录下的web.config文件,之前我们在该文件中经常设置全局导入的命名空间,以避免在每个view文件中重复使用@using xx.xx语句.默认的示例如下: @using BookStore @usi

ES2019 中的 JavaScript 新特性

JavaScript 从成立之初就已经走了很长一段路,提供了许多新的功能,这些功能是专门设计来使该语言更加人性化和提升效率.以下是我最近发现的一些有趣的JavaScript 新增内容.其中一些功能已在 Node,Chrome,Firefox 和 Safari 中可用,而其他功能仍处于建议阶段. Optional chaining (可选链) Optional chaining 可选链使用 ?. 操作符来表示,Optional Chaining 使我们能检查一个对象上面是否存在某属性.其它一些语言

黑马程序员------Java中jdk1.5新特性

Java培训.Android培训.iOS培训..Net培训.期待与您交流! JDK1.5新特性: 为什么会出现新特性: 新的技术出现是为了解决老的问题,Java语言为了提高开发者的开发效率,对之前的某些不利于提高效率的技术进行改进. 静态导入: 静态导入:可以导入某个类下的静态方法,静态导入后,可以不写类名而直接使用此类下的静态方法. 语法:import static 包名.类名.静态方法 代码示例: package com.itheima.day1; /** * 静态导入 * @author

VS2013中F#的新特性

为了更好的迎接新版本的到来,先看一下之前F#的特性. 1.为区分联合(discriminated unions)添加了命名域,使代码更加清晰. 2.用新数据的新特性,使矢量和矩阵编码更容易的工作 3.更强大的泛型算法的扩展 4.得到更好的调试支持,当你使用F #调试时,调试编译器和解释器选项. 5.当你使用LINQ扩展方法如select时,lambda表达式将使你的代码非常简浩. 6.使用.NET框架4.5.1和Windows商店简化版的库支持. 7.支持同时在当前和以前的版本的VisualSt