一、上节回顾

上一节,我们探究了网络延迟增大问题的分析方法,并通过一个案例,掌握了如何用hping3、tcpdump、Wireshark、strace 等工具,来排查和定位问题的根源。

简单回顾一下,网络延迟是最核心的网络性能指标。由于网络传输、网络包处理等各种因素的影响,网络延迟不可避免。但过大的网络延迟,会直接影响用户的体验。

所以,在发现网络延迟增大的情况后,你可以先从路由、网络包的收发、网络包的处理,再到应用程序等,从各个层级分析网络延迟,等到找出网络延迟的来源层级后,再深入定
位瓶颈所在。

今天,我再带你来看看,另一个可能导致网络延迟的因素,即网络地址转换(NetworkAddress Translation),缩写为 NAT。

接下来,我们先来学习 NAT 的工作原理,并弄清楚如何优化 NAT 带来的潜在性能问题

二、NAT 原理

NAT 技术可以重写 IP 数据包的源 IP 或者目的 IP,被普遍地用来解决公网 IP 地址短缺的问题。它的主要原理就是,网络中的多台主机,通过共享同一个公网 IP 地址,来访问外网资源。同时,由于 NAT 屏蔽了内网网络,自然也就为局域网中的机器提供了安全隔离。

你既可以在支持网络地址转换的路由器(称为 NAT 网关)中配置 NAT,也可以在 Linux服务器中配置 NAT。如果采用第二种方式,Linux 服务器实际上充当的是“软”路由器的角色。

NAT 的主要目的,是实现地址转换。根据实现方式的不同,NAT 可以分为三类:

  1. 静态 NAT,即内网 IP 与公网 IP 是一对一的永久映射关系;
  2. 动态 NAT,即内网 IP 从公网 IP 池中,动态选择一个进行映射;
  3. 网络地址端口转换 NAPT(Network Address and Port Translation),即把内网 IP 映
  4. 射到公网 IP 的不同端口上,让多个内网 IP 可以共享同一个公网 IP 地址。

NAPT 是目前最流行的 NAT 类型,我们在 Linux 中配置的 NAT 也是这种类型。而根据转换方式的不同,我们又可以把 NAPT 分为三类。

第一类是源地址转换 SNAT,即目的地址不变,只替换源 IP 或源端口。SNAT 主要用于,多个内网 IP 共享同一个公网 IP ,来访问外网资源的场景。

第二类是目的地址转换 DNAT,即源 IP 保持不变,只替换目的 IP 或者目的端口。DNAT主要通过公网 IP 的不同端口号,来访问内网的多种服务,同时会隐藏后端服务器的真实IP 地址。

第三类是双向地址转换,即同时使用 SNAT 和 DNAT。当接收到网络包时,执行DNAT,把目的 IP 转换为内网 IP;而在发送网络包时,执行 SNAT,把源 IP 替换为外部IP。

双向地址转换,其实就是外网 IP 与内网 IP 的一对一映射关系,所以常用在虚拟化环境中,为虚拟机分配浮动的公网 IP 地址。

为了帮你理解 NAPT,我画了一张图。我们假设:

  1. 本地服务器的内网 IP 地址为 192.168.0.2;
  2. NAT 网关中的公网 IP 地址为 100.100.100.100;
  3. 要访问的目的服务器 baidu.com 的地址为 123.125.115.110。

那么 SNAT 和 DNAT 的过程,就如下图所示:

从图中,你可以发现:

  1. 当服务器访问 baidu.com 时,NAT 网关会把源地址,从服务器的内网 IP 192.168.0.2替换成公网 IP 地址 100.100.100.100,然后才发送给 baidu.com;
  2. 当 baidu.com 发回响应包时,NAT 网关又会把目的地址,从公网 IP 地址100.100.100.100 替换成服务器内网 IP 192.168.0.2,然后再发送给内网中的服务器。

了解了 NAT 的原理后,我们再来看看,如何在 Linux 中实现 NAT 的功能。

三、iptables 与 NAT

Linux 内核提供的 Netfilter 框架,允许对网络数据包进行修改(比如 NAT)和过滤(比如防火墙)。在这个基础上,iptables、ip6tables、ebtables 等工具,又提供了更易用
的命令行接口,以便系统管理员配置和管理 NAT、防火墙的规则。

其中,iptables 就是最常用的一种配置工具。要掌握 iptables 的原理和使用方法,最核心的就是弄清楚,网络数据包通过 Netfilter 时的工作流向,下面这张图就展示了这一过程。

在这张图中,绿色背景的方框,表示表(table),用来管理链。Linux 支持 4 种表,包括filter(用于过滤)、nat(用于 NAT)、mangle(用于修改分组数据) 和 raw(用于原
始数据包)等。

跟 table 一起的白色背景方框,则表示链(chain),用来管理具体的 iptables 规则。每个表中可以包含多条链,比如:

  1. filter 表中,内置 INPUT、OUTPUT 和 FORWARD 链;
  2. nat 表中,内置 PREROUTING、POSTROUTING、OUTPUT 等。

当然,你也可以根据需要,创建你自己的链。

灰色的 conntrack,表示连接跟踪模块。它通过内核中的连接跟踪表(也就是哈希表),记录网络连接的状态,是 iptables 状态过滤(-m state)和 NAT 的实现基础。
iptables 的所有规则,就会放到这些表和链中,并按照图中顺序和规则的优先级顺序来执行。

针对今天的主题,要实现 NAT 功能,主要是在 nat 表进行操作。而 nat 表内置了三个链:

  1. PREROUTING,用于路由判断前所执行的规则,比如,对接收到的数据包进行DNAT。
  2. POSTROUTING,用于路由判断后所执行的规则,比如,对发送或转发的数据包进行SNAT 或 MASQUERADE。
  3. OUTPUT,类似于 PREROUTING,但只处理从本机发送出去的包。

熟悉 iptables 中的表和链后,相应的 NAT 规则就比较简单了。我们还以 NAPT 的三个分类为例,来具体解读一下。

1、SNAT

根据刚才内容,我们知道,SNAT 需要在 nat 表的 POSTROUTING 链中配置。我们常用两种方式来配置它。

第一种方法,是为一个子网统一配置 SNAT,并由 Linux 选择默认的出口 IP。这实际上就是经常说的 MASQUERADE:

iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -j MASQUERADE

第二种方法,是为具体的 IP 地址配置 SNAT,并指定转换后的源地址:

iptables -t nat -A POSTROUTING -s 192.168.0.2 -j SNAT --to-source 100.100.100.100

2、DNAT

再来看 DNAT,显然,DNAT 需要在 nat 表的 PREROUTING 或者 OUTPUT 链中配置,其中, PREROUTING 链更常用一些(因为它还可以用于转发的包)。

iptables -t nat -A PREROUTING -d 100.100.100.100 -j DNAT --to-destination 192.168.0.2

3、双向地址转换

双向地址转换,就是同时添加 SNAT 和 DNAT 规则,为公网 IP 和内网 IP 实现一对一的映射关系,即:

iptables -t nat -A POSTROUTING -s 192.168.0.2 -j SNAT --to-source 100.100.100.100
$ iptables -t nat -A PREROUTING -d 100.100.100.100 -j DNAT --to-destination 192.168.0.2

在使用 iptables 配置 NAT 规则时,Linux 需要转发来自其他 IP 的网络包,所以你千万不要忘记开启 Linux 的 IP 转发功能。

你可以执行下面的命令,查看这一功能是否开启。如果输出的结果是 1,就表示已经开启了 IP 转发:

sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

如果还没开启,你可以执行下面的命令,手动开启:

sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

当然,为了避免重启后配置丢失,不要忘记将配置写入 /etc/sysctl.conf 文件中:

cat /etc/sysctl.conf | grep ip_forward
net.ipv4.ip_forward=1

讲了这么多的原理,那当碰到 NAT 的性能问题时,又该怎么办呢?结合我们今天学过的NAT 原理,你先自己想想,动手试试,下节课我们继续“分解”。

五、小结

今天,我们一起学习了 Linux 网络地址转换 NAT 的原理。

NAT 技术能够重写 IP 数据包的源 IP 或目的 IP,所以普遍用来解决公网 IP 地址短缺的问题。它可以让网络中的多台主机,通过共享同一个公网 IP 地址,来访问外网资源。同时,
由于 NAT 屏蔽了内网网络,也为局域网中机器起到安全隔离的作用。

Linux 中的 NAT ,基于内核的连接跟踪模块实现。所以,它维护每个连接状态的同时,也会带来很高的性能成本。具体 NAT 性能问题的分析方法,我们将在下节课继续学习。

Linux性能优化实战学习笔记:第四十一讲的更多相关文章

  1. Linux性能优化实战学习笔记:第三十六讲

    一.上节总结回顾 上一节,我们回顾了经典的 C10K 和 C1000K 问题.简单回顾一下,C10K 是指如何单机同时处理 1 万个请求(并发连接 1 万)的问题,而 C1000K 则是单机支持处理 ...

  2. Linux性能优化实战学习笔记:第四十四讲

    一.上节回顾 上一节,我们学了网络性能优化的几个思路,我先带你简单复习一下. 在优化网络的性能时,你可以结合 Linux 系统的网络协议栈和网络收发流程,然后从应用程序.套接字.传输层.网络层再到链路 ...

  3. Linux性能优化实战学习笔记:第四十八讲

    一.上节回顾 上一节,我们一起学习了如何分析网络丢包的问题,特别是从链路层.网络层以及传输层等主要的协议栈中进行分析. 不过,通过前面这几层的分析,我们还是没有找出最终的性能瓶颈.看来,还是要继续深挖 ...

  4. Linux性能优化实战学习笔记:第五十二讲

    一.上节回顾 上一节,我们一起学习了怎么使用动态追踪来观察应用程序和内核的行为.先简单来回顾一下.所谓动态追踪,就是在系统或者应用程序还在正常运行的时候,通过内核中提供的探针,来动态追踪它们的行为,从 ...

  5. Linux性能优化实战学习笔记:第三十二讲

    一.上节总结 专栏更新至今,四大基础模块的第三个模块——文件系统和磁盘 I/O 篇,我们就已经学完了.很开心你还没有掉队,仍然在积极学习思考和实践操作,并且热情地留言与讨论. 今天是性能优化的第四期. ...

  6. Linux性能优化实战学习笔记:第五十八讲

    一.上节回顾 专栏更新至今,咱们专栏最后一部分——综合案例模块也要告一段落了.很高兴看到你没有掉队,仍然在积极学习思考.实践操作,并热情地分享你在实际环境中,遇到过的各种性能问题的分析思路以及优化方法 ...

  7. Linux性能优化实战学习笔记:第十八讲

    一.内存的分配和回收 1.管理内存的过程中,也很容易发生各种各样的“事故”, 对应用程序来说,动态内存的分配和回收,是既核心又复杂的一的一个逻辑功能模块.管理内存的过程中,也很容易发生各种各样的“事故 ...

  8. Linux性能优化实战学习笔记:第三十一讲

    一.上节回顾 上一节,我们一起回顾了常见的文件系统和磁盘 I/O 性能指标,梳理了核心的 I/O 性能观测工具,最后还总结了快速分析 I/O 性能问题的思路. 虽然 I/O 的性能指标很多,相应的性能 ...

  9. Linux性能优化实战学习笔记:第五十六讲

    一.上节回顾 上一节,我带你一起梳理了,性能问题分析的一般步骤.先带你简单回顾一下. 我们可以从系统资源瓶颈和应用程序瓶颈,这两个角度来分析性能问题的根源. 从系统资源瓶颈的角度来说,USE 法是最为 ...

  10. Linux性能优化实战学习笔记:第五十七讲

    一.上节回顾 上一节,我带你一起梳理了常见的性能优化思路,先简单回顾一下.我们可以从系统和应用程序两个角度,来进行性能优化. 从系统的角度来说,主要是对 CPU.内存.网络.磁盘 I/O 以及内核软件 ...

随机推荐

  1. vue自定义事件---拖拽

    margin布局拖拽 Vue.directive('drag', { bind(el, binding, vnode, oldVnode) { const dialogHeaderEl = el.qu ...

  2. ElementUI中如何实现Form表单内的文字居中

    <el-table :data='orderList' border stripe :align='center' :cell-style='cellStyle' :header-cell-st ...

  3. spring的@ControllerAdvice注解

    @ControllerAdvice注解是Spring3.2中新增的注解,学名是Controller增强器,作用是给Controller控制器添加统一的操作或处理. 对于@ControllerAdvic ...

  4. c# sqlserver 删除大批量数据超时

    我做的项目有个功能需要进行批量删除,删除的数据量有4.5W条数据. 通过下面的sql语句删除这么多数据,直接导致结果超时,无法删除数据. ,,,......) 我查了一些资料,可能找的不全,找到了一个 ...

  5. centos systemd占用大量内存

    不知道为什么,我用vmware做测试用,而且是mini版本,没装什么应用,就是php开发环境,lnmp. 在开发时,内存和swap都爆满,composer包无法安装. 网上搜到解决方法: system ...

  6. Python 摘要算法hashlib 与hmac

    参考链接:https://www.liaoxuefeng.com/wiki/1016959663602400/1017686752491744 摘要算法(也成为哈希算法)是用来防篡改的,因为我们的即使 ...

  7. Java学习——枚举类

    Java学习——枚举类 摘要:本文主要介绍了Java的枚举类. 部分内容来自以下博客: https://www.cnblogs.com/sister/p/4700702.html https://bl ...

  8. 【maven】测试

    针对spring-boot项目 通过命令行执行mvn命令来启动测试模块. 1.引入plugin 并自定义参数ignore.test 2.命令行传递参数启动test mvn clean package ...

  9. 运算符 &(与运算)、|(或运算)、^(异或运算)

    按位与运算符(&) 参加运算的两个数据,按二进制位进行“与”运算. 运算规则:0&0=0;  0&1=0;   1&0=0;    1&1=1; 按位或运算符( ...

  10. SQL行转列,列转行

    SQL 行转列,列转行 行列转换在做报表分析时还是经常会遇到的,今天就说一下如何实现行列转换吧. 行列转换就是如下图所示两种展示形式的互相转换 行转列 假如我们有下表: SELECT * FROM s ...