<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/rss.xsl" type="text/xsl"?>
<rss version="2.0">
  <channel>
    <title>IT瘾网络推荐</title>
    <link>https://itindex.net/categories/网络</link>
    <description>IT社区推荐资讯 - ITIndex.net</description>
    <language>zh</language>
    <copyright>https://itindex.net/</copyright>
    <generator>https://itindex.net/</generator>
    <docs>http://backend.userland.com/rss</docs>
    <image>
      <url>https://itindex.net/images/logo.gif</url>
      <title>IT社区推荐资讯 - ITIndex.net</title>
      <link>https://itindex.net/categories/网络</link>
    </image>
    <item>
      <title>丹麦拟禁止15岁以下人群使用社媒，并提议免纸质书籍税：孩子应走出网络囚禁</title>
      <link>https://itindex.net/detail/63062-%E4%B8%B9%E9%BA%A6-%E4%BA%BA%E7%BE%A4-%E4%B9%A6%E7%B1%8D</link>
      <description>&lt;br /&gt;当地时间10月7日，丹麦首相弗雷泽里克森宣布，该国拟禁止15岁以下未成年人使用社交媒体。  &lt;br /&gt;  &lt;p&gt;丹麦首相弗雷泽里克森表示，手机和社交媒体“偷走了我们孩子的童年”。她还说：“我们释放了一个怪物。以前从未有这么多儿童和年轻人遭受焦虑和抑郁的困扰。”&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;弗雷泽里克森在10月7日的议会演讲上宣布了这项提案。她强调，许多孩子在阅读和集中注意力方面出现了困难，他们在屏幕上看到了儿童或年轻人不应该看到的东西。&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;丹麦60%11-19岁男孩 &lt;/p&gt;  &lt;p&gt;空闲时见不到一个朋友&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;弗雷泽里克森并没有具体说明新措施将影响哪些社交网络，但表示该提案将涵盖多个社交媒体平台。另外，13岁到15岁孩子的父母可以选择允许孩子使用社交媒体。&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;弗雷泽里克森在演讲中引用的数据显示，丹麦60%的11岁至19岁男孩在空闲时间里见不到一个朋友，而94%的七年级学生在13岁之前就在社交媒体上建立了个人账户。&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;丹麦数字部长卡罗琳·斯泰奇表示，丹麦政府的这项决定是一个突破。她说道：“我以前说过，现在再说一遍：我们太天真了。我们把孩子们的网络生活完全交给那些从未考虑过他们福祉的平台。”斯泰奇强调，孩子们应该从网络的囚禁中走出来，到实际生活中的社区中交朋友。&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;此前，丹麦于2月份宣布，将在所有学校禁止使用手机。2024年，丹麦有5万人签署请愿书，呼吁禁止社交媒体。&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;丹麦提议免书籍税&lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;希腊提议欧盟设定“数字成年年龄”&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;      &lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;丹麦在鼓励支持民众降低使用社交媒体的频率方面，做出了众多努力。今年8月，丹麦政府提出提案，将免除对纸质书籍征收的25%增值税。丹麦文化部长表示，这一政策旨在应对该国日益严重的“阅读危机”，尤其是在年轻人群体中。通过免税降低书籍价格，将改善目前年轻人沉迷网络的现状。他希望在书籍和社交媒体的竞争中，创造一个更公平的环境。&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;"&gt;&lt;/img&gt;  &lt;p&gt;▲丹麦哥本哈根河边的阅读者&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;丹麦出版商协会主管克里斯汀·博德切尔-汉森称，丹麦政府这一举措，反映了政策上对书籍价值和阅读文化重要性的认可，“在反思和批判性思维至关重要的时代，这一点比以往任何时候都更加重要。”&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;根据丹麦统计局的数据，丹麦90%的人口都在使用社交媒体，这一比例在欧盟中最高。丹麦所有16-19岁的青少年都在使用社交媒体。而且，丹麦20-34岁的年轻人中，98%的人都在使用社交媒体。 &lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;根据丹麦数字事务部的一项新研究，61%的丹麦人表示，他们在社交媒体上花费的时间超出了他们的预期。丹麦政府健康委员会最近的一项研究发现，社交媒体成瘾在女孩中尤为普遍：31%的13岁至17岁女孩表现出中度或重度社交媒体成瘾的迹象。 &lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;在欧洲，有越来越多的人认为，政府需要加大对大型社交媒体平台的监管力度。而丹麦走在了前面。丹麦政府顾问、数字化与心理健康领域专家伊姆兰·拉希德表示，丹麦从今年7月至12月担任欧盟轮值主席国，这意味着该国可以“为未来的欧盟技术监管奠定基础”。据了解，欧盟已经开始研究如何迫使大型社交媒体公司改变其极易上瘾的算法。&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;目前，澳大利亚已宣布禁止16岁以下人士使用脸书、油管等社交媒体平台。挪威总理斯特勒则表示，挪威将严格执行社交媒体的最低年龄限制，并且将使用社交媒体的最低年龄限制从13岁提高至15岁。斯特勒称，这将是一场“艰苦的战斗”，但政客们必须介入，保护儿童免受“算法的力量”的侵害。今年6月，希腊提议欧盟设定“数字成年年龄”，禁止儿童在未经父母同意的情况下访问社交媒体。&lt;/p&gt;  &lt;br /&gt;  &lt;img alt="&amp;#22270;&amp;#29255;"&gt;&lt;/img&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/63062-%E4%B8%B9%E9%BA%A6-%E4%BA%BA%E7%BE%A4-%E4%B9%A6%E7%B1%8D</guid>
      <pubDate>Thu, 09 Oct 2025 06:25:10 CST</pubDate>
    </item>
    <item>
      <title>网络安全专家爱用的逆向工具 Top9</title>
      <link>https://itindex.net/detail/62960-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8-%E4%B8%93%E5%AE%B6-%E5%B7%A5%E5%85%B7</link>
      <description>&lt;div&gt;    &lt;p&gt;逆向工程是指解构应用程序的过程，不论使用何种编程语言开发，目的是获得其源代码或其中的任何部分。逆向工程的代码有助于发现任何程序中的安全风险，也能用于解密任何恶意应用以进行干扰。      &lt;img alt="" src="https://image.3001.net/images/20241217/1734406966_6760f3360af9160622067.png!small"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;在寻找破解敏感数据或加密密钥的过程中，黑客们通常选择逆向工程作为一种选项，以找出整个系统中隐藏漏洞的所在之处。这导致了敏感数据的完全暴露，包括被硬编码到应用程序中的 API 密钥、 URL 和API 机密信息，开发人员用于测试的开发服务器 URL，非标准端口号，以及硬编码到应用程序文件及其子目录中的多个私钥等。&lt;/p&gt;    &lt;p&gt;逆向工程涉及一系列步骤，包括数据编译、记录元素和功能、评估数据、记录控制流、提取流结构、审查提取的设计、生成逆向工程文档。&lt;/p&gt;    &lt;p&gt;从实时跟踪运行的应用程序，解析二进制代码到汇编代码，管理和编辑二进制文件或嵌入式资源在 exe 文件中，逆向工具有各种各样的类型，根据其应用可以分为以下几类：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;反汇编器&lt;/li&gt;      &lt;li&gt;调试器&lt;/li&gt;      &lt;li&gt;数据包跟踪和分析工具&lt;/li&gt;      &lt;li&gt;脚本工具&lt;/li&gt;      &lt;li&gt;文件分析工具&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;以下分享&lt;/p&gt;    &lt;h2&gt;1.十六进制编辑器&lt;/h2&gt;    &lt;p&gt;十六进制编辑器是一组用于微软 Windows 的十六进制开发工具，结合了高级的二进制编辑和字处理器的简洁易用性和多功能性。它主要用于操纵构成计算机文件的基本二进制数据。&lt;/p&gt;    &lt;p&gt;此外，十六进制编辑器还支持查找、替换、比较、计算校验和、添加智能标签、颜色映射，并在一个扇区或文件中生成字符分布。十六进制编辑器还支持拖放功能，并可与所有的 Windows 操作系统集成，无论其迭代版本如何。&lt;/p&gt;    &lt;p&gt;根据其不同的功能和应用，有各种不同类型的十六进制编辑器，有些允许它们以可视化方式显示文件的内部结构。因此，您可能需要在最常用的工作空间中进行快速简单的十六进制编辑。&lt;/p&gt;    &lt;p&gt;数据检视器非常适合解释、查看和编辑十进制和二进制值。算术、逻辑、 ASCII 过程和位操作可用于帮助操作数据集。&lt;/p&gt;    &lt;p&gt;集成结构查看器使您能够直观而充分地编辑和查看数据。结构查看器验证信息结构、对各种网络的引用，以及许多原子数据类型：char 、byte 、ubyte 、word 、uword 、long 、ulong 、longlong 、float 、double 、OLE 日期/时间、 DOSTIME 、DOSDATE 、FILETIME 和time_t 。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;进行任何十六进制计算时非常方便&lt;/li&gt;      &lt;li&gt;提供多种选项&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;用户友好度不太高&lt;/li&gt;      &lt;li&gt;有时更新问题&lt;/li&gt;&lt;/ul&gt;    &lt;h2&gt;2.OllyDbg&lt;/h2&gt;    &lt;p&gt;OllyDbg 是一个针对 Microsoft Windows 的32 位汇编调试器。任何无法获得源代码的情况下，二进制代码的计算认知使得它在许多情况下都非常适用。此外，OllyDbg 是共享软件应用程序,可以下载使用。&lt;/p&gt;    &lt;p&gt;OllyDbg 的一些关键特性如下：&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;1.保存补丁以在会话之间返回到可执行文件并进行修补升级&lt;/p&gt;      &lt;p&gt;2.查找对象和库模式&lt;/p&gt;      &lt;p&gt;3.代码分析——跟踪记录、查找过程切换、 API 调用、表和循环常量和字符串&lt;/p&gt;      &lt;p&gt;4.DNow 、MMX 和为 Athlon 等SSE 数据类型和扩展提供指令&lt;/p&gt;      &lt;p&gt;5.识别高级配置，如对事件的请求&lt;/p&gt;      &lt;p&gt;6.用于执行的跟踪系统，日志已知可用于调和冲突&lt;/p&gt;      &lt;p&gt;7.查找错误命令和掩盖关键字&lt;/p&gt;      &lt;p&gt;8.检查和修改内存，设置断点并在不可见的情况下暂停应用程序&lt;/p&gt;      &lt;p&gt;9.在会话之间输入标记，将它们还原到可执行文件并修复更新&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;      &lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;共享软件，免费使用&lt;/li&gt;      &lt;li&gt;功能强大的动态调试器&lt;/li&gt;      &lt;li&gt;相对于 IDA 来说更容易操作&lt;/li&gt;      &lt;li&gt;允许直接加载和调试 DLL &lt;/li&gt;      &lt;li&gt;有脚本和插件可用&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;仅限于 Microsoft® Windows®&lt;/li&gt;      &lt;li&gt;只适用于 x86（或 32 位）软件&lt;/li&gt;      &lt;li&gt;不是静态调试器&lt;/li&gt;&lt;/ul&gt;    &lt;h2&gt;3.APKTool&lt;/h2&gt;    &lt;p&gt;Apktool 是另一种开源选择，主要用于 Android 逆向工程，可以将资源解码为几乎其原始形式。可以进行修改，并将其转换回二进制 APK/JAR 文件。&lt;/p&gt;    &lt;p&gt;此外，Apktool 还允许逐步调试 smali 代码，并且由于项目文件的结构以及对一些重复性操作的自动化，使得处理应用程序变得更加容易。使用该程序需要 Java 7 。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;在逆向 Android 应用文件方面高效&lt;/li&gt;      &lt;li&gt;可在网上免费使用&lt;/li&gt;      &lt;li&gt;社区支持良好&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;不如 JEB 反编译工具普遍&lt;/p&gt;    &lt;h2&gt;4.WireShark&lt;/h2&gt;    &lt;p&gt;Wireshark 是一个知名的网络和网络领域的工具。它是免费和开源的，是一个 Web 调试器，可以拦截和修改 HTTP 请求，并且可以记录 HTTPS 请求。它用于数据包分析和网络故障排除。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;免费且开源的 Web 调试器&lt;/li&gt;      &lt;li&gt;支持跨平台&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;对于初学者来说，可能会感到压力山大&lt;/li&gt;&lt;/ul&gt;    &lt;h2&gt;5.Scylla&lt;/h2&gt;    &lt;p&gt;Scylla 不是一个独立的工具，而更倾向于用于重构 Windows 的x86 和x64 文件的工具。它还具有全 Unicode 支持，并且与 Windows 7 、8 和10 完全兼容。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;一个开源的产品&lt;/li&gt;      &lt;li&gt;支持 x64 和x86 &lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;缺乏更新&lt;/li&gt;      &lt;li&gt;有时会有错误&lt;/li&gt;&lt;/ul&gt;    &lt;h2&gt;6.Dex2jar&lt;/h2&gt;    &lt;p&gt;Dex2jar 是一个 API，用于扫描 Dalvik Executable（.dex/.odex）格式。它与 Android 和Java .class 文件兼容。&lt;/p&gt;    &lt;p&gt;Dex2jar 包括以下几个组件：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;Dex-reader 用于扫描 Dalvik Executable（.dex/.odex）格式。它具有类似 ASM 的轻量级 API &lt;/li&gt;      &lt;li&gt;Dex-translator 用于执行转换工作。它读取 dex 指令以 dex-or 格式，经过一些优化后，转换为 ASM 格式&lt;/li&gt;      &lt;li&gt;Dex-用于它使用 Dex-translator 表示 dex 指令&lt;/li&gt;      &lt;li&gt;Dex-tools 用于处理.class 文件&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;示例：修改应用程序、解混淆一个.jar 文件。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;可以读取 Dalvik Executable 格式&lt;/li&gt;      &lt;li&gt;轻量级 API &lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;只与 Android 和Java .class 文件兼容&lt;/li&gt;&lt;/ul&gt;    &lt;h2&gt;7.CCF&lt;/h2&gt;    &lt;p&gt;CCF 是一个免费的便携式可执行编辑器，支持.NET 文件结构。 CCF 支持 32 位和 64 位PE 文件。 CCF 由NTCore 开发，还可用于解压缩 UPX 打包器。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;免费的 PE 编辑器&lt;/li&gt;      &lt;li&gt;也支持.NET 文件&lt;/li&gt;      &lt;li&gt;支持 PE 32 位和 64 位&lt;/li&gt;      &lt;li&gt;包含 PE 重建器&lt;/li&gt;      &lt;li&gt;可用于解压缩 UPX &lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;免费版本自 2012 年以来未更新&lt;/li&gt;&lt;/ul&gt;    &lt;h2&gt;8.Oracle VM VirtualBox&lt;/h2&gt;    &lt;p&gt;Oracle VM VirtualBox 是一个开源的虚拟化解决方案，在 Windows 、Mac 、Linux 等不同平台上皆可使用，用于在安全环境中分析恶意软件。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;免费且开源&lt;/li&gt;      &lt;li&gt;活跃的开发社区&lt;/li&gt;      &lt;li&gt;支持虚拟机操作系统&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;与 VMware 相比，功能略差&lt;/li&gt;&lt;/ul&gt;    &lt;h2&gt;9.BinaryNinja&lt;/h2&gt;    &lt;p&gt;目前没有反编译器，但计划在将来的“高级”版本中加入。 Binary Ninja 由Vector 35 开发，以其易用性而自豪，使得自动化比其他解决方案更容易理解。&lt;/p&gt;    &lt;p&gt;尽管易于使用，但该软件在反向工程本地主机中仍然存在一些问题。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;优点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;简单易用&lt;/li&gt;      &lt;li&gt;包含反汇编器&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;缺点：&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;不是调试器或反编译器&lt;/li&gt;      &lt;li&gt;有时无法加载用户界面&lt;/li&gt;      &lt;li&gt;免费版本有限&lt;/li&gt;&lt;/ul&gt;    &lt;blockquote&gt;      &lt;p&gt;参考来源：        &lt;a href="https://www.secureblink.com/blogs/top-9-reverse-engineering-hacking-tools-for-cyber-security-experts"&gt;https://www.secureblink.com/blogs/top-9-reverse-engineering-hacking-tools-for-cyber-security-experts&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62960-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8-%E4%B8%93%E5%AE%B6-%E5%B7%A5%E5%85%B7</guid>
      <pubDate>Tue, 17 Dec 2024 15:13:47 CST</pubDate>
    </item>
    <item>
      <title>只花不到 150 元，部署一套可能是最佳体验的家庭网络系统</title>
      <link>https://itindex.net/detail/62939-%E4%BD%93%E9%AA%8C-%E5%AE%B6%E5%BA%AD-%E7%BD%91%E7%BB%9C</link>
      <description>&lt;div&gt;  &lt;p&gt;原文地址:   &lt;a href="https://yojigen.tech/30.html" rel="nofollow" title="https://yojigen.tech/30.html"&gt;https://yojigen.tech/30.html&lt;/a&gt;&lt;/p&gt;  &lt;h2&gt;前言&lt;/h2&gt;  &lt;p&gt;哪个男孩不想要一个可以自由驰骋互联网的网络呢？&lt;/p&gt;  &lt;p&gt;关于家中的互联网建设这一块，已经不知道有多少博主聊过，自己也是来来回回折腾了很多种方案。&lt;/p&gt;  &lt;p&gt;最近终于找到了我直到目前为止我认为可能是最完美的方案——PaoPaoDNS+PaoPaoGateWay 。然后就在自己家的软路由系统里部署了起来，目前也是稳定用了一个月感觉非常的舒适。&lt;/p&gt;  &lt;p&gt;但是我家里面用的是软路由+虚拟机的方案，本身全套机器下载价格要 400 元左右了，而且机器也是做了一点点硬改，没有改机能力的人恐怕用起来也会比较麻烦。&lt;/p&gt;  &lt;p&gt;于是我就在想，能不能用比较便宜的方案，和较低的功耗，用一些市面上常见的设备来实现这一套方案呢？&lt;/p&gt;  &lt;h2&gt;最终预期的结果&lt;/h2&gt;  &lt;p&gt;在尽可能保证正常网络不会受到影响的情况下，实现网内透明代理，以用于科学上网。&lt;/p&gt;  &lt;p&gt;附赠功能: 去广告，虚拟局域网组网等&lt;/p&gt;  &lt;h2&gt;设备选择和采购&lt;/h2&gt;  &lt;p&gt;于是经过我的思考，最后做出了如下的设备方案:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;一台硬路由，要可以刷入支持设置静态路由，静态 DHCP 的系统(OpenWRT 、爱快、ROS 等)&lt;/li&gt;   &lt;li&gt;一台可以部署 Docker 容器的机器，例如一台小型 ARM 主机(玩客云，x905 电视盒子等)&lt;/li&gt;   &lt;li&gt;一台低功耗 x86 小主机(最好支持 AES 硬解)&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;以上设备各位读者可以根据自身的经济条件和现有的设备来决定如何选择，比如全放进虚拟机里之类。而我这次选择的设备是下面这几个。&lt;/p&gt;  &lt;h3&gt;硬路由-JCG Q30 Pro: 59 元&lt;/h3&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024090412211939_c4ca4238a0b92382.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024090412211939_c4ca4238a0b92382.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;这个价格不算特别的大众，这是一台天线坏掉的机器，而我的家里面因为还有三个其他的无线路由器当做 AP 使用，所以我不需要无线网络功能。&lt;/p&gt;  &lt;p&gt;这台机器的芯片是联发科的 mt7981 ，内存是 256m(也有 512m 的版本)，性能较好，可以轻松跑满千兆。而且这款机器还是被 OpenWRT 和 immortalwrt 官方支持的型号，可以直接刷主线版的固件，这样也可以避免一些网上所谓的“大神”编译的固件中的各种坑。&lt;/p&gt;  &lt;p&gt;机器怎么刷机我这里就不说了，网上有一些现成的资料，在这里说会导致教程太过于复杂，而且也许你的设备也不需要刷机，对吧。&lt;/p&gt;  &lt;p&gt;其实我个人目前比较推荐的机器是爱快 IK-Q3000 ，不用刷机就能享受官方的爱快的系统固件，机身自己支持 AX3000 ，如果没有其他无线组网，一台机器就能解决大部分人家中的路由和 WiFI 了。现在这个机器京东售价 159 ，同样所谓 mt7981 芯片的机器，他也就比别的机器贵了 20-30 。30 块钱买个免刷机带售后的爱快系统我觉得还是挺香的。(不过不清楚这台机器有没有硬件转发，如果没有的话还是不要用了)&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024090412213128_c81e728d9d4c2f63.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024090412213128_c81e728d9d4c2f63.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;ARM 主机-玩客云: 28 元&lt;/h3&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024090412214239_eccbc87e4b5ce2fe.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024090412214239_eccbc87e4b5ce2fe.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;玩客云算是我们垃圾佬应该非常熟悉的一个东西了，他本身是一个拿来做 PCDN 的所谓的“挖矿”设备，后续随着 PCDN 的收益越来越低，运营商对 PCDN 的打击等等原因，现在网上有着大量的机器在流通。而且由于存世量多，玩的人也多，这机器在价格便宜的同时，机器的玩法也开发的比较全面，很多系统都能刷入进去。&lt;/p&gt;  &lt;p&gt;我们这里选择给它刷入 Armbian ，以用来部署 Docker 容器，刷机方法大家也可以参考网络资料。&lt;/p&gt;  &lt;h3&gt;X86 小主机-中兴 CT321G2: 本人购入 79 元，咸鱼现价 50 元&lt;/h3&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024090412215356_a87ff679a2f3e71d.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024090412215356_a87ff679a2f3e71d.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024090412215911_e4da3b7fbbce2345.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024090412215911_e4da3b7fbbce2345.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;这个小机器是之前无意中发现的，机身外壳的做工还不错，虽然是塑料但是很厚实。这个机器由于只有一个千兆网口，不好做软路由，且只有一个无法更换 4g 硬盘，所以对于垃圾佬来说，可玩性就有点差了，导致价格一直不高。但是这台机器的 CPU 是小主机里面不太常见的 AMD GX-218GL ，这块 CPU 性能和 J1900 差不太多，功耗也都是在 10w 左右，但是他有一个 J1900 没有的优势: 支持 AES 硬解。&lt;/p&gt;  &lt;p&gt;大家都知道 AES 硬解意味着什么，加上小尺寸，低功耗，所以这台机器非常适合拿来做我们的网关机。&lt;/p&gt;  &lt;p&gt;注意: 这个机器只有 VGA 输出，需要你准备支持 VGA 的显示器和线，或者转换线。&lt;/p&gt;  &lt;h2&gt;系统搭建&lt;/h2&gt;  &lt;h3&gt;主网络&lt;/h3&gt;  &lt;p&gt;首先要保证你的网络是正常的，你需要了解如何使用你的路由器正确的设置上网功能。
我这里以最常见的网络地址作为演示，你可以根据你的需求来设置自己的网段。&lt;/p&gt;  &lt;pre&gt;   &lt;code&gt;路由器 IP: 192.168.1.1
DHCP 范围: 192.168.1.101-192.168.1.200
局域网段: 192.168.1.0/24
子网掩码: 255.255.255.0
网关机 IP: 192.168.1.2
Docker 容器机 IP: 192.168.1.3&lt;/code&gt;&lt;/pre&gt;  &lt;h3&gt;网关机&lt;/h3&gt;  &lt;p&gt;首先要准备一下 PaoPaoGateWay 的系统镜像，由于是在物理机运行，所以需要全网卡驱动的支持。官方 Github 上的镜像是默认不带全网卡驱动的，需要我们用官方的 docker 来定制一下 ios 镜像。
定制方式非常简单，随便找一台 x86 的装有 docker 的机器(官方容器不支持 arm)，运行下面两条命令，就能在当前目录获得一个具有全部网卡的 ios 镜像了。&lt;/p&gt;  &lt;pre&gt;   &lt;code&gt;docker pull sliamb/ppgwiso:fullmod
docker run --rm -v .:/data sliamb/ppgwiso:fullmod&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt;如果你不方便定制，也可以下载我定制好的镜像文件(记得解压)。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://github.com/mouyase/PaoPaoGateWay/releases/download/20240812-9eb91d3/paopao-gateway-x86-64-custom-364b136.zip" rel="nofollow"&gt;paopao-gateway-x86-64-custom-364b136.zip&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;准备一个写磁盘的工具，Rufus 、balenaEtcher 、UltraISO 之类的都可以，我这里使用 Rufus 。
准备一个 U 盘，将镜像文件写入到 U 盘里。&lt;/p&gt;  &lt;p&gt;然后将 U 盘插入 x86 小主机，在 Bios 里设置为从 U 盘启动系统，通电自动启动系统，最后用网线将网口和路由器的 Lan 口进行连接。&lt;/p&gt;  &lt;p&gt;这样网关机这里就算设置完成了。&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;注:&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;如果有条件可以将网关机接上屏幕开机测试一下，看看能不能正常启动开机看到日志。&lt;/li&gt;   &lt;li&gt;系统测试稳定之后，可以尝试用 PE 将 ISO 镜像写入到系统内置磁盘里，这样就可以不插 U 盘启动了，不过这样后面更新会稍微麻烦点。&lt;/li&gt;&lt;/ul&gt;  &lt;h3&gt;Docker 机&lt;/h3&gt;  &lt;p&gt;首先搭建好 Docker 环境，这里根据不同的设备和系统会有不同的方法，请根据网络上的教程自行操作。&lt;/p&gt;  &lt;p&gt;创建目录 DNS ，并且在其中创建   &lt;code&gt;docker-compose.yaml&lt;/code&gt;文件，用于配置容器。&lt;/p&gt;  &lt;p&gt;   &lt;code&gt;docker-compose.yaml&lt;/code&gt;文件内容参考如下。&lt;/p&gt;  &lt;pre&gt;   &lt;code&gt;services:
  paopaodns_china:
    image: sliamb/paopaodns:latest
    container_name: PaoPaoDNS-China
    restart: always
    volumes:
      - ./PaoPaoDNS-China:/data
    networks:
      dns:
        ipv4_address: 172.30.1.10 # IP 地址为 Docker 内网分配地址，用于内网访问
    environment:
      - TZ=Asia/Shanghai
      - UPDATE=weekly
      - DNS_SERVERNAME=PaoPaoDNS-China
      - DNSPORT=53
      - CNAUTO=no

  paopaodns _global:
    image: sliamb/paopaodns:latest
    container_name: PaoPaoDNS-Global
    restart: always
    volumes:
      - ./PaoPaoDNS-Global:/data
    networks:
      dns:
        ipu4_address: 172.30.1.20 # IP 地址为 Docker 内网分配地址，用于内网访问
    environment:
      - TZ=Asia/Shanghai
      - UPDATE=weekly
      - DNS_SERVERNAME=PaoPaoDNS-Global
      - DNSPORT=53
      - CNAUTO=yes
      - CNFALL=yes
      - CN_TRACKER=yes
      - USE_HOSTS=no
      - IPU6=no
      - SOCKS5=192.168.1.2:1080 # IP 地址为网关机的 IP 地址
      - SERVER_IP=192.168.1.3 # IP 地址为本台宿主机的 IP 地址
      - CUSTOM_FORWARD=192.168.1.2:53 # IP 地址为网关机的 IP 地址
      - AUTO_FORWARD=yes
      - AUTO_FORWARD_CHECK=yes
      - USE_MARK_DATA=yes
      - HTTP_FILE=yes
    ports:
      - &amp;quot;5304:5304/udp&amp;quot;
      - &amp;quot;5304:5304/tcp&amp;quot;
      - &amp;quot;7889:7889/tcp&amp;quot;

  adguard_home:
    image: adguard/adguardhome:latest
    container_name: AdGuardHome
    restart: always
    depends_on:
    - paopaodns_china
    - paopaodns_global
    volumes:
    - ./AdGuardHome:/opt/adguardhome/work
    - ./AdGuardHome:/opt/adguardhome/conf
    networks:
      dns:
        ipv4_address: 172.30.1.2 # IP 地址为 Docker 内网分配地址，用于内网访问
    environment:
      - TZ=Asia/Shanghai
    ports:
      - &amp;quot;53:53/udp&amp;quot;
      - &amp;quot;53:53/tcp&amp;quot;
      - &amp;quot;80:80/tcp&amp;quot; # 如果不是使用 80 端口作为网页端口则需要添加对应的端口映射
      - &amp;quot;3000:3000/tcp&amp;quot; # 安装成功后可以删除

networks:
  dns:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.30.1.0/24
          gateway: 172.30.1.1&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt;解释一下这个配置文件。&lt;/p&gt;  &lt;p&gt;这个配置文件定义了三个容器。&lt;/p&gt;  &lt;p&gt;两个 PaoPaoDNS ，用来作为 AdguardHome 的上游 DNS ，其中一个容器没有做特殊的配置，仅当做本地递归 DNS 服务器使用。而另一台则添加了分流相关的设置，用于对需要出国的设备进行 DNS 分流处理。&lt;/p&gt;  &lt;p&gt;AdguardHome ，用于提供本地 DNS 服务，给不同的客户端配置不同的上游 DNS ，以及去广告(虽然是他的本职，但是这里反而成了附赠的功能了)。&lt;/p&gt;  &lt;p&gt;注: 爱快官方之前在论坛中提到，系统更新到 3.7.12 后，DHCP 设置将支持对不同的客户端配置不同的 DNS ，所以用爱快系统的可以根据需求不使用 AdguardHome 。&lt;/p&gt;  &lt;p&gt;接下来启动容器。&lt;/p&gt;  &lt;pre&gt;   &lt;code&gt;docker compose up -d&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt;容器正常启动后，则可以使用   &lt;code&gt;本机 IP:3000&lt;/code&gt;访问 AdguardHome 的安装页面了，设置一下用户名和密码，以及 WebUI 的端口(建议 80)即可。&lt;/p&gt;  &lt;h3&gt;网络配置&lt;/h3&gt;  &lt;p&gt;因为我文章里是使用的 OpenWRT 作为路由系统，所以这里也是用 OpenWRT 来演示。&lt;/p&gt;  &lt;p&gt;启动网关机和 Docker 容器机，让他们的信息出现在你的路由器里面。&lt;/p&gt;  &lt;p&gt;首先要固定一下 IP 。&lt;/p&gt;  &lt;p&gt;打开 网络→DHCP/DNS→静态地址分配，将网关机的 IP 固定为   &lt;code&gt;192.168.1.2&lt;/code&gt;，将 Docker 机的 IP 固定为   &lt;code&gt;192.168.1.3&lt;/code&gt;。&lt;/p&gt;  &lt;p&gt;然后将 DHCP 默认的 DNS 设置为   &lt;code&gt;192.168.1.3&lt;/code&gt;(如果需要输入两个地址就都填一样的)。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719020618_1bb59a5cf2f75a5e.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719020618_1bb59a5cf2f75a5e.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;接下来要设置网内设备的 DNS 。&lt;/p&gt;  &lt;p&gt;打开 网络→接口→lan→DHCP 服务器→高级设置，在 DHCP 选项中添加。&lt;/p&gt;  &lt;pre&gt;   &lt;code&gt;6,192.168.1.3&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt;这个值就是你的 Docker 机的 IP 。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719050519_dcf9d4e16ce100ea.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719050519_dcf9d4e16ce100ea.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;然后重启一下网关机和 Docker 机，让他们可以获取到新的 IP 和 DNS 。&lt;/p&gt;  &lt;p&gt;接下来网页打开 AdguardHome 的后台   &lt;a href="http://192.168.1.3" rel="nofollow" title="http://192.168.1.3"&gt;http://192.168.1.3&lt;/a&gt;，在 DNS 设置中，将上游 DNS 设置为   &lt;code&gt;172.30.1.10&lt;/code&gt;，并且关闭缓存。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719082383_16a1523166bd1ae9.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719082383_16a1523166bd1ae9.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;这时我们可以试一下我们的 DNS 能否正常使用。&lt;/p&gt;  &lt;pre&gt;   &lt;code&gt;nslookup whoami.03k.org 192.168.1.3
服务器:  Unknown
Address:  192.168.1.3

非权威应答:
名称:    whoami.03k.org
Address:  123.234.123.234 #连接权威 DNS 服务器的 IP=你的宽带 IP&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt;返回的地址如果是你的公网 IP 网段，就说明递归 DNS 已经生效了。&lt;/p&gt;  &lt;p&gt;接下来是设置静态路由，我们回到 OpenWRT 的界面。&lt;/p&gt;  &lt;p&gt;打开 网络→路由→静态 IPv4 路由，添加一条新的静态路由，类型   &lt;code&gt;unicast&lt;/code&gt;，目标   &lt;code&gt;11.0.0.0/8&lt;/code&gt;，网关   &lt;code&gt;192.168.1.2&lt;/code&gt;。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719092071_6e583d6e5568ccf3.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719092071_6e583d6e5568ccf3.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719175972_96a852a85b5e3e8d.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719175972_96a852a85b5e3e8d.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;最后要屏蔽掉对 FakeIP 的 NAT 。&lt;/p&gt;  &lt;p&gt;打开 网络→防火墙→通信规则，添加一条新的规则，源区域为   &lt;code&gt;lan&lt;/code&gt;，目标区域为   &lt;code&gt;wan&lt;/code&gt;，目标地址为   &lt;code&gt;11.0.0.0/8&lt;/code&gt;，操作为   &lt;code&gt;丢弃&lt;/code&gt;。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719135684_6f2f75e01f73364b.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719135684_6f2f75e01f73364b.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719135961_b1a793f2fdf259c6.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719135961_b1a793f2fdf259c6.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;注:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;如果有使用一些纯靠 IP 访问的软件(例如网飞、Telegram)，还需要把他们的 IP 端也设置相同的静态路由和通信规则中，比较长这里我就不写了，有需求的可以自行添加。&lt;/p&gt;  &lt;p&gt;到这里网络路由相关内容设置完毕。&lt;/p&gt;  &lt;h3&gt;网关配置&lt;/h3&gt;  &lt;p&gt;网关配置文件在 Docker 机器的   &lt;code&gt;DNS/PaoPaoDNS-Global&lt;/code&gt;目录中的   &lt;code&gt;ppgw.ini&lt;/code&gt;。&lt;/p&gt;  &lt;pre&gt;   &lt;code&gt;#paopao-gateway

# mode=socks5|ovpn|yaml|suburl|free
# default: free
# free: 直接出站不走代理
# socks5: 使用 socks5 代理出站
# ovpn: 使用 ovpn 代理出站
# yaml: 使用 yaml 配置文件，yaml 配置文件在同目录下，文件名参考下面的 yamlfile
# suburl: 使用订阅地址，最常见的应该就是这种了
mode=suburl

# Set fakeip&amp;apos;s CIDR here
# default: fake_cidr=7.0.0.0/8
# FakeIP 的网段，如果要修改，请修改成看似是外网的空 IP 网段
fake_cidr=11.0.0.0/8

# Set your trusted DNS here
# default: dns_ip=1.0.0.1
# 这里需要和 Docker 机，也就是 DNS 的 IP 匹配
dns_ip=192.168.1.3
# default: dns_port=53
# If used with PaoPaoDNS, you can set the 5304 port
# 这是网关获取配置的端口，如果没有修改过端口映射，请使用默认值
dns_port=5304

# Clash&amp;apos;s web dashboard
# 这是网页管理面板的端口和密码
clash_web_port=&amp;quot;80&amp;quot;
clash_web_password=&amp;quot;clashpass&amp;quot;

# default：openport=no
# socks+http mixed 1080
openport=no

# default: udp_enable=no
udp_enable=no

# default:30
sleeptime=30

# socks5 mode settting
# default: socks5_ip=gatewayIP
# 这里需要填入网关 IP ，用于开启局域网内的 socks5 代理
socks5_ip=&amp;quot;192.168.1.2&amp;quot;
# default: socks5_port=&amp;quot;7890&amp;quot;
socks5_port=&amp;quot;7890&amp;quot;

# ovpn mode settting
# The ovpn file in the same directory as the ppgw.ini.
# default: ovpnfile=custom.ovpn
ovpnfile=&amp;quot;custom.ovpn&amp;quot;
ovpn_username=&amp;quot;&amp;quot;
ovpn_password=&amp;quot;&amp;quot;

# yaml mode settting
# The yaml file in the same directory as the ppgw.ini.
# default: yamlfile=custom.yaml
# 这里是 yaml 模式时，网关获取的配置文件的文件名
yamlfile=&amp;quot;custom.yaml&amp;quot;

# suburl mode settting
# 这里填入你的订阅地址
suburl=&amp;quot;https://...&amp;quot;
# 这里是订阅自动更新时间
subtime=1d

# fast_node=check/yes/no
# check: 代表会自动检查下面的 URL 能否访问，如果不能访问则自动重启服务并重新拉取订阅
# yes: 代表会自动根据延迟切换到延迟最低的节点，同时具有 check 的功能
# no: 代表不检查延迟与连通性
fast_node=yes
test_node_url=&amp;quot;https://www.youtube.com/generate_204&amp;quot;
ext_node=&amp;quot;Traffic|Expire| GB|Days|Date&amp;quot;
cpudelay=&amp;quot;3000&amp;quot;

# dns burn setting
# depend on fast_node=yes &amp;amp; mode=suburl/yaml
dns_burn=no
# If used with PaoPaoDNS, you can set the PaoPaoDNS:53
# 这里需要设置成 DNS 的 IP
ex_dns=&amp;quot;192.168.1.3:53&amp;quot;

# Network traffic records
net_rec=no
max_rec=5000&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt;更详细的参数解释，以及自定义规则等等，请参考   &lt;a href="https://github.com/kkkgo/PaoPaoGateWay#ppgwini%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E" rel="nofollow"&gt;官方的文档&lt;/a&gt;，如果没有特殊需求，按本文的配置即可。&lt;/p&gt;  &lt;h3&gt;配置设备 DNS&lt;/h3&gt;  &lt;p&gt;我的教程中的方案，是建立在网内只有一部分设备出国，另一部分正常用网的场景，所以需要针对不同的设备，设置不同的上游 DNS 服务器。&lt;/p&gt;  &lt;p&gt;如果你没有这种需求，可以直接在网络配置那一步中，将上游 DNS 设置为   &lt;code&gt;172.30.1.20&lt;/code&gt;，就不用继续往下看了。&lt;/p&gt;  &lt;p&gt;如果你也像我一样，只需要部分的设备走出国规则，那就还需要在多一步设置。&lt;/p&gt;  &lt;p&gt;打开 AdguardHome 的后台   &lt;a href="http://192.168.1.3" rel="nofollow" title="http://192.168.1.3"&gt;http://192.168.1.3&lt;/a&gt;。&lt;/p&gt;  &lt;p&gt;打开客户端设置，添加客户端。&lt;/p&gt;  &lt;p&gt;添加需要出国的设备的 IP 或者 IP 段，然后在下面的自定义上游的地方，将上游 DNS 设置为   &lt;code&gt;172.30.1.20&lt;/code&gt;，然后保存即可。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719181210_2f4c713455403fc7.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719181210_2f4c713455403fc7.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;至此系统全部搭建完毕。&lt;/p&gt;  &lt;h2&gt;测试&lt;/h2&gt;  &lt;p&gt;可以使用 Speedtest ，分别选择国内和国外的测速节点，看一下带宽能否跑满。&lt;/p&gt;  &lt;p&gt;可以在   &lt;a href="https://ip111.cn" rel="nofollow" title="https://ip111.cn"&gt;https://ip111.cn&lt;/a&gt;或者   &lt;a href="https://ip.skk.moe" rel="nofollow" title="https://ip.skk.moe"&gt;https://ip.skk.moe&lt;/a&gt;检查一下 IP 分流是否正常。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719210259_aac670543d7d5533.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719210259_aac670543d7d5533.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719210965_2772b3be94a07bb8.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719210965_2772b3be94a07bb8.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;可以用 NatTypeTester 检查一下 Nat 等级。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://yojigen.tech/wp-content/uploads/2024091719214622_af3abad9fd9dabd4.webp" rel="nofollow"&gt;    &lt;img alt="" src="https://yojigen.tech/wp-content/uploads/2024091719214622_af3abad9fd9dabd4.webp"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h2&gt;总结&lt;/h2&gt;  &lt;p&gt;整套设备花费是 59+28+50=137 元，这里是没有计算 U 盘和交换机的价格。&lt;/p&gt;  &lt;p&gt;U 盘作为一个搞机佬，我相信各位家里一定会有的，而交换机要看自己网内具体有多少需要网线的设备，所以我就没有算在内。&lt;/p&gt;  &lt;p&gt;这里面路由器的价格可能会有一些上下波动，比如你需要一款可以跑满千兆的路由器，又不想刷机，所以可能买了我推荐的爱快 Q3000 ，那价格就一下多了 100 元了，但是你买了更好的路由器就算不玩这套系统，那也可以让网络体验变好，也是不亏。而如果你家的网络没有达到千兆，比如只有 500M 甚至 100M ，那你大可买一些 mt7621 的路由器，刷个 OP 或者爱快的固件，这种路由器咸鱼 50 以内可以随便买。&lt;/p&gt;  &lt;p&gt;希望这篇文章可以帮助到一直想要一套舒适的网络的你。&lt;/p&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>geek</category>
      <guid isPermaLink="true">https://itindex.net/detail/62939-%E4%BD%93%E9%AA%8C-%E5%AE%B6%E5%BA%AD-%E7%BD%91%E7%BB%9C</guid>
      <pubDate>Wed, 18 Sep 2024 00:00:00 CST</pubDate>
    </item>
    <item>
      <title>数据中心网络高可用技术之从交换机到交换机：MLAG, 堆叠技术</title>
      <link>https://itindex.net/detail/62923-%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%BF%83-%E7%BD%91%E7%BB%9C-%E6%8A%80%E6%9C%AF</link>
      <description>&lt;p&gt;在  &lt;a href="https://www.kawabangga.com/?p=6509"&gt;上一篇文章结束对链路聚合的讨论&lt;/a&gt;之后，我们发现一个问题——我们只能用多条线连接到同一个 switch 上面，这样万一这个交换机挂了，连接这个这个交换机的机器（通常是一个 Rack）就一起消失了。&lt;/p&gt;



 &lt;h2&gt;MLAG 技术&lt;/h2&gt;



 &lt;p&gt;MLAG(Multi-Chassis Link Aggregation) 可以提供跨设备的链路聚合功能。&lt;/p&gt;


 &lt;div&gt;
  &lt;a href="https://www.kawabangga.com/wp-content/uploads/2024/08/cisco-modular-switch.jpeg"&gt;   &lt;img alt="" height="289" src="https://www.kawabangga.com/wp-content/uploads/2024/08/cisco-modular-switch.jpeg" width="605"&gt;&lt;/img&gt;&lt;/a&gt;思科模块化交换机&lt;/div&gt;


 &lt;p&gt;Multi-Chassis 这个词很有意思，为什么叫做 Chassis （机箱）而不叫座 Multi-Switch LAG 呢？因为这个功能不仅仅是运行在 Switch 上，还记得在  &lt;a href="https://www.kawabangga.com/posts/6295"&gt;理解网络的分层模型&lt;/a&gt;中说的吗？二层和三层设备的界限已经越来越模糊了，三层设备也可以有这个功能。&lt;/p&gt;



 &lt;p&gt;现在的网络设备都是模块化的，一个机箱上面可以根据自己的需求插不同的线卡，卡上面甚至还能装不同的模块，满足不同的需求。机箱可以认为是网络设备单元，以「机箱」来说，意思就是运行于不同网络设备之间的功能。&lt;/p&gt;



 &lt;p&gt;  &lt;em&gt;MLAG 是一个设备的 feature，而不是协议，所以在不同厂商的产品中，MLAG，Peer Link 等术语会有所不同。&lt;/em&gt;&lt;/p&gt;


 &lt;div&gt;
  &lt;a href="https://www.kawabangga.com/wp-content/uploads/2024/08/mlag.png"&gt;   &lt;img alt="" height="306" src="https://www.kawabangga.com/wp-content/uploads/2024/08/mlag.png" width="424"&gt;&lt;/img&gt;&lt;/a&gt;多交换机 MLAG&lt;/div&gt;


 &lt;p&gt;对于客户端 Linux 来说，不知道对端是两个设备，在 Linux 的视角下，自己的多条线路连接的就是同一个设备。&lt;/p&gt;



 &lt;p&gt;在交换机侧，就需要跨设备完成 LACP 信息的同步，两个交换机设备之间需要协调好，A 的 3号端口 和 B 的 3号端口是同一个链路聚合组(LAG)。所以两个交换机之间需要一条线，来沟通控制面的信息。这条线就叫做 Peer Link。在 Peer Link 上如何传输控制信息，取决于不同厂商对于 MLAG 的实现。某些厂商的设备使用   &lt;a href="https://en.wikipedia.org/wiki/IEC_60870-6"&gt;ICCP&lt;/a&gt; (Inter-Control Center Communications Protocol) 来进行不同的机箱之间的连接。&lt;/p&gt;



 &lt;p&gt;这样，就可以完成从服务器到交换机的高可用了，服务器网卡、网线、交换机接口、交换机系统、交换机整机，任意一个地方出现问题，都有冗余路线，不会对服务造成太大影响。&lt;/p&gt;



 &lt;p&gt;数据中心广泛使用的就是 MLAG。&lt;/p&gt;



 &lt;h2&gt;堆叠技术&lt;/h2&gt;



 &lt;p&gt;在交换机之间的高可用，还有一种技术，就是交换机堆叠。这个功能在不同的厂商里也是不同的名字，比如华为的 istack，思科的 StackWise.&lt;/p&gt;



 &lt;p&gt;简单来说，这个功能可以让多个交换机虚拟成一个。只有一个主操作系统在运行，其他的交换机就像主交换机扩展出来的板卡一样。堆叠之后只有一个管理 IP 和 MAC 地址，只需要登录一个系统进行配置操作。&lt;/p&gt;



 &lt;a href="https://www.kawabangga.com/wp-content/uploads/2024/08/ip-mac-stacking-switch.png"&gt;  &lt;img alt="" height="430" src="https://www.kawabangga.com/wp-content/uploads/2024/08/ip-mac-stacking-switch-1024x430.png" width="1024"&gt;&lt;/img&gt;&lt;/a&gt;4个交换机完成堆叠之后，相当于一个交换机有了 4 倍的端口



 &lt;p&gt;堆叠之后逻辑上就是一个交换机，所以服务器可以直接连接到多个物理交换机，从逻辑上看，交换机侧也是同一个了。&lt;/p&gt;



 &lt;a href="https://www.kawabangga.com/wp-content/uploads/2024/08/switch-stacking.png"&gt;  &lt;img alt="" height="629" src="https://www.kawabangga.com/wp-content/uploads/2024/08/switch-stacking-1024x629.png" width="1024"&gt;&lt;/img&gt;&lt;/a&gt;交换机堆叠连接服务器



 &lt;p&gt;堆叠也能实现故障快速切换，在正常情况下也能充分利用线路的带宽，配置简单。但是和 MLAG 相比，稳定性上来说 MLAG 更高，因为堆叠交换机只有一个控制面，如果主交换机出现故障，比如堆叠失效，整个堆叠集群都会出错。MLAG 的故障域更小，交换机坏也就坏一台。这也带来很多维护便利，从升级维护上说，MLAG 可以让我们一台一台地操作交换机升级而不影响服务，堆叠就会更加麻烦一些。从部署上，MLAG 不受距离显示，堆叠的话，两个交换机距离越远，出错的概率越大。&lt;/p&gt;



 &lt;p&gt;  &lt;em&gt;说起来，思科还有一个    &lt;a href="https://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus7000/sw/vdc/config/cisco_nexus7000_vdc_config_guide_8x/overview.html"&gt;VDC 技术&lt;/a&gt;(Virtual Device Context), 支持把一个设备虚拟成多个。这些技术又是把一个物理设备拆成多个又是把多个合成一个的，可真有意思。&lt;/em&gt;&lt;/p&gt;



 &lt;p&gt;这个系列的二层技术介绍的差不多了，我们下一篇就开始聊三层技术。&lt;/p&gt;



 &lt;p&gt;Until next time!&lt;/p&gt;



 &lt;h2&gt;数据中心网络高可用技术系列&lt;/h2&gt;



 &lt;ol&gt;
  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6417"&gt;数据中心网络高可用技术：序&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6430"&gt;数据中心网络高可用技术之从服务器到交换机：active-backup&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6485"&gt;数据中心网络高可用技术之从服务器到交换机：balance-tlb 和 balance-alb&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6460"&gt;数据中心网络高可用技术之从服务器到交换机：链路聚合 (balance-xor, balance-rr, broadcast)&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6509"&gt;数据中心网络高可用技术之从服务器到交换机：802.3 ad&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6537"&gt;数据中心网络高可用技术之从交换机到交换机：MLAG, 堆叠技术&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6594"&gt;数据中心网络高可用技术之从服务器到网关：VRRP&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>网络 ICCP (Inter-Control Center Communications Protocol) MLAG (Multi-Chassis Link Aggregation) Peer Link VDC (Virtual Device Context)</category>
      <guid isPermaLink="true">https://itindex.net/detail/62923-%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%BF%83-%E7%BD%91%E7%BB%9C-%E6%8A%80%E6%9C%AF</guid>
      <pubDate>Thu, 08 Aug 2024 10:04:25 CST</pubDate>
    </item>
    <item>
      <title>从输入URL到页面展示过程：深入解析网络请求与渲染</title>
      <link>https://itindex.net/detail/62838-url-%E9%A1%B5%E9%9D%A2-%E5%B1%95%E7%A4%BA</link>
      <description>&lt;h1&gt;推荐阅读&lt;/h1&gt;
 &lt;h1&gt;  &lt;a href="https://cloud.tencent.com/developer/article/2304343"&gt;项目实战:AI文本 OCR识别最佳实践&lt;/a&gt;&lt;/h1&gt;
 &lt;h1&gt;  &lt;a href="https://gamma.app/signup?r=sqgovd3iif5btr4"&gt;AI Gamma一键生成PPT工具直达链接&lt;/a&gt;&lt;/h1&gt;
 &lt;h1&gt;  &lt;a href="https://cloud.tencent.com/developer/article/2272077?areaSource=&amp;traceId="&gt;玩转cloud Studio 在线编码神器&lt;/a&gt;&lt;/h1&gt;
 &lt;h1&gt;  &lt;a href="https://cloud.tencent.com/developer/article/2291530?shareByChannel=link"&gt;玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间&lt;/a&gt;&lt;/h1&gt;
 &lt;h1&gt;资源分享&lt;/h1&gt;
 &lt;h1&gt;  &lt;a href="https://zkk-1300025204.cos.ap-nanjing.myqcloud.com/%E5%8F%B2%E4%B8%8A%E6%9C%80%E5%85%A8StableDiffusion%E8%B5%84%E6%96%99%E5%8C%85.csv"&gt;史上最全文档AI绘画stablediffusion资料分享&lt;/a&gt;&lt;/h1&gt;
 &lt;h1&gt;  &lt;a href="https://yv4kfv1n3j.feishu.cn/docx/MRyxdaqz8ow5RjxyL1ucrvOYnnH"&gt;AI绘画关于SD,MJ,GPT,SDXL百科全书&lt;/a&gt;&lt;/h1&gt;
 &lt;h1&gt;  &lt;a href="https://blog.csdn.net/weixin_42373241/article/details/132341577?spm=1001.2014.3001.5501"&gt;AI绘画 stable diffusion Midjourney 官方GPT文档 AIGC百科全书资料收集&lt;/a&gt;&lt;/h1&gt;
 &lt;pre&gt;  &lt;code&gt;「java、python面试题」来自UC网盘app分享，打开手机app，额外获得1T空间
https://drive.uc.cn/s/2aeb6c2dcedd4
AIGC资料包
https://drive.uc.cn/s/6077fc42116d4
https://pan.xunlei.com/s/VN_qC7kwpKFgKLto4KgP4Do_A1?pwd=7kbv#
&lt;/code&gt;&lt;/pre&gt;
 &lt;h2&gt;引言&lt;/h2&gt;
 &lt;p&gt;在当今互联网时代，我们每天都会通过浏览器访问各种网页。但是，你是否曾经思考过在我们输入一个URL后，浏览器是如何加载并显示页面的呢？这背后涉及到一系列复杂的技术和过程。本文将带领大家深入了解从输入URL到页面展示的过程，并给出相应的代码示例，让我们一起探索这个神奇而又复杂的世界。&lt;/p&gt;
 &lt;h2&gt;1. 网络请求的发起&lt;/h2&gt;
 &lt;p&gt;通过浏览器输入URL后，浏览器会根据协议类型（如HTTP或HTTPS）向服务器发起请求。这个过程可以通过下面的代码示例来体现：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;const url = &amp;quot;https://example.com&amp;quot;;
fetch(url)
  .then(response =&amp;gt; response.text())
  .then(data =&amp;gt; {
    console.log(data);
  })
  .catch(error =&amp;gt; {
    console.error(error);
  });
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;在代码中，我们使用了JavaScript的fetch API来发起网络请求，并将服务器响应转换为文本输出到控制台。&lt;/p&gt;
 &lt;h2&gt;2. DNS解析&lt;/h2&gt;
 &lt;p&gt;在发送网络请求前，浏览器首先需要将URL中的域名解析成对应的IP地址。这个过程称为DNS解析。下面是一个简化版的DNS解析示例代码：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;const dns = require(&amp;apos;dns&amp;apos;);

const domain = &amp;quot;example.com&amp;quot;;
dns.resolve(domain, &amp;apos;A&amp;apos;, (err, addresses) =&amp;gt; {
  if (err) {
    console.error(err);
    return;
  }
  console.log(addresses);
});
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;上述代码中，我们使用Node.js的  &lt;code&gt;dns&lt;/code&gt;模块来进行DNS解析，并输出解析得到的IP地址。&lt;/p&gt;
 &lt;h2&gt;3. 建立TCP连接&lt;/h2&gt;
 &lt;p&gt;经过DNS解析后，浏览器会尝试与服务器建立TCP连接。这个过程涉及到三次握手，确保数据能够安全可靠地传输。以下是一个简化的TCP连接代码示例：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;const net = require(&amp;apos;net&amp;apos;);

const serverIP = &amp;apos;192.168.0.1&amp;apos;;
const port = 80;

const client = new net.Socket();
client.connect(port, serverIP, () =&amp;gt; {
  console.log(&amp;apos;TCP connection established&amp;apos;);
});
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;在上述代码中，我们使用Node.js的  &lt;code&gt;net&lt;/code&gt;模块创建了一个TCP socket，并通过  &lt;code&gt;connect&lt;/code&gt;方法与服务器建立连接。&lt;/p&gt;
 &lt;h2&gt;4. 发送HTTP请求&lt;/h2&gt;
 &lt;p&gt;TCP连接建立后，浏览器会构建HTTP请求并发送给服务器。以下是一个简化的HTTP请求发送代码示例：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;const http = require(&amp;apos;http&amp;apos;);

const options = {
  hostname: &amp;apos;example.com&amp;apos;,
  port: 80,
  path: &amp;apos;/&amp;apos;,
  method: &amp;apos;GET&amp;apos;
};

const req = http.request(options, res =&amp;gt; {
  console.log(`HTTP response status code: ${res.statusCode}`);
});

req.end();
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;在上述代码中，我们使用Node.js的  &lt;code&gt;http&lt;/code&gt;模块创建了一个HTTP请求，并通过  &lt;code&gt;request&lt;/code&gt;方法发送给服务器。&lt;/p&gt;
 &lt;h2&gt;5. 服务器处理请求&lt;/h2&gt;
 &lt;p&gt;服务器收到浏览器发送的HTTP请求后，会根据请求的内容进行相应的处理。这个过程通常包括路由解析、数据查询等操作。下面是一个简化的服务器处理请求的代码示例：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;const http = require(&amp;apos;http&amp;apos;);

const server = http.createServer((req, res) =&amp;gt; {

  if (req.url === &amp;apos;/&amp;apos;) {

res.writeHead(200, { &amp;apos;Content-Type&amp;apos;: &amp;apos;text/plain&amp;apos; });

res.end(&amp;apos;Hello, World!&amp;apos;);

  } else if (req.url === &amp;apos;/about&amp;apos;) {

res.writeHead
(200, { &amp;apos;Content-Type&amp;apos;: &amp;apos;text/html&amp;apos; });
    res.end(&amp;apos;&amp;lt;h1&amp;gt;About Page&amp;lt;/h1&amp;gt;&amp;apos;);
  } else {
    res.writeHead(404, { &amp;apos;Content-Type&amp;apos;: &amp;apos;text/plain&amp;apos; });
    res.end(&amp;apos;Page not found&amp;apos;);
  }
});

server.listen(80, () =&amp;gt; {
  console.log(&amp;apos;Server running at http://localhost:80/&amp;apos;);
});
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;在上述代码中，我们使用Node.js的  &lt;code&gt;http&lt;/code&gt;模块创建了一个简单的HTTP服务器。根据请求的URL路径，服务器会返回不同的响应内容。&lt;/p&gt;
 &lt;h2&gt;6. 接收响应数据&lt;/h2&gt;
 &lt;p&gt;当服务器处理完请求并生成响应后，浏览器会接收到响应数据。这个过程在浏览器内部进行，我们无法直接访问其代码。浏览器会将响应数据存储在缓存中，并准备进行后续的解析和渲染。&lt;/p&gt;
 &lt;h2&gt;7. 解析HTML&lt;/h2&gt;
 &lt;p&gt;浏览器接收到响应数据后，会对HTML进行解析，构建出一棵DOM树。这个过程包括识别HTML标签、属性、文本等，并将其转换为可以操作的数据结构。以下是一个简化的HTML解析代码示例：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;const parser = new DOMParser();
const htmlString = &amp;apos;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Hello, World!&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;apos;;
const doc = parser.parseFromString(htmlString, &amp;apos;text/html&amp;apos;);

console.log(doc.title); // Output: &amp;quot;Hello, World!&amp;quot;
console.log(doc.body.innerHTML); // Output: &amp;quot;&amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;在上述代码中，我们使用JavaScript的DOMParser来解析HTML字符串，并通过操作解析后的DOM树来获取需要的信息。&lt;/p&gt;
 &lt;h2&gt;8. 构建DOM树&lt;/h2&gt;
 &lt;p&gt;浏览器在解析HTML后，会根据标签之间的层次关系构建一棵DOM树。每个HTML元素都会被转换为DOM节点，并按照其在HTML中的嵌套关系形成父子节点的层次结构。以下是一个简化的DOM树构建示例：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;const htmlString = &amp;apos;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Hello, World!&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;apos;;
const doc = new DOMParser().parseFromString(htmlString, &amp;apos;text/html&amp;apos;);

console.log(doc.documentElement); // Output: HTML元素节点
console.log(doc.documentElement.childNodes.length); // Output: 2，包含&amp;lt;head&amp;gt;和&amp;lt;body&amp;gt;
console.log(doc.documentElement.childNodes[1].childNodes[0]); // Output: &amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;在上述代码中，我们使用DOMParser来解析HTML字符串，并通过访问  &lt;code&gt;documentElement&lt;/code&gt;和  &lt;code&gt;childNodes&lt;/code&gt;属性来获取DOM树的节点信息。&lt;/p&gt;
 &lt;h2&gt;9. 渲染页面&lt;/h2&gt;
 &lt;p&gt;经过DOM树的构建后，浏览器会根据DOM树的结构和样式信息对页面进行渲染。这个过程包括布局计算、绘制元素、加载外部资源等操作，最终将页面显示给用户。由于浏览器的渲染过程非常复杂，我们无法直接操作其渲染引擎。但是，我们可以通过调试工具来观察页面的渲染情况。&lt;/p&gt;
 &lt;h2&gt;10. 用户交互与动态效果&lt;/h2&gt;
 &lt;p&gt;在页面渲染完成后，用户可以与页面进行交互，并享受丰富的动态效果。这包括点击链接、提交表单、触发事件等操作。JavaScript在此起到了重要的作用，它可以监听用户的操作并相应地更新页面内容或执行相应的逻辑。&lt;/p&gt;
 &lt;h2&gt;11. 性能优化&lt;/h2&gt;
 &lt;p&gt;为了提供更好的用户体验，我们需要关注性能优化。这包括减少网络请求次数、压缩资源文件、使用缓存等策略。同时，优化JavaScript和CSS的编写方式也可以提升页面的加载速度和响应性能。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62838-url-%E9%A1%B5%E9%9D%A2-%E5%B1%95%E7%A4%BA</guid>
      <pubDate>Thu, 31 Aug 2023 09:33:35 CST</pubDate>
    </item>
    <item>
      <title>2022 全球网络黑产常用攻击方法 Top 10</title>
      <link>https://itindex.net/detail/62571-%E5%85%A8%E7%90%83-%E7%BD%91%E7%BB%9C-%E6%94%BB%E5%87%BB</link>
      <description>&lt;div&gt;近几年，借助互联网产业发展的东风，网络黑产也迎来更加巅峰的状态，不论是从攻击效率，组织规模，亦或是收益变现能力，都在一天天变的成熟完善。根据艾瑞咨询 2020 年发布的《现代网络诈骗分析报告》，全国黑产从业者已经超过 40 万人，依托其从事网络诈骗的人数至少有 160 万人，“年产值”在 1000 亿元以上。  &lt;br /&gt;毫不夸张的讲，网络黑产从早期的小打小闹，发展成如今的多行业、多场景、多任务的全社会广泛渗透。在巨额经济利益的驱动下，黑灰产从业者游走在法律监管的边缘地带，利用各种网络犯罪技术与工具，逐渐形成一条分工明确、合作紧密的黑灰产业链条，并且以一种难以遏制的速度，成长起来。  &lt;br /&gt;简单来说，当下网络黑产产业链可分为上中下三个层级：上游黑产主要提供“武器弹药”，收集各种信息资源，并为中游提供工具和平台；中游黑产则是针对网络系统和计算机进行直接破坏、入侵，以各种各样的方式实施资源窃取的行为；下游则相当于是“销赃”，可将黑产转化为现金收益，例如利用中上游提供的信息实施诈骗、洗钱等。  &lt;br /&gt;  &lt;img height="389" width="658"&gt;&lt;/img&gt;  &lt;br /&gt;网络黑产的快速膨胀以及对全社会的巨大危害，让全球警方深恶痛绝，各国开始制定各种政策、法规，持续打击网络黑产产业的发展。但是，它就像是融入了互联网的血液之中，在多重打击之下反而愈演愈烈，有的国家甚至已经成为网络黑产的温床。  &lt;br /&gt;同时，网络黑产的手段也越来越高明，有的是利用各种黑客技术，而有的则是深谙人性的阴暗面，以各种手法诱惑他人上当受骗，DDoS 攻击、网络赌博、网络招嫖、制作木马程序、内网渗透攻击等攻击手法。  &lt;br /&gt;本文列举当下最流行的网络黑产常用攻击方法，总结了 2022 全球网络黑产常用攻击方法 Top 10，带你更深刻认识网络黑产。  &lt;h2&gt;   &lt;strong&gt;    &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;深度伪造&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;深度伪造技术是一种基于人工智能的音频、视频和图像合成技术，通过将图片、音频或视频合并叠加到源图片、音频或视频上，借助神经网络技术进行样本学习，将个人声音、面部表情及身体动作拼接合成虚假内容。   &lt;br /&gt;&lt;/h2&gt;  &lt;br /&gt;  &lt;img height="346" width="615"&gt;&lt;/img&gt;  &lt;br /&gt;深度伪造最常见的方式主要包括 AI 换脸技术，语音模拟、人脸合成、视频生成等，技术人员通过样本学习，逼真模仿出原人物的面部表情、肢体语言。深度伪造技术民用化最早追溯到 2017 年，当时美国一个网友发布一款名为“深度伪造”的软件，两年后，我国出现了一款“ZAO”换脸社交软件，一时风靡。  &lt;br /&gt;深度伪造技术不断演进，几乎可以达到以假乱真的地步，民众仅通过肉眼无法辨别真伪，使得篡改或生成高度逼真且难以甄别的音视频内容成为可能，带来一系列安全问题，部分不法分子利用该技术恶意拼接色情视频，进行勒索活动，产生极其恶劣的社会影响。  &lt;br /&gt;或许，人脸、声音、视频替换将成为网络黑产下一个阶段的重点发展方向，黑客将使用这项技术进行恐吓诈骗，网络欺诈。不仅如此，生产变脸和变声工具、提供虚假语音和视频合成服务也会成为网络黑色产业链中一个新的环节。  &lt;h2&gt;   &lt;strong&gt;    &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;探针盒子&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;2019 年央视 3·15 晚会期间，“探针盒子”第一次走进民众视线，当天记者曝光一种 WiFi 探针盒子，当用户手机处于 wifi 打开情况时，探针盒子发现信号后，会识别出手机的 MAC 地址，然后在根据 MAC 地址转换成 IMEI，之后再转换成用户手机号码。   &lt;br /&gt;&lt;/h2&gt;  &lt;br /&gt;  &lt;img height="257" width="641"&gt;&lt;/img&gt;  &lt;br /&gt;直白讲，探针盒子就是一种 Wi-Fi 路由器，当用户手机连接“探针盒子”发出的 Wi-Fi 网络信号时，探针盒子会自动获得手机 MAC 地址，随后便将其上传至非法云端数据库进行匹配，在自动进行 MAC 地址、IMEI 串号、手机号之间的匹配关联，返回一系列的数据，其中有机主的号码、应用软件的下载和使用情况和相关浏览数据等。  &lt;br /&gt;日常生活中，许多商场、酒店、餐厅、咖啡厅、健身设施等场地都会突然弹出免费 WiFi 蹭网提示，这些如果是非法分子布置的探针盒子，一旦用户连接，便会悄无声息盗取手机号码，后续可以用于“精准营销”。  &lt;br /&gt;目前，网上仍有许多售卖 WiFi 探针盒子设备的网店，并表示帮助对接到代理商平台，导出探针盒子附近采集到的手机数字信息。我国法律规定，利用探针盒子获取他人手机号等隐私信息的行为，涉嫌侵犯他人隐私，严重情况下可能面临民事侵权责任及治安管理处罚责任。  &lt;h2&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;窃取指纹面容声音等生物信息的方式&lt;/strong&gt;&lt;/h2&gt;目前，生物识别信息已应用到社会各环节，生物识别信息技术利用开始逐渐平民化，极大提升了用户使用体验，但网络犯罪分子也开始盯上了这块“香饽饽”。  &lt;br /&gt;  &lt;br /&gt;  &lt;img height="336" width="636"&gt;&lt;/img&gt;  &lt;br /&gt;相较于其它民众个人信息，生物识别信息是物联网时代背景下，将民众指纹、人脸、声音、基因、虹膜等个人特征，进行数字化处理后的信息，具有不可替代性。因此，生物特征信息无可争议属于民众个人信息中最敏感的部分。  &lt;br /&gt;但近几年民众生物识别信息屡遭侵害，网络犯罪份子通过 AI 合成技术伪造人脸、声音、指纹，或者在未告知情况下，偷拍、收集民众人脸信息、指纹，进行非法行为，侵犯民众个人生命财产安全。  &lt;br /&gt;目前，生物识别信息技术广泛应用于支付、日常通行、通信等几个方面，违法收集、盗取转移、贩卖民众生物识别信息构成了上下游产业链。生物识别信息如此重要，相关机构势必要对实行人脸识别、录入的单位及相关人员严格限制，应当对拥有类似虹膜、指纹、刷脸等一些生物特征识别技术的企业进行规范监管。  &lt;br /&gt;政府部门已经在加快推进个人信息保护立法，近些年，网信办、工信部、信息安全标准化技术委员会等部门接连发布文件，对生物识别信息实行规范性管理。  &lt;h2&gt;   &lt;strong&gt;    &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;撞库攻击&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;此前，网络犯罪分子获取受害者账号信息主要通过感染系统后，横向移动破解，效率低、步骤繁琐，而且仅能获得单一账号详细信息，“撞库” 出现很好解决了这些问题，成为黑客盗号的重要手段。&lt;/h2&gt;  &lt;h2&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;img height="343" width="586"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;br /&gt;对于普通民众而言，“撞库”无疑是一个专业名词。通俗讲，撞库是网络犯罪分子通过收集互联网已泄露的用户信息，生成对应字典表，尝试批量登陆其它网站后，便可以得获取一系列用户账号信息。许多用户在不同网站设置相同账号密码，可以利用获取的字典表随机登录任意网站，这个过程就可以简单理解为撞库攻击。  &lt;h3&gt;   &lt;br /&gt;&lt;/h3&gt;  &lt;h3&gt;   &lt;strong&gt;常见的撞库场景主要有以下两种：&lt;/strong&gt;&lt;/h3&gt;  &lt;strong&gt;   &lt;br /&gt;&lt;/strong&gt;  &lt;strong&gt;弱密码嗅探：&lt;/strong&gt;类似 111111、123456 这样的简单密码因为很多人用，用这样的弱口令去试探大量的账号，就有一定概率能发现一些真正在使用弱密码的账号。  &lt;strong&gt;   &lt;br /&gt;&lt;/strong&gt;  &lt;strong&gt;利用拖库数据：&lt;/strong&gt;这是攻击成功率更高的一种方式，原理是大多数人倾向于在多个站点上使用同一个密码。当攻击者成功入侵一个安全防护能力很弱的站点 A，并拿到其数据库的所有用户名密码组合，然后再拿着这些组合去站点 B 尝试，如果你两个站点都注册过并且使用了同样的密码……撞库就成功了。  &lt;h2&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;钓鱼网站&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;钓鱼网站一般指诱骗用户填写信息的虚假网站，毋庸置疑是安全人最熟悉的黑产模式。钓鱼网站何以坚挺十几年？离不开其诈骗网页与真实网站界面别无二致，很难区分，一旦潜在受害者进入界面，所提交的账号和密码等敏感信息便会立刻被黑客抓取。   &lt;br /&gt;&lt;/h2&gt;  &lt;br /&gt;  &lt;img height="455" width="653"&gt;&lt;/img&gt;  &lt;br /&gt;钓鱼网站作为网络黑产“钉子户”，虽难以彻底拔除，但也早已被安全人员研究透彻。通常情况下，网络犯罪分子会分发伪装成受害者企业内部邮箱或者某些权威性网站。这些邮箱或网站地址具有极高相似度，最大的区别在于其有且仅有几个页面，甚至只有一个页面 。  &lt;br /&gt;常见钓鱼方式主要包括“鱼叉攻击”、“商业邮件欺诈”、“灯笼式钓鱼”、“克隆钓鱼”、“域名欺骗”、“短信钓鱼”、“语音钓鱼”、“域欺骗”、“水坑攻击”等方式，攻击者利用上述方式进行非法信息收集，潜在受害者往往会泄露个人信息，如姓名、电话、家庭住址、身份 ID，甚至信用卡号、账户用户名和密码等内容也会被攻击者获取。  &lt;br /&gt;钓鱼网站最早案例可能要追溯到美国，几十年前，美国互联网产业发展迎来高峰期，无数网络犯罪分子企图通过钓鱼网站，攫取经济利益。随着全球互联网产业融合发展，亚非拉等区域计算机产业井喷，钓鱼网站攻击开始蔓延全球。钓鱼网站难以彻底拔除，根源在于即使大多数民众很清楚钓鱼网站的套路，但还是难以抵挡各种诱惑。钓鱼网站运营者熟练运用社会从工程学，抓住人类贪婪、恐惧、羡慕、虚荣、善良等各种情绪，付出极小代价便可获得受害者“秘密信息”。  &lt;h2&gt;   &lt;strong&gt;    &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;色情网站&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;互联网江湖五花八门，黑客组织各显神通，色情网站自然占据一席之地，迫于法律法规，当下多采用地下模式存活。当用户偷偷摸摸访问这些网站时，自以为无人知悉、天衣无缝，殊不知获取视频数据过程中，网站内部嵌入程序已经在偷偷抓取用户手机信息，悄无声息窃取手机号码，浏览器记录、IP 地址，甚至相册、通讯录等机密信息也难逃一劫。&lt;/h2&gt;  &lt;h2&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;img height="392" width="637"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;br /&gt;不止如此，某些色情 APP 还会雇佣黑客组织，利用境外服务器群发附有病毒的链接，一旦点击，木马病毒便会植入手机，横向获取银行卡信息、真实姓名、通讯录等敏感信息。更可怕的是，黑客还通过用户通讯录，群发所有好友。  &lt;br /&gt;部分色情网站窃取信息是征求用户同意后的行为。当用户打开一个视频，准备“欣赏”，突然弹出一个界面，需要获得存储权、相机、通讯录权限，一旦点击同意，无疑同意网站收集用户个人信息。不单技术手段，部分色情 APP 暗地里直接兜售用户个人数据，明码标价，“童叟无欺”。  &lt;br /&gt;色情网站的危害远不止于此，如何终止色情网站运行，阻断色情内容扩散，是社会以及各大网络搜索平台亟需解决的问题。  &lt;h2&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;收买内鬼&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;直接攻击获取信息的手段已经不能满足网络犯罪分子的野心了，目前，这群人也开始玩起无间道，培养内鬼。何为安全行业内鬼？潜伏在企业内部，为攻击者提供登陆凭证、漏洞情报，企业消息，资源详情的”特务人员“就是内鬼！&lt;/h2&gt;  &lt;h2&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;img height="320" width="608"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;br /&gt;有道是日防夜防家贼难防，网络犯罪分子”火力全开“使用各种攻击手段，投入大量资源，不见得能够洞穿企业安全防护体系，但只需要很小的一部分资金便可以收买内鬼，轻松突破防线，盗取、锁定企业数据。  &lt;br /&gt;网络空间中，不仅有急需内鬼的买方，卖方同样无时无刻不在兜售自己。微信群聊中，部分人员打着“公司内部信息”旗号，倒卖数据的事件在日常正并不罕见，“内鬼监守自盗，成为民众、企业数据信息流向暗网交易市场的重要渠道之一。  &lt;br /&gt;在 2020 年，公安机关办理的数据安全案件中，涉及到内鬼利用工作之便窃取、泄露公民个人信息的违法犯罪行为，查获重点行业内部涉案人员 500 余名。目前，圈内最火的黑客组织 LAPSUS$ 也是收买企业内鬼的”忠实拥趸“，为轻松突破目标企业安全防御体系， LAPSUS$ 提出一种创新型方法，针对目标企业，在论坛或者社交软件 Telegram 上，用各种语言广发“英雄贴”，蓄意丰厚报酬，试图招募目标企业员工献出其内部登录凭证。  &lt;br /&gt;”内鬼“之所以如此具有价值，归咎于企业机构中，对数据信息权限的管理不够明确，许多企业存在内部数据无分级，任何人都能查看、下载等情况。在高额金钱诱惑下，难免有小部分人员动歪心思。  &lt;h2&gt;   &lt;strong&gt;    &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;伪基站&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;伪基站顾名思义就是伪冒基站，是一种利用 GSM 单向认证漏洞的非法无线电通信设备，主要由主机和笔记本电脑组成，能够搜取以其为中心、一定半径范围内的 GSM 移动电话信息，并任意冒用他人手机号码强行向用户手机发送诈骗、推销等垃圾短信，常部署在汽车或者一个比较隐蔽区域。（伪基站产业猖狂时期，能够在街上看到某些车辆鬼鬼祟祟，围绕某片区域巡逻）。&lt;/h2&gt;  &lt;h2&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;img height="384" width="547"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;br /&gt;伪基站原理相对简单，当运营时覆盖范围内的用户信号被强制连接到该设备上，无法连接到三大运营商的网络信号，以影响手机用户正常使用，之后利用移动信令监测系统监测移动通讯过程中的各种信令过程，获得手机用户当前的位置信息。  &lt;br /&gt;伪基站启动后会立刻工作，开始屏蔽一定范围内的信号，趁着用户信号短暂中断，搜索出附近连接伪基站的手机号，随机将短信发送到这些号码上。一般而言，伪基站的作用时间持续10 秒到 20 秒，恰好允许短信推送。  &lt;br /&gt;伪基站具有隐蔽性、持久性等特点，加上往往部署在灵活性较高的汽车上，因此伪基站还具有较强流动性。目前，伪基站仍然可以通过特殊渠道购买，国家已经出台相应法规，例如《中华人民共和国刑法》第 288 条和《中华人民共和国治安处罚法》第 28 条都分别规定，擅自使用无线电台，经无线电管理部门责令停止使用后拒不停止使用的，或故意干扰无线电业务经有关部门指出后拒不采取有效措施消除的，移送司法部门处罚。  &lt;h2&gt;   &lt;strong&gt;    &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;DDoS攻击&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;DDoS 攻击，官方定义为多个攻击者同时向一个或数个目标发动攻击，或者一个攻击者控制了多个位于不同位置的机器并利用这些机器对受害者同步实施攻击。直白点，就是攻击者利用已被攻陷的电脑，在较短时间内对目标网站发起大量请求，大规模消耗目标网站的主机资源，集中火力”围殴“受害者，使其无法正常服务。   &lt;br /&gt;&lt;/h2&gt;  &lt;br /&gt;  &lt;img height="308" width="589"&gt;&lt;/img&gt;  &lt;br /&gt;DDoS 攻击表现形式主要有两种，一种为流量攻击，主要是针对网络带宽的攻击，即大量攻击包导致网络带宽被阻塞，合法网络包被虚假的攻击包淹没而无法到达主机。另一种为资源耗尽攻击，主要是针对服务器主机的攻击，即通过大量攻击包导致主机的内存被耗尽或 CPU 被内核及应用程序占完而造成无法提供网络服务。  &lt;br /&gt;当被企业系统被 DDoS 攻击时，主要表现出以下几种情况：  &lt;blockquote&gt;1. 被攻击主机上有大量等待的 TCP 连接。2. 网络中充斥着大量的无用的数据包，源地址为假。3. 制造高流量无用数据，造成网络拥塞，使受害主机无法正常和外界通讯。4. 利用受害主机提供的服务或传输协议上的缺陷，反复高速地发出特定的服务请求，使受害主机无法及时处理所有正常请求。5. 严重时会造成系统死机&lt;/blockquote&gt;  &lt;br /&gt;针对企业的 DDoS 频频发生，从《2022 上半年全球 DDoS 威胁报告》数据显示，随着企业数字化、云化，DDoS 攻击次数已连续数年高速增长，已达去年同期的 3 倍，并且攻击手段、攻击烈度也在不断进化。  &lt;br /&gt;值得一提的是，网络犯罪分子为增加非法收入，会在暗网上出售 DDoS 服务，无差别攻击企业机构，获取佣金、赎金双倍利益。更有甚者部分勒索团伙毫无职业精神，即使受害者选择支付赎金，也不会解绑系统，甚至会“转卖受害者”，进行双重勒索。  &lt;h2&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;假冒 APP&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;随着移动互联网技术快速发展，APP 已成为民众获取获取信息、娱乐交流、消费投资等各类生活需求的主要媒介。APP 大量使用便利民众同时，假冒 APP 也随之出现，成为一些网络犯罪分子攫取利益的工具。&lt;/h2&gt;  &lt;h2&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;img height="477" width="646"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/h2&gt;  &lt;br /&gt;区分正规 APP 和假冒 APP 的关键点在于用户支付时资金流向问题。正规 APP 充值方式都是集成在平台上，在 APP 上可以直接用绑定的银行卡进行充值，假冒 APP 的充值方式通常是诱导受害者通过银行卡或者支付宝、微信直接转账到对方账户。  &lt;br /&gt;从以往暴雷的事件来看，假冒 APP 并不是简单页面相仿、操作流程相似，而是经过团伙内开发人员、运维、产品等相互协作，严格分工，流程化设计，精准仿冒，量身定制假冒 APP 中各种诈骗流程，最后经下游渠道封装和分发假冒 APP。  &lt;br /&gt;各环节疏通后，假冒 APP 最终流向诈骗团伙，随后诈骗团伙根据假冒 APP 的功能特点，将其包装成极具迷惑性的“正规”应用平台，诱使潜在受害人点击链接或扫描二维码下载 APP，进而实施诈骗活动。  &lt;h2&gt;   &lt;strong&gt;    &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;   &lt;strong&gt;网络黑产发展趋势&lt;/strong&gt;&lt;/h2&gt;  &lt;h2&gt;网络黑产凭借其隐匿性、复杂性、灵活性，暗地里利用 DDos 攻击、钓鱼网站、色情网站等技术手段，谋取大量的经济利益。此外，为躲避法律监管，利益最大化，国内网络黑产组织彼此之间相互配合，形成上下游一体化“作案”，上游专门负责利用系统漏洞，盗取受害者数据信息，下游组织掌握庞大交易平台，分类数据，更为精准定位目标客户，最终实现利益最大化，俨然是一派分工明确、组织严密的“和谐景象”。   &lt;br /&gt;&lt;/h2&gt;  &lt;br /&gt;现阶段，网络黑产逐渐升级技术手段、转移运营区域、加强不同组织间协作、优化宣传方式、谋求合法身份，呈现出智能化、国际化、平台化、涉众化、产业化的发展趋势。更值得警惕的是，网络黑产早已盯上了年轻群体，青少年群体心智尚未成熟，法律意识薄弱，缺乏是非判断力，极易容易成为黑产引诱的对象。  &lt;strong&gt;   &lt;br /&gt;&lt;/strong&gt;  &lt;strong&gt;网络黑产治理，任重道远！&lt;/strong&gt;  &lt;strong&gt;   &lt;br /&gt;&lt;/strong&gt;  &lt;p&gt;精彩推荐&lt;/p&gt;  &lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=Mzg2MTAwNzg1Ng==&amp;mid=2247489745&amp;idx=1&amp;sn=6f77d8693394a4a0366b9746bed80f01&amp;scene=21#wechat_redirect" target="_blank"&gt;    &lt;img&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=Mzg2MTAwNzg1Ng==&amp;mid=2247489652&amp;idx=1&amp;sn=65c62897ab40e356beba9c6ea3f4aa55&amp;scene=21#wechat_redirect" target="_blank"&gt;    &lt;img&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=Mzg2MTAwNzg1Ng==&amp;mid=2247489635&amp;idx=1&amp;sn=3c48e93c56b4c3c088ce793872954807&amp;scene=21#wechat_redirect" target="_blank"&gt;    &lt;img&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;img&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>dev</category>
      <guid isPermaLink="true">https://itindex.net/detail/62571-%E5%85%A8%E7%90%83-%E7%BD%91%E7%BB%9C-%E6%94%BB%E5%87%BB</guid>
      <pubDate>Tue, 03 Jan 2023 00:00:00 CST</pubDate>
    </item>
    <item>
      <title>网络安全科普：详解 HTTPS 与 TLS</title>
      <link>https://itindex.net/detail/62556-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8-%E7%A7%91%E6%99%AE-https</link>
      <description>&lt;h2&gt;引言&lt;/h2&gt;

 &lt;p&gt;现在的网站都推荐使用 HTTPS 来确保用户数据的安全，验证网站的所有权，防止攻击者创建虚假网站版本，以及将信任传达给用户。如果网站要求用户登录、输入个人详细信息（例如其信用卡号）或查看机密信息（例如，健康福利或财务信息），则必须对数据保密。&lt;/p&gt;

 &lt;p&gt;作为普通用户，当我们上网冲浪时，是否想过为什么越来越多的域名输入时是 HTTPS 开头而非 HTTP 么？HTTPS 相比 HTTP 多出来的 S 到底多了些什么？TLS 和 SSL 又是什么，握手机制是如何进行的？其在七层协议中处于什么位置，与 HTTPS 相关的概念比如 CA 证书、Keyless、DTLS、mTLS 又分别是些啥？当我们使用 wireshark 时又该怎么抓包分析……种种疑问，希望能通过这篇文章的介绍为大家解答其中的部分解惑。&lt;/p&gt;

 &lt;h2&gt;背景与介绍&lt;/h2&gt;

 &lt;h3&gt;什么是 HTTPS&lt;/h3&gt;

 &lt;p&gt;超文本传输协议 (Hypertext Transfer Protocol, HTTP) 是设计用于在 Web 上传输内容的协议。 HTTP 是一种简单协议，它利用可靠的传输控制协议 (Transmission Control Protocol, TCP) 服务来执行其内容传输功能。由于数据在传输过程中是明文传输，因此无法保证网络通信在传输过程中不被篡改，安全性受到限制。&lt;/p&gt;

 &lt;p&gt;超文本传输安全协议 (HTTPS) 是 HTTP 的安全版本，但 HTTPS 并不是独立于 HTTP 的协议。它只是在 HTTP 协议的基础上使用 TLS/SSL 加密。HTTPS 经过加密，以提高数据传输的安全性。&lt;/p&gt;

 &lt;h3&gt;为什么 HTTPS 可以保证安全&lt;/h3&gt;

 &lt;p&gt;HTTPS 使用加密协议对通信进行加密。该协议称为传输层安全性 (TLS)，但以前称为安全套接字层 (SSL)。该协议通过使用所谓的非对称公钥基础架构来保护通信。这种类型的安全系统使用两个不同的密钥来加密两方之间的通信：&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;私钥 - 此密钥由网站所有者控制，并且如读者所推测的那样，它是私有的。此密钥位于 Web 服务器上，用于解密通过公钥加密的信息。&lt;/li&gt;
    &lt;li&gt;公钥 - 所有想要以安全方式与服务器交互的人都可以使用此密钥。用公钥加密的信息只能用私钥解密。&lt;/li&gt;
&lt;/ol&gt;

 &lt;p&gt;HTTPS安全是由一套安全机制来保证的，主要包含这4个特性：  &lt;strong&gt;机密性、完整性、真实性和不可否认性&lt;/strong&gt;。&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;机密性是指传输的数据是采用 Session Key（会话密钥）加密的，在网络上是看不到明文的。&lt;/li&gt;
    &lt;li&gt;完整性是指为了避免网络中传输的数据被非法篡改，使用 MAC 算法来保证消息的完整性。&lt;/li&gt;
    &lt;li&gt;真实性是指通信的对方是可信的，利用了 PKI（Public Key Infrastructure 即「公钥基础设施」）来保证公钥的真实性。&lt;/li&gt;
    &lt;li&gt;不可否认性是这个消息就是你给我发的，无法伪装和否认，是因为使用了签名的技术来保证的。&lt;/li&gt;
&lt;/ul&gt;

 &lt;h3&gt;什么是 SSL/TLS&lt;/h3&gt;

 &lt;p&gt;SSL（Secure Socket Layer）是指安全套接字层，简而言之，它是一项标准技术，可确保互联网连接安全，保护两个系统之间发送的任何敏感数据，防止网络犯罪分子读取和修改任何传输信息，包括个人资料。TLS（Transport Layer Security，传输层安全）是更为安全的升级版 SSL。&lt;/p&gt;

 &lt;p&gt;TLS 1.0 版实际上最初作为 SSL 3.1 版开发，HTTPS 是在 HTTP 协议基础上实施 TLS 加密，所有网站以及其他部分 web 服务都使用该协议。因此，任何使用 HTTPS 的网站都使用 TLS 加密。&lt;/p&gt;

 &lt;p&gt;使用了 SSL/TLS 之后，因为数据被非对称加密手段加密了，即使被截获，也是获取不到信息的。&lt;/p&gt;

 &lt;p&gt;TLS 协议实现的功能有三个主要组成部分：加密、认证和完整性。&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;   &lt;strong&gt;加密：&lt;/strong&gt; 隐藏从第三方传输的数据。&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;身份验证：&lt;/strong&gt; 确保交换信息的各方是他们所声称的身份。&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;完整性：&lt;/strong&gt; 验证数据未被伪造或篡改。&lt;/li&gt;
&lt;/ul&gt;

 &lt;h3&gt;为什么 SSL/TLS 可以保证安全&lt;/h3&gt;

 &lt;p&gt;网站或应用程序要使用 TLS，必须在其源服务器上安装 TLS 证书（由于上述命名混淆，该证书也被称为 SSL 证书），而 TLS 连接是通过一个称为 TLS 握手的流程启动的，在这个过程中用户设备会和服务器交换确定信息，这些信息包括要使用的 TLS 版本、密码套件、TLS 证书、会话密钥等等。&lt;/p&gt;

 &lt;p&gt;而在浏览器端，当用户访问服务器页面的时候，浏览器会检查服务器的 SSL/TLS 许可是不是可用的，不可用的话，会提醒用户，这个网站不安全，也就是访问的数据可能被黑客截获；此时用户可以根据判断来不访问这个界面；许可都齐全的话，便可以安全的进行数据交互。&lt;/p&gt;

 &lt;p&gt;具体来说，SSL/TLS 在工作流程中通过如下三个方面保证安全性：&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;通过 CA 体系交换 public key&lt;/li&gt;
    &lt;li&gt;通过非对称加密算法，交换用于对称加密的密钥&lt;/li&gt;
    &lt;li&gt;通过对称加密算法，加密正常的网络通信&lt;/li&gt;
&lt;/ul&gt;

 &lt;h2&gt;术语表&lt;/h2&gt;

 &lt;p&gt;为了方便大家阅读，特在此章将全文涉及到的一些专业术语进行整理，整理此术语表供大家查阅。&lt;/p&gt;

 &lt;table&gt;
  
      &lt;tr&gt;
         &lt;th&gt;简称&lt;/th&gt;
         &lt;th&gt;英文全称&lt;/th&gt;
         &lt;th&gt;中文全称&lt;/th&gt;
    &lt;/tr&gt;
  
  
      &lt;tr&gt;
         &lt;td&gt;CA&lt;/td&gt;
         &lt;td&gt;Certificate Authority / Certification Authority&lt;/td&gt;
         &lt;td&gt;证书颁发机构&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;SSL&lt;/td&gt;
         &lt;td&gt;Secure Sockets Layer&lt;/td&gt;
         &lt;td&gt;安全套接字层协议&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;TLS&lt;/td&gt;
         &lt;td&gt;Transport Layer Security&lt;/td&gt;
         &lt;td&gt;传输层安全性协议&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;PKI&lt;/td&gt;
         &lt;td&gt;Public key infrastructure&lt;/td&gt;
         &lt;td&gt;公钥基础设施&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;PCA&lt;/td&gt;
         &lt;td&gt;Private Certificate Authority&lt;/td&gt;
         &lt;td&gt;私有证书颁发机构，又名私有 CA&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;HTTP&lt;/td&gt;
         &lt;td&gt;Hypertext Transfer Protocol&lt;/td&gt;
         &lt;td&gt;超文本传输协议&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;HTTPS&lt;/td&gt;
         &lt;td&gt;Hypertext Transfer Protocol Secure&lt;/td&gt;
         &lt;td&gt;超文本传输安全协议&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;-&lt;/td&gt;
         &lt;td&gt;Public key&lt;/td&gt;
         &lt;td&gt;公钥&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;-&lt;/td&gt;
         &lt;td&gt;Private key&lt;/td&gt;
         &lt;td&gt;私钥&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;OSI&lt;/td&gt;
         &lt;td&gt;Open Systems Interconnection&lt;/td&gt;
         &lt;td&gt;开放网络互联模型&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;TCP&lt;/td&gt;
         &lt;td&gt;Transmission Control Protocol&lt;/td&gt;
         &lt;td&gt;传输控制协议&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;DTLS&lt;/td&gt;
         &lt;td&gt;Datagram Transport Layer Security&lt;/td&gt;
         &lt;td&gt;数据包传输层安全性协议&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;mTLS&lt;/td&gt;
         &lt;td&gt;Mutual Transport Layer Security&lt;/td&gt;
         &lt;td&gt;双向 TLS&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;DH&lt;/td&gt;
         &lt;td&gt;Diffie-Hellman key exchange&lt;/td&gt;
         &lt;td&gt;迪菲-赫尔曼密钥交换&lt;/td&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
         &lt;td&gt;-&lt;/td&gt;
         &lt;td&gt;premaster secret&lt;/td&gt;
         &lt;td&gt;预主密钥&lt;/td&gt;
    &lt;/tr&gt;
  
&lt;/table&gt;

 &lt;h2&gt;TLS 相关协议详解&lt;/h2&gt;

 &lt;h3&gt;HTTPS 协议组成&lt;/h3&gt;

 &lt;p&gt;HTTP 协议是用于从网络传送超文本数据到本地浏览器的传送协议，HTTPS 协议简单讲是 HTTP 的安全版，在 HTTP 协议的基础上加入 SSL 层。&lt;/p&gt;

 &lt;p&gt;其中，HTTP的端口号为80， HTTPS的端口号为443，两者均为应用层协议，在 OSI 七层模型的最上层。&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-0.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;h3&gt;HTTPS 与 CA 证书&lt;/h3&gt;

 &lt;p&gt;在 HTTPS 的工作流程中，一个重要的角色便是证书，他的正常运行需要有一个证书（CA 证书）：由专门的证书机构颁发。在知道了 TLS 的握手流程后，我们来看看证书在其中所起到的作用。&lt;/p&gt;

 &lt;p&gt;当客户端向服务端发送请求，请求中会向服务器提供以下信息：客户端支持的协议版本，比如TLS 1.0 版，此后，服务器返回经过 CA 认证的数字证书，证书里面包含了服务器的 public key，接下来证书在客户端的工作流程如下：&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;客户端读取证书中的相关的明文信息，采用相同的散列函数计算得到信息摘要，然后，利用对应CA的公钥解密签名数据，对比证书的信息摘要，如果一致，则可以确认证书的合法性，即公钥合法；&lt;/li&gt;
    &lt;li&gt;客户端然后验证证书相关的域名信息、有效时间等信息；&lt;/li&gt;
    &lt;li&gt;客户端会内置信任 CA 的证书信息（此处一般指顶级 CA 的自签根证书，包含公钥），如果 CA 不被信任，则找不到对应 CA 的证书，证书也会被判定非法；此外，客户端还会通过 OCSP 对证书状态进行查询；&lt;/li&gt;
    &lt;li&gt;客户端在完成对数字证书的验证后，用自己浏览器内置的 CA 证书解密得到服务器的 public key；&lt;/li&gt;
    &lt;li&gt;客户端用服务器的 public key 加密一个预主密钥（这个密钥将在之后结合随机数等信息被用于客户端和服务端各自生成用于网络通信的对称密钥），传给服务器。因为只有服务器有 private key 可以解密，所以不用担心中间人拦截这个加密数据而获取其中的密钥信息；&lt;/li&gt;
    &lt;li&gt;服务器拿到这个加密的密钥，解密获取信息，再依据双方约定好的参数生成对称加密密钥，并以此和客户端完成接下来的网络通信；&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;关于 TLS 证书/CA 证书的更多细节，可以参见文章《  &lt;a href="https://hijiangtao.github.io/2022/11/16/Dig-Out-All-Secrets-Behind-TLS-Certificate-One/"&gt;奇妙的 SSL/TLS 证书&lt;/a&gt;》，本文不再深入探讨。&lt;/p&gt;

 &lt;h3&gt;TLS/SSL 握手与密钥交换&lt;/h3&gt;

 &lt;p&gt;HTTPS 连接建立过程和 HTTP 差不多，区别在于 HTTP（默认端口 80） 请求只要在 TCP 连接建立后就可以发起，而 HTTPS（默认端口 443） 在 TCP 连接建立后，还需要经历 SSL 协议握手，成功后才能发起请求。&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-1.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;h4&gt;TLS 1.2 握手流程&lt;/h4&gt;

 &lt;p&gt;在 TLS1.2 以前，需要2-RTT时间进行握手，我们具体来看每一步操作：&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;   &lt;strong&gt;第1步：&lt;/strong&gt;整个连接是从客户端向服务器发送“Client Hello”消息开始。该消息由加密信息组成，与此同时客户端也会将本身支持的所有密码套件（Cipher Suite）列表发送过去，包括支持的协议和支持的密码套件，也包含一个随机值或随机字节串。&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;第2步：&lt;/strong&gt;响应客户端的“客户端问候”消息，服务器以“Server Hello”消息响应。此消息包含服务器已从客户端提供的 CipherSuite 中选择的 CipherSuite。服务器还会将其证书以及会话ID和另一个随机值一起发送。&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;第3步：&lt;/strong&gt;客户端验证服务器发送的证书。验证完成后，它会发送一个随机字节字符串，也称为“预主密钥”，并使用服务器证书的公钥对其进行加密。客户端向服务器发送“ChangeCipherSpec”消息，通过会话密钥的帮助让它知道它将切换到对称加密。与此同时，它还发送“客户端已完成”消息。&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;第4步：&lt;/strong&gt;一旦服务器收到预主密钥，客户端和服务器都会生成一个主密钥以及会话密钥(临时密钥)。这些会话密钥将用于对称加密数据。在答复客户端的“更改密码规范”消息时，服务器执行相同操作并将其安全状态切换为对称加密。服务器通过发送“服务器已完成”消息来结束握手。&lt;/li&gt;
&lt;/ol&gt;

 &lt;p&gt;在客户端和服务器之间进行了两次往返（2-RTT）以完成握手。 平均而言，这需要0.25秒到0.5秒之间的时间。而这只是握手过程，实际的数据传输还没有开始。我们绘制示意图如下解释如上流程：&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-2.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;h4&gt;TLS 1.3 握手流程&lt;/h4&gt;

 &lt;p&gt;TLS1.3 在握手上做了优化，只需要一次时延往返就可以建立连接（1-RTT），其握手基本步骤为：&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;   &lt;strong&gt;客户端问候：&lt;/strong&gt;客户端发送客户端问候消息，内含协议版本、客户端随机数和密码套件列表。由于已从 TLS 1.3 中删除了对不安全密码套件的支持，因此可能的密码套件数量大大减少。客户端问候消息还包括将用于计算预主密钥的参数。&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;服务器生成主密钥：&lt;/strong&gt;此时，服务器已经接收到客户端随机数以及客户端的参数和密码套件。它已经拥有服务器随机数，因为它可以自己生成。因此，服务器可以创建主密钥。&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;服务器问候和“完成”：&lt;/strong&gt;服务器问候包括服务器的证书、数字签名、服务器随机数和选择的密码套件。因为它已经有了主密钥，所以它也发送了一个“完成”消息。&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;最后步骤和客户端“完成”：&lt;/strong&gt;客户端验证签名和证书，生成主密钥，并发送“完成”消息。&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;实现安全对称加密：&lt;/strong&gt;依据双方约定好的参数生成的对称加密主密钥，将被用在接下来客户端和服务端的网络通信中；&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;TLS 1.3 的核心宗旨是简单性。在新版本中，除去了 Diffie-Hellman（DH）密钥交换以外的所有密钥交换算法。简而言之，DH 算法（Diffie-Hellman 算法）可以保证在双方不直接传输原始密钥的情况下，完成双方密钥交换。&lt;/p&gt;

 &lt;p&gt;TLS 1.3 还定义了一组经过测试的 DH 参数，无需与服务器协商参数。由于只有一个密钥交换算法（具有内置参数）和少数支持的密码，因此设置 TLS 1.3 通道所需的绝对带宽比早期版本要少得多。示意图流程如下：&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-3.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;h3&gt;基于 UDP 的 TLS 协议：DTLS&lt;/h3&gt;

 &lt;h4&gt;DTLS 介绍&lt;/h4&gt;

 &lt;p&gt;DTLS 是基于 UDP 场景下数据包可能丢失或重新排序的现实情况下，为 UDP 定制和改进的 TLS 协议。&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-4.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;DTLS 协议由两层组成: Record 协议 和 Handshake 协议&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;Record 协议：使用对称密钥对传输数据进行加密，并使用 HMAC 对数据进行完整性校验，实现了数据的安全传输。&lt;/li&gt;
    &lt;li&gt;Handshake 协议：使用非对称加密算法，完成 Record 协议使用的对称密钥的协商。&lt;/li&gt;
&lt;/ol&gt;

 &lt;h4&gt;DTLS 与 TLS 握手差异&lt;/h4&gt;

 &lt;p&gt;与 TLS 的握手流程相比，DTLS 的握手流程存在如下几点差异（左为 TLS 握手，右为 DTLS 握手）：&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-5.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;HelloVerifyRequest 用于服务端对客户端实现二次校验；DTLS 的 RecordLayer 新增了 SequenceNumber 和 Epoch，以及 ClientHello 中新增了 Cookie，以及 Handshake 中新增了 Fragment 信息（防止超过 UDP 的 MTU），都是为了适应 UDP 的丢包以及容易被攻击做的改进；&lt;/li&gt;
    &lt;li&gt;Certificate 是交换的证书，由协商后的算法确定是否需要传输；&lt;/li&gt;
    &lt;li&gt;TLS 没有发送 CertificateRequest，这个也不是必须的，是反向验证即服务器验证客户端；当服务端要求验证客户端身份时，发起 CertificateRequest，此时客户端需要发送证书；&lt;/li&gt;
    &lt;li&gt;ChangeCipherSpec 是一个简单的标记，标明当前已经完成密钥协商，可以准备传输；&lt;/li&gt;
    &lt;li&gt;Finished 消息表示握手结束，通常会携带加密数据由对端进行初次验证。&lt;/li&gt;
&lt;/ol&gt;

 &lt;h4&gt;DTLS 的握手防护、加密方式与应用场景&lt;/h4&gt;

 &lt;p&gt;在实现机制上，DTLS 还存在几个特点，首先是握手防护机制，在这个机制中，除了上文说到的防止被攻击等在握手阶段引入的改进措施外，还有一个机制叫重传：&lt;/p&gt;

 &lt;ul&gt;
    &lt;li&gt;DTLS 每一方在每次握手中传送的第一个消息总是有 message_seq = 0。每当有新消息产生时，message_seq 的值就会增加1。&lt;/li&gt;
    &lt;li&gt;DTLS需兼容多种出错场景，出错时往往直接丢弃处理，而在 TLS 中，如果出错，则会中断连接；&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;以握手的第一阶段举例，客户端发送 Client Hello（不带 Cookie，区别于握手流程中的第二次 Client Hello）之后，启动一个定时器，等待服务端返回 HelloVerifyRequest，如果超过了定时器时间客户端还没有收到 HelloVerifyRequest，那么客户端就会知道要么是 Client Hello 消息丢了要么是 Hello Verify Request 消息丢了，客户端就会再次发送相同的 Client Hello 消息，即使服务端确实发送了 Hello Verify Request 还是收到了 Client Hello 消息，它也知道是需要重传，并再次发送 Hello Verify Request 消息，同样地，服务端也会启动定时器来等待下一条消息。&lt;/p&gt;

 &lt;p&gt;由于 DTLS 依赖 UDP，而 SSL/TLS 依赖 TCP，所以两者在加密方式上存在如下差异：&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;SSL/TLS 不能独立解密单个封包，SSL/TLS 对于封包的认证需要序号作为输入，在 SSL/TLS 中并未直接传递序号，因为 TCP 是可靠的，所以 SSL/TLS 的两端各自维护自身的收发序号；&lt;/li&gt;
    &lt;li&gt;DTLS 支持独立解密，其通过在每条记录中显式携带的序号作为解码的输入；此外，由于算法加解密的限制，DTLS所支持的加密算法为 TLS 的子集。&lt;/li&gt;
&lt;/ol&gt;

 &lt;p&gt;DTLS 主要被用在 WebRTC 协议中，以保证媒体传输的安全性。&lt;/p&gt;

 &lt;h3&gt;客户端身份校验与 mTLS&lt;/h3&gt;

 &lt;p&gt;在基础的 TLS 认证流程中，大量的场景都是确保用户访问的是真正的服务方，如：银行、电商网站等等，即保证用户不会被钓鱼网站或是中间人攻击，此时我们只需要在客户端侧对服务端身份进行校验。&lt;/p&gt;

 &lt;h4&gt;SSL 连接中的客户端身份校验&lt;/h4&gt;

 &lt;p&gt;在典型的 SSL 连接场景中，通过 HTTPS 连接到服务器的客户端会检查服务器的有效性，它会在启动 SSL 握手时检查服务器返回证书的有效性。但是，有时你可能希望将服务器配置为对与其连接的客户端进行身份验证。这样，你便可以只允许使用证书进行身份验证的用户访问 web 服务器上的资源。&lt;/p&gt;

 &lt;p&gt;启用客户端身份校验的两个基本步骤：&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;客户端需要获取、并安装经过 CA 认证的 SSL/TLS 证书&lt;/li&gt;
    &lt;li&gt;服务端需要开启客户端身份验证选项&lt;/li&gt;
&lt;/ol&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-6.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;由于客户端安装证书的不方便性、成本高以及双因素身份验证的快速推行，客户端身份验证并没有得到广泛使用。&lt;/p&gt;

 &lt;h4&gt;mTLS 介绍&lt;/h4&gt;

 &lt;p&gt;很多时候，比如在一些支付场景下，我们和支付机构、商户构成的三者关系中，在商户和支付机构间需要保证相互的身份认证，以保证支付信息在两者间正常流转，这时便需要我们使用双向认证，即相互 TLS。&lt;/p&gt;

 &lt;p&gt;相互 TLS，简称 mTLS，是一种相互身份验证的方法。mTLS 通过验证他们都拥有正确的私人密钥来确保网络连接两端的各方都是他们声称的身份。他们各自的 TLS 证书中的信息提供了额外的验证。&lt;/p&gt;

 &lt;h4&gt;mTLS 与 TLS 流程的区别&lt;/h4&gt;

 &lt;p&gt;一个典型的 TLS 流程应该包含如下几步：&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;客户端连接到服务器&lt;/li&gt;
    &lt;li&gt;服务器出示其 TLS 证书&lt;/li&gt;
    &lt;li&gt;客户端验证服务器的证书&lt;/li&gt;
    &lt;li&gt;客户端和服务器通过加密的 TLS 连接交换信息&lt;/li&gt;
&lt;/ol&gt;

 &lt;p&gt;相比之下，mTLS 会在客户端验证服务器证书后加上几步，以保证服务端可以对客户端身份进行验证，并授予访问权限，一个完整的 mTLS 流程如下：&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;客户端连接到服务器&lt;/li&gt;
    &lt;li&gt;服务器出示其 TLS 证书&lt;/li&gt;
    &lt;li&gt;客户端验证服务器的证书&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;客户端出示其 TLS 证书&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;服务器验证客户端的证书&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;strong&gt;服务器授予访问权限&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;客户端和服务器通过加密的 TLS 连接交换信息&lt;/li&gt;
&lt;/ol&gt;

 &lt;h4&gt;mTLS 的应用场景与安全性&lt;/h4&gt;

 &lt;p&gt;由于公共互联网上亟待解决的问题是防止被访问的网站内容被篡改，保证用户不会访问到钓鱼网站；此外，再加上将 TLS 证书分发到所有终端用户设备上是非常困难的现状，mTLS 并没有被运用到整个互联网。mTLS 对于较小范围内的组织验证和通信非常有用，除了验证信息外，他还可以防止各种类型的攻击，比如在途攻击、网络钓鱼攻击以及恶意 API 请求等等。&lt;/p&gt;

 &lt;p&gt;mTLS 通常被用于零信任安全框架，以验证组织内的用户、设备和服务器。它也可以帮助保持 API 的安全。&lt;/p&gt;

 &lt;h3&gt;HTTPS 与 Keyless SSL&lt;/h3&gt;

 &lt;p&gt;虽然 HTTPS 可以解决传输的安全性但是引入了私钥的安全和管理问题。只要拿到了私钥，HTTPS 就如同虚设。尤其是在传统 CDN 加速场景下，需要将私钥证书同步给 CDN，无形中增加了风险，所以诞生了 Keyless 技术。这项技术可以使得客户在使用 CDN 进行 HTTPS 加速时保留其自身 SSL 的私钥，在仅有公钥的场景下顺利完成 SSL 握手。&lt;/p&gt;

 &lt;p&gt;在 Keyless 的作用下，服务端不解密密文，而是将经加密后的预主密钥（premaster secret）等数据打包发送给远端 key server，由其进行加工并返回数据；针对 DH 协商密钥的流程，服务端则负责将 DH 参数、服务端随机数、客户端随机数等数据传给 key server，由 key server 处理后返回 DH 数据以及证书等信息。&lt;/p&gt;

 &lt;p&gt;以 CloudFlare 为例，我们看看 Keyless 在部署时有设计哪些额外的流程以保证安全。为了使 Keyless SSL 安全，CloudFlare 边缘到 key server 的连接也需要安全。key server 可以为所有能够访问它的人提供私钥操作，就像一个密码数据库。保证只有 CloudFlare 可以访问 key server 来执行操作对 Keyless SSL 至关重要。&lt;/p&gt;

 &lt;p&gt;CloudFlare 通过相互认证的 TLS 机制来保证 CloudFlare 和 key server 之间的连接安全。在握手环节一章，我们提到了客户端对服务端的单方向身份认证，是通过验证 CA 证书来进行的，而后我们也提到了客户端身份校验，这在这里便派上了用场。在 TLS 双向认证中，客户端和服务端都由对方的证书并相互认证。&lt;/p&gt;

 &lt;p&gt;在 Keyless SSL 中，key server 仅允许携带 CloudFlare 内部签发的证书的连接。CloudFlare 使用我们自己签发的证书来进行双向认证。&lt;/p&gt;

 &lt;p&gt;在这里，我们以 RSA 为例，如下两图展示了在接入 Keyless 前后，TLS 握手过程的变化差异。&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-7.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-8.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;h3&gt;RFC 协议标准&lt;/h3&gt;

 &lt;p&gt;本文介绍的各类协议均有对应的 RFC 标准，罗列于此供读者参考：&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;TLS1.3    &lt;a href="https://www.rfc-editor.org/rfc/rfc8446"&gt;https://www.rfc-editor.org/rfc/rfc8446&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;DTLS1.2    &lt;a href="https://www.rfc-editor.org/rfc/rfc6347.html"&gt;https://www.rfc-editor.org/rfc/rfc6347.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;HTTPS    &lt;a href="https://www.rfc-editor.org/rfc/rfc2818.html"&gt;https://www.rfc-editor.org/rfc/rfc2818.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;MTLS    &lt;a href="https://www.rfc-editor.org/rfc/rfc8705"&gt;https://www.rfc-editor.org/rfc/rfc8705&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

 &lt;h2&gt;HTTPS 流量抓包与分析&lt;/h2&gt;

 &lt;p&gt;利用 wireshark 我们可以对 https 流量进行抓包分析，下载地址见   &lt;a href="https://www.wireshark.org/#download"&gt;https://www.wireshark.org/#download&lt;/a&gt;&lt;/p&gt;

 &lt;h3&gt;操作与步骤&lt;/h3&gt;

 &lt;p&gt;通过 Wireshark 我们可以很好的过滤 HTTPS 流量，比如如下常见的几个过滤条件：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;// TLS加密传输数据的过滤器
ssl.record.content_type == 23  and tcp.dstport == 443

// TLS 建立连接
ssl.handshake.type == 1

// 在知道 IP 地址为A时的指定 TLS 流量
ip.addr == A &amp;amp;&amp;amp; tcp.port == 443
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;但对于 HTTPS 流量，如果需要解密，我们还需要增加如下几个步骤来达成目的：&lt;/p&gt;

 &lt;ol&gt;
    &lt;li&gt;在终端打开你的 chrome 浏览器，并指定你的 SSL key 的 log 日志存放地址，假设地址为A；&lt;/li&gt;
    &lt;li&gt;在 WireShark 中，通过路径 Wireshark - Preferences - Protocols - TLS ，在 (Pre)-Master-Secret log filename 输入同样的地址 A，并保存；&lt;/li&gt;
    &lt;li&gt;然后通过第一步打开的浏览器访问 https 协议的网站地址，并在 wireshark 中指定 filter 例如    &lt;code&gt;tls &amp;amp;&amp;amp; ip.addr=1.1.1.1&lt;/code&gt; 来过滤指定 tls 流量；&lt;/li&gt;
&lt;/ol&gt;

 &lt;p&gt;通过 Wireshark 抓包，以一个 TLS1.2 版本的 ClientHello 消息报文内容为例，我们可以看到其中包含了客户端支持的 TLS 版本、加密套件、以及用于连接的 SNI 等信息&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-9.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;同样的，以一个 TLS1.2 版本的建立连接为例，我们可以看到 Server 在返回 Server Hello 之后还返回了证书、Server Key Exchange 以及 Server Done 等信息&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="Untitled" src="https://hijiangtao.github.io/assets/in-post/2022-12-25-HTTP-and-TLS-10.png"&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;h2&gt;应用与拓展场景&lt;/h2&gt;

 &lt;h3&gt;实现 Charles 抓包代理&lt;/h3&gt;

 &lt;p&gt;用过抓包工具的人都知道，比如 Charles，Fiddler 是可以抓取 HTTPS 请求并解密的，它们是如何做到的呢？&lt;/p&gt;

 &lt;p&gt;简单来说，Charles 作为一个“中间人代理”，当浏览器和服务器通信时，Charles 接收服务器的证书，然后动态生成一张证书发送给浏览器，也就是说 Charles 作为中间代理在浏览器和服务器之间通信，所以通信的数据可以被 Charles 拦截并解密，这包括服务器证书公钥和 HTTPS 连接的对称密钥。&lt;/p&gt;

 &lt;p&gt;由于 Charles 更改了证书，浏览器校验不通过会给出安全警告，所以 Charles 可以正常工作的前提在于必须安装 Charles 的证书，使系统信任。&lt;/p&gt;

 &lt;h3&gt;为开发环境启动 HTTPS&lt;/h3&gt;

 &lt;p&gt;在本地开发功能模块时，可能有些 Web API 前置要求环境为 HTTPS，这要求我们在本地开发环境也能够配置 HTTPS，OpenSSL 是 SSL 和 TLS 协议的开放式源代码实现，使用它，我们可以在本地生成一个自签名证书，以方便开发。如下一行命令可以帮助我们生成一个 HTTPS 证书以及私钥：&lt;/p&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;pre&gt;    &lt;code&gt;openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

 &lt;p&gt;社区里有一个开源库叫 mkcert，可以更便捷的为你生成 TLS 证书，这里不深入介绍，感兴趣可以移步   &lt;a href="https://github.com/FiloSottile/mkcert"&gt;https://github.com/FiloSottile/mkcert&lt;/a&gt; 查看更多。&lt;/p&gt;

 &lt;p&gt;注：为了能够正常使用，本地生成的证书需要被加入信任列表才能正常使用。&lt;/p&gt;

 &lt;h2&gt;参考&lt;/h2&gt;

 &lt;ol&gt;
    &lt;li&gt;   &lt;a href="https://www.cloudflare.com/zh-cn/learning/ssl/what-happens-in-a-tls-handshake/"&gt;https://www.cloudflare.com/zh-cn/learning/ssl/what-happens-in-a-tls-handshake/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://tech.bytedance.net/articles/7166221771396349982"&gt;https://tech.bytedance.net/articles/7166221771396349982&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://blog.csdn.net/qzcsu/article/details/72861891"&gt;https://blog.csdn.net/qzcsu/article/details/72861891&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://tinychen.com/20200602-encryption-intro/"&gt;https://tinychen.com/20200602-encryption-intro/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://comodosslstore.com/blog/what-is-ssl-tls-client-authentication-how-does-it-work.html"&gt;https://comodosslstore.com/blog/what-is-ssl-tls-client-authentication-how-does-it-work.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://web.dev/i18n/zh/how-to-use-local-https/"&gt;https://web.dev/i18n/zh/how-to-use-local-https/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://blog.cloudflare.com/announcing-keyless-ssl-all-the-benefits-of-cloudflare-without-having-to-turn-over-your-private-ssl-keys/"&gt;https://blog.cloudflare.com/announcing-keyless-ssl-all-the-benefits-of-cloudflare-without-having-to-turn-over-your-private-ssl-keys/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/"&gt;https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://tech.bytedance.net/articles/6915326021995200519"&gt;https://tech.bytedance.net/articles/6915326021995200519&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;   &lt;a href="https://www.cloudflare.com/zh-cn/learning/access-management/what-is-mutual-tls/"&gt;https://www.cloudflare.com/zh-cn/learning/access-management/what-is-mutual-tls/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Document HTTPS TLS mTLS DTLS</category>
      <guid isPermaLink="true">https://itindex.net/detail/62556-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8-%E7%A7%91%E6%99%AE-https</guid>
      <pubDate>Sun, 25 Dec 2022 08:00:00 CST</pubDate>
    </item>
    <item>
      <title>聊聊容器网络和 iptables</title>
      <link>https://itindex.net/detail/62542-%E5%AE%B9%E5%99%A8-%E7%BD%91%E7%BB%9C-iptables</link>
      <description>&lt;p&gt;大家好，我是张晋涛。&lt;/p&gt;
 &lt;p&gt;上周有小伙伴在群里问到 Docker 和 Iptables 的关系，这里来具体聊聊。&lt;/p&gt;
 &lt;p&gt;Docker 能为我们提供很强大和灵活的网络能力，很大程度上要归功于与 iptables 的结合。在使用时，你可能没有太关注到 iptables 的作用，这是因为 Docker 已经帮我们自动完成了相关的配置。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ dockerd --help |grep iptables
--iptables Enable addition of iptables rules (default true)
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;docker daemon 有个   &lt;code&gt;--iptables&lt;/code&gt; 的参数，便是用来控制是否要自动启用 iptables 规则的，默认已经设置成了开启（true）。所以通常我们不会过于关注到它的工作。&lt;/p&gt;
 &lt;p&gt;本文中，为了避免环境的干扰，我将使用 docker in docker 的环境来进行介绍，可通过如下方式启动该环境：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker run --rm -d --privileged docker:dind
f323aef7b532ba6d575ca6f9444a08f1a55f2447afec2e853954694c034e6ae0
&lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;iptables 基础&lt;/h2&gt;
 &lt;p&gt;  &lt;code&gt;iptables&lt;/code&gt; 是一个用于配置 Linux 内核防火墙的工具，可用于检测、修改转发、重定向以及丢弃 IPv4 数据包。它使用了内核的 ip_tables 的功能，所以需要 Linux 2.4+ 版本的内核。&lt;/p&gt;
 &lt;p&gt;同时，iptables 为了便于管理，所以按照不同的目的组织了多张   &lt;strong&gt;表&lt;/strong&gt; ；每张表中又包含了很多预定义的   &lt;strong&gt;链&lt;/strong&gt;；每个链中包含着顺序遍历的   &lt;strong&gt;规则&lt;/strong&gt;；这些规则中又定义了动作的匹配规则和   &lt;strong&gt;目标&lt;/strong&gt;。&lt;/p&gt;
 &lt;p&gt;对于用户而言，我们通常需要交互的就是   &lt;strong&gt;链&lt;/strong&gt;和   &lt;strong&gt;规则&lt;/strong&gt;了。&lt;/p&gt;
 &lt;p&gt;理解 iptables 的主要工作流程有一张比较经典的图：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="img/tables_traverse.jpg" src="https://www.frozentux.net/iptables-tutorial/images/tables_traverse.jpg"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;em&gt;图片来源：    &lt;a href="https://www.frozentux.net/iptables-tutorial/images/tables_traverse.jpg"&gt;https://www.frozentux.net/iptables-tutorial/images/tables_traverse.jpg&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
 &lt;p&gt;上面的小写字母是   &lt;strong&gt;表&lt;/strong&gt;，大写字母则表示   &lt;strong&gt;链&lt;/strong&gt;，从任何网络端口 进来的每一个 IP 数据包都要从上到下的穿过这张图。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;引用自    &lt;a href="https://wiki.archlinux.org/index.php/Iptables"&gt;ArchWiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;不过这不是本篇的重点，所以就不展开了。如果大家对 iptables 的内容感兴趣也欢迎留言，后续可以写一篇完整的。&lt;/p&gt;
 &lt;h2&gt;Docker 网络与 iptables&lt;/h2&gt;
 &lt;p&gt;接下来我们直接看看 Docker 在开启和关闭 iptables 时，具体有什么区别。&lt;/p&gt;
 &lt;h3&gt;关闭 Docker 的 iptables 支持&lt;/h3&gt;
 &lt;p&gt;在本文开头已经为你介绍过 docker daemon 存在一个   &lt;code&gt;--iptables&lt;/code&gt; 的参数，用于控制是否使用 iptables 。我们使用以下命令启动一个 docker daemon 并关闭 iptables 支持。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker run --rm -d --privileged docker:dind dockerd --iptables=false
7135a54c913af5e9ce69a45a0819475503ea9e3c5c673d62d9d38f0f0896179d
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;进入此容器，并查看其所有 iptables 规则：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker exec -it $(docker ps -ql) sh
/ # iptables-save
# Generated by iptables-save v1.8.8 on Mon Dec 12 01:46:38 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [2:80]
COMMIT
# Completed on Mon Dec 12 01:46:38 2022
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;可以看到，当 docker daemon 加了   &lt;code&gt;--iptables=false&lt;/code&gt; 的参数时，默认没有任何规则的输出。&lt;/p&gt;
 &lt;h3&gt;开启 Docker 的 iptables 支持&lt;/h3&gt;
 &lt;p&gt;使用以下命令启动一个 docker daemon，这里没有显式的传递   &lt;code&gt;--iptables&lt;/code&gt; 选项，因为默认就是   &lt;code&gt;true&lt;/code&gt; 。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker run --rm -d --privileged docker:dind
c464c5c08ecdf9129afbf217c6462236089fe0a1d11dfe7700c2985a04d8d216
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查看其 iptables 规则：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker exec -it $(docker ps -ql) sh
/ # iptables-save
# Generated by iptables-save v1.8.8 on Mon Dec 12 14:48:16 2022
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [1:40]
:POSTROUTING ACCEPT [1:40]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.18.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
COMMIT
# Completed on Mon Dec 12 14:48:16 2022
# Generated by iptables-save v1.8.8 on Mon Dec 12 14:48:16 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [2:80]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Mon Dec 12 14:48:16 2022
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;可以看到，它比刚才关闭 iptables 支持时多了几条链：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;DOCKER&lt;/li&gt;
  &lt;li&gt;DOCKER-ISOLATION-STAGE-1&lt;/li&gt;
  &lt;li&gt;DOCKER-ISOLATION-STAGE-2&lt;/li&gt;
  &lt;li&gt;DOCKER-USER&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;以及增加了一些转发规则，以下将具体介绍。&lt;/p&gt;
 &lt;h3&gt;DOCKER-USER 链&lt;/h3&gt;
 &lt;p&gt;在上述新增的几条链中，我们先来看最先生效的 DOCKER-USER 。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;*filter
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
...
-A DOCKER-USER -j RETURN
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;以上规则是在 filter 表中生效的：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;第一条是    &lt;code&gt;-A FORWARD -j DOCKER-USER&lt;/code&gt; 这表示流量进入 FORWARD 链后，直接进入到 DOCKER-USER 链；&lt;/li&gt;
  &lt;li&gt;最后一条    &lt;code&gt;-A DOCKER-USER -j RETURN&lt;/code&gt; 这表示流量进入 DOCKER-USER 链处理后，（如果无其他处理）可以再 RETURN 回原先的链，进行后续规则的匹配。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;这其实是 Docker 预留的一个链，供用户来自行配置的一些额外的规则的。&lt;/p&gt;
 &lt;p&gt;Docker 默认的路由规则是允许所有客户端访问的，   &lt;strong&gt;如果你的 Docker 运行在公网，或者你希望避免 Docker 中容器被局域网内的其他客户端访问，那么你需要在这里添加一条规则&lt;/strong&gt;。
比如, 你仅仅允许 100.84.94.62 访问，但是要拒绝其他客户端访问：&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;iptables -I DOCKER-USER -i &amp;lt;net interface&amp;gt; ! -s 100.84.94.62 -j DROP
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;此外，Docker 在重启之类的操作时候，会进行 iptables 相关规则的清理和重建，但是 DOCKER-USER 链中的规则可以持久化，不受影响。&lt;/p&gt;
 &lt;p&gt;具体的实现均在   &lt;code&gt;docker/libnetwork&lt;/code&gt; 下，以下是关于   &lt;code&gt;DOCKER-USER&lt;/code&gt; 链的相关代码：&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;const userChain = &amp;quot;DOCKER-USER&amp;quot;
func arrangeUserFilterRule() {
if ctrl == nil || !ctrl.iptablesEnabled() {
return
}
iptable := iptables.GetIptable(iptables.IPv4)
_, err := iptable.NewChain(userChain, iptables.Filter, false)
if err != nil {
logrus.Warnf(&amp;quot;Failed to create %s chain: %v&amp;quot;, userChain, err)
return
}
if err = iptable.AddReturnRule(userChain); err != nil {
logrus.Warnf(&amp;quot;Failed to add the RETURN rule for %s: %v&amp;quot;, userChain, err)
return
}
err = iptable.EnsureJumpRule(&amp;quot;FORWARD&amp;quot;, userChain)
if err != nil {
logrus.Warnf(&amp;quot;Failed to ensure the jump rule for %s: %v&amp;quot;, userChain, err)
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;可以看到链名称是固定在代码中的，同时会创建/确保链和规则存在。&lt;/p&gt;
 &lt;h3&gt;DOCKER-ISOLATION-STAGE-1/2 链&lt;/h3&gt;
 &lt;p&gt;DOCKER-ISOLATION-STAGE-1/2 这两条链作用类似，这里一起进行介绍。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;*filter
...
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
...
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
...
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;这两条链主要是分两个阶段进行了桥接网络隔离。所谓的桥接网络，通常就是指通过   &lt;code&gt;docker0&lt;/code&gt; 这个由 Docker 创建的接口的网络。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;/ # ifconfig docker0
docker0 Link encap:Ethernet HWaddr 02:42:11:31:97:0D
inet addr:172.18.0.1 Bcast:172.18.255.255 Mask:255.255.0.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;举个例子进行说明。&lt;/p&gt;
 &lt;p&gt;首先创建一个名为   &lt;code&gt;moelove&lt;/code&gt; 的 network，并查看它的 IP 。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;➜ ~ docker network create moelove
0d3d76dcf81fcf4b9d76ab5a7dec22737b115dddd593c73b27d27f0114cec1e2
➜ ~ docker run --rm -it --network moelove alpine
/ # hostname -i
172.22.0.2
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;然后分别使用默认的 network 和使用前面创建的 network 启动容器，来 ping 上述创建的容器 IP 。&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;➜ ~ docker run --rm -it alpine ping -c1 -w2 172.22.0.2
PING 172.22.0.2 (172.22.0.2): 56 data bytes
--- 172.22.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
➜ ~ docker run --rm -it --network moelove alpine ping -c1 -w2 172.22.0.2
PING 172.22.0.2 (172.22.0.2): 56 data bytes
64 bytes from 172.22.0.2: seq=0 ttl=64 time=0.092 ms
--- 172.22.0.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.092/0.092/0.092 ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;可以看到，如果是相同 network 的容器是可以 ping 成功的，但如果是不同 network 的容器则不能 ping 通。&lt;/p&gt;
 &lt;p&gt;DOCKER-ISOLATION-STAGE-1 会首先匹配来自桥接网络的网桥，目标是不同的接口，如果匹配到就进入 DOCKER-ISOLATION-STAGE-2，
不匹配就返回父链。&lt;/p&gt;
 &lt;p&gt;DOCKER-ISOLATION-STAGE-2 匹配目标是桥接网络的网桥，如果匹配，意味着数据包是来自于一个桥接网络的网桥，
目的地是另一个桥接网络的网桥，并将其 DROP 丢弃掉。不匹配则返回父链。&lt;/p&gt;
 &lt;p&gt;看到这里，你可能会问   &lt;strong&gt;为什么要分两个阶段进行隔离？用一条链直接隔离行不行？&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;答案是行，一条链也能隔离，Docker 很早的版本就是这样做的。&lt;/p&gt;
 &lt;p&gt;但是当时的实在超过 30 个 network 以后，就会导致 Docker 启动很慢。所以后来做了这个优化，
将这部分的复杂度从 O(N^2) 降低到 O(2N) ，Docker 就不再会出现启动慢的情况了。&lt;/p&gt;
 &lt;h3&gt;DOCKER 链&lt;/h3&gt;
 &lt;p&gt;最后我们来看看 DOCKER 链，这是 Docker 中使用最为频繁的一个链，也是规则最多的链，但它却很好理解。
通常情况下，如果不小心删掉了这个链的内容，可能会导致容器的网络出现问题，手动修复下，或者重启 Docker 均可解决。&lt;/p&gt;
 &lt;p&gt;这里我们启动一个容器，并进行端口映射，来看看会有哪些变化。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;(MoeLove) ➜ ~ docker exec -it $(docker ps -ql) sh
/ # docker run -p 6379:6379 --rm -d redis:alpine
Unable to find image &amp;apos;redis:alpine&amp;apos; locally
alpine: Pulling from library/redis
c158987b0551: Pull complete
1a990ecc86f0: Pull complete
f2520a938316: Pull complete
ae8c5b65b255: Pull complete
1f2628236ae0: Pull complete
329dd56817a5: Pull complete
Digest: sha256:518c024ec78b3074917bad2d40863e882e5297d65587e6d7c6e0b7281d9b8270
Status: Downloaded newer image for redis:alpine
6bf21bd3de78ce32617bf64a6a730c0fb50e304509a2ec3ef05ceae648334294
/ # docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6bf21bd3de78 redis:alpine &amp;quot;docker-entrypoint.s…&amp;quot; 9 seconds ago Up 8 seconds 0.0.0.0:6379-&amp;gt;6379/tcp friendly_spence
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;之后再次执行   &lt;code&gt;iptables-save&lt;/code&gt; ，对比当前的结果与上次的差别：&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt; *filter
+-A DOCKER -d 172.18.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 6379 -j ACCEPT
 *nat
+-A POSTROUTING -s 172.18.0.2/32 -d 172.18.0.2/32 -p tcp -m tcp --dport 6379 -j MASQUERADE
+-A DOCKER ! -i docker0 -p tcp -m tcp --dport 6379 -j DNAT --to-destination 172.18.0.2:6379
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;Docker 分别在   &lt;code&gt;filter&lt;/code&gt; 表和   &lt;code&gt;nat&lt;/code&gt; 表增加了规则。它的具体含义如下：&lt;/p&gt;
 &lt;p&gt;  &lt;code&gt;filter&lt;/code&gt; 表中新增的这条规则表示：在自定义的   &lt;code&gt;DOCKER&lt;/code&gt; 链中，对于目标地址是 172.18.0.2 且不是从   &lt;code&gt;docker0&lt;/code&gt; 进入的但从   &lt;code&gt;docker0&lt;/code&gt; 出去的，目标端口是 6379 的 TCP 协议则接收。&lt;/p&gt;
 &lt;p&gt;简单点来说就是放行通过   &lt;code&gt;docker0&lt;/code&gt; 流出的，目标为 172.18.0.2:6379 的 TCP 协议的流量。&lt;/p&gt;
 &lt;p&gt;  &lt;code&gt;nat&lt;/code&gt; 表中这两条规则的表示：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;为 172.18.0.2 上目标端口为 6379 的流量执行 MASQUERADE 动作（这里就简单的将它理解为 SNAT 也可以）；&lt;/li&gt;
  &lt;li&gt;在自定义的    &lt;code&gt;DOCKER&lt;/code&gt; 链中，如果入口不是    &lt;code&gt;docker0&lt;/code&gt; 并且目标端口是 6379 则进行 DNAT 动作，将目标地址转换为 172.18.0.2:6379 。简单点来说，这条规则就是为我们提供了 Docker 容器端口转发的能力，将访问主机本地 6379 端口流量的目标地址转换为 172.18.0.2:6379 。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;当然，要提供完整的访问能力，也需要和其他前面列出的其他规则共同配合才能完成。&lt;/p&gt;
 &lt;p&gt;此外，由于 Docker 中还存在多种不同的 network 驱动，在其他模式下还会有一些区别，需要注意。&lt;/p&gt;
 &lt;h2&gt;containerd 与 iptables&lt;/h2&gt;
 &lt;p&gt;随着 Kubernetes 中将 dockershim 彻底移除，已经有很多人将容器运行时切换到了 containerd，甚至有人希望把所有 Docker 环境都替换成 containerd。
但这里其实有一些需要注意的点，比如我们上述的示例，在 containerd 中实际上是无法进行端口映射（端口发布）的。&lt;/p&gt;
 &lt;p&gt;containerd 中可以通过类似上述 docker 的命令来启动相同的容器，比如：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;$ ctr run docker.io/library/redis:alpine redis-1
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;但它是没有   &lt;code&gt;-p&lt;/code&gt; 或者   &lt;code&gt;-P&lt;/code&gt; 参数的。所以这个端口发布的能力是 Docker 自己专门提供的。&lt;/p&gt;
 &lt;p&gt;如果确实想用这样的功能，怎么做呢？&lt;/p&gt;
 &lt;p&gt;一种方式是自己来管理 iptables 规则，但比较繁琐了。&lt;/p&gt;
 &lt;p&gt;另一种方式，推荐大家可以直接使用   &lt;a href="https://github.com/containerd/nerdctl"&gt;nerdctl&lt;/a&gt; 这是一个专为 containerd 做的，
兼容 Docker CLI 的工具。提供了很多远比默认的   &lt;code&gt;ctr&lt;/code&gt; 工具更丰富的能力。&lt;/p&gt;
 &lt;p&gt;比如可以这样：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;$ nerdctl run -d --name redis-1 -p 6379:6379 redis:alpine
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;获取其 IP 是 192.168.40.9， 然后检查 iptables 的规则：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;$ iptables -t nat -L | grep &amp;apos;192.168.40.9&amp;apos;
CNI-66888846605aa0cf860a0834 all -- 192.168.40.9 anywhere
DNAT tcp -- anywhere anywhere tcp dpt:redis to:192.168.40.9:6379
&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;发现有类似的规则，让它可以正常访问。&lt;/p&gt;
 &lt;h2&gt;总结&lt;/h2&gt;
 &lt;p&gt;本篇从 Docker 与 iptables 的关系将其，分别剖析了 Docker 启动后会创建的 iptables 规则及其含义。并通过示例介绍了 Docker 端口映射的实际原理，
以及如何利用 nerdctl 配合使用 containerd 进行端口映射。&lt;/p&gt;
 &lt;p&gt;容器的网络内容比较多，不过原理都是相通的，在 Kubernetes 中也包含了类似的内容。&lt;/p&gt;
 &lt;p&gt;好了，以上就是本篇的内容。&lt;/p&gt;
 &lt;p&gt;欢迎大家在评论区留言讨论，也请点赞再看，谢谢。&lt;/p&gt;
 &lt;hr&gt;&lt;/hr&gt;
 &lt;p&gt;欢迎订阅我的文章公众号【MoeLove】&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="TheMoeLove" src="https://gitee.com/tlrr/awesome/raw/master/2020-9-9/1599632564572-mp-qrcode.png"&gt;&lt;/img&gt;&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>post Linux Docker Kubernetes</category>
      <guid isPermaLink="true">https://itindex.net/detail/62542-%E5%AE%B9%E5%99%A8-%E7%BD%91%E7%BB%9C-iptables</guid>
      <pubDate>Mon, 12 Dec 2022 00:04:54 CST</pubDate>
    </item>
    <item>
      <title>Linux网络丢包排查 - 墨天轮</title>
      <link>https://itindex.net/detail/62475-linux-%E7%BD%91%E7%BB%9C-%E4%B8%A2%E5%8C%85</link>
      <description>&lt;div&gt;    &lt;p&gt;      &lt;strong&gt;&lt;/strong&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;一、简介&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;工作中遇到的服务器，最常用的操作系统就是linux系统，linux 系统使用网络适配器和外部进行数据交换。当在高速链路或异常环境下进行网络通信时，就有可能出现网络数据丢包现象，接下来我主要要说的是：网路丢包的故障定位思路和解决方法。&lt;/p&gt;    &lt;p&gt;      &lt;img src="https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211019_c4d1098e-30e0-11ec-8b07-fa163eb4f6be.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;二、相关原理介绍&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;1&lt;/strong&gt;      &lt;strong&gt;、网络消息的收发（报文收发过程）&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;在说丢包故障定位之前，我先来了介绍“网络报文收发过程”。本文以接收报文为例，发送报文与之类似，只是报文的传输方向相反。&lt;/p&gt;    &lt;p&gt;1、网络packet首先通过网线被网卡获取，网卡检查packet的crc正常后，去掉packet头得到frame，如果frame中MAC的目的地址为本机地址，则接受该报文，否则丢弃（在混杂模式下也会接收该报文）&lt;/p&gt;    &lt;p&gt;2、网卡将frame拷贝到网卡内部缓冲区中，一般是网卡的ring buffer中，拷贝完成后触发软中断通知内核处理&lt;/p&gt;    &lt;p&gt;3、内核从ring buffer中拷贝网络数据，并传递给网络协议栈进行解析&lt;/p&gt;    &lt;p&gt;4、协议栈解析完成后将数据放入ocket套接字的buffer中，最终传递给上层应用&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;2&lt;/strong&gt;      &lt;strong&gt;、相关名词解释&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;-&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;enp125s0f0:flags=4163  mtu 1500&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;inet90.90.160.163  netmask 255.255.252.0  broadcast 90.90.163.255&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;inet6fe80::903a:4e71:69cd:eb09  prefixlen 64  scopeid 0x20&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;ether08:4f:0a:04:85:ac  txqueuelen 1000  (Ethernet)&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;RXpackets 28356  bytes 4397271 (4.1 MiB)&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;RXerrors 0  dropped 15869  overruns 0  frame 0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;TXpackets 3003  bytes 450378 (439.8 KiB)&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;TXerrors 0  dropped 0 overruns 0  carrier 0  collisions 0&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;table&gt;      &lt;tr&gt;&lt;/tr&gt;&lt;/table&gt;    &lt;p&gt;RX errors：表示总的收包的错误数量&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;RX dropped：表示数据包已进入Ring buffer，但是由于系统原因(如内存不足)导致在拷贝到内存中的过程中被丢弃&lt;/p&gt;    &lt;p&gt;RX overruns：表示数据还未进入网卡缓存(Ring buffer)时就被丢弃了，一般是由于Ring buffer中的数据未被及时取出导致溢出，新来的数据只能被丢弃。例如CPU负载大，导致处理网卡数据的速度小于网卡接收数据的速度，Ring buffer溢出。&lt;/p&gt;    &lt;p&gt;RX frame：表示misaligend的frames数量&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;三、丢包故障定位与解决&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;1&lt;/strong&gt;      &lt;strong&gt;、网卡丢包&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;首先检查丢包是否是因为crc校验错误导致的：&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;[root@localhost ~]# ethtool -S enp1s0f0 | grep crc&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;rx_crc_errors_phy:0&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;p&gt;如果crc字段为非0，则表示网络报文在传输时出现了差错，此时可以更换线缆或网卡再做验证。&lt;/p&gt;    &lt;p&gt;如果丢包发生在网卡上，则可以通过ethtool -S eth0 | egrep-i drop|error确认&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;table&gt;      &lt;tr&gt;        &lt;td&gt;          &lt;br /&gt;&lt;/td&gt;        &lt;td&gt;          &lt;br /&gt;&lt;/td&gt;        &lt;td&gt;          &lt;br /&gt;&lt;/td&gt;        &lt;td&gt;          &lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;[root@localhost ~]# ethtool -S enp125s0f0 | egrep -ierror|drop&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;rxq#0_rx_dropped: 0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;rxq#0_errors: 0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;rx_oq_drop_pkt_cnt:0&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;p&gt;netstat -i也可以提供网卡的收发报文和丢包情况，正常情况下error、drop和overrun字段应该为0&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;p&gt;如果RX_OVR一直在增加，说明Ringbuffer有溢出，除了Ring Buffer太小以外，有可能是CPU处于高负荷下，来不及从Ring buffer中获取数据，此时可以检查CPU高负荷的原因，对网卡进行中断亲和设置等操作。通过查看/proc/net/dev也可以查看是否有Ring buffer满而导致的丢包&lt;/p&gt;    &lt;p&gt;[root@localhost~]# netstat -i&lt;/p&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;KernelInterface table&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;IfaceMTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp125s0f01500    29113      0  16149 0          3258      0      0      0 BMRU&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp125s0f11500        0      0      0 0             0      0      0      0 BMU&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp125s0f21500        0      0      0 0             0      0      0      0 BMU&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp125s0f31500        0      0      0 0             0      0      0      0 BMRU&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp1s0f01500        0      0      0 0             0      0      0      0 BMU&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;        &lt;br /&gt;&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;        &lt;br /&gt;&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp1s0f11500        0      0      0 0             0      0      0      0 BMU&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;lo65536     1820      0      0 0          1820      0      0      0 LRU&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;p&gt;如果硬件或者驱动没有问题，一般网卡丢包是由于Ring buffer太小导致，可以使用ethtool -G修改Ring buffer大小。&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;[root@localhost~]# cat proc/net/dev&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Inter-|Receive                                                |  Transmit&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;face|bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp125s0f1:0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;        &lt;br /&gt;&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;        &lt;br /&gt;&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp125s0f3:0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp125s0f2:0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp1s0f1:0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp1s0f0:0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;lo:169176    1948    0    0    0     0          0         0   169176    1948    0    0    0     0       0          0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;enp125s0f0:4880071   32037    0 18238    0     0          0     40408   486664    3302    0    0    0     0       0          0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;        &lt;br /&gt;&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;p&gt;       &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;2&lt;/strong&gt;      &lt;strong&gt;、内核丢包&lt;/strong&gt;其中的fifo字段统计的是Ringbuffer满而丢弃的包      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;内核从网卡收到数据以后，交给协议栈处理之前会有缓冲队列backlog，每个CPU都有一个backlog队列，当从网卡中获取数据到backlog中的速率大于从backlog中将数据交给协议栈的速率时就会发生溢出。可以查看/proc/net/softnet_stat文件确认是否有backlog溢出：&lt;/p&gt;    &lt;p&gt;-&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;[root@localhost~]# cat proc/net/softnet_stat&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0000000300000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0000000000000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0000000000000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0000000000000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0000000000000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0000000000000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0000000000000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;每一行代表一个CPU core接收数据的情况&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;第1列表示收到的包总数&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;第2列是丢弃的包计数，此处的丢包指的是从网卡Ring buffer中输出到内核缓存队列时，由于队列满了而丢弃的数据包&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;第3列表示软中断一次取走netdev_budget个数据包，或取数据包时间超过2ms的次数&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;第4列~第8列固定为0，没有意义&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;第9列表示发送数据包时，对应的队列被锁住的次数&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;如果是因为backlog队列溢出导致的丢包，可以修改backlog队列的大小，通过systctl修改netdev      &lt;em&gt;max&lt;/em&gt;backlog参数，默认大小为1000&lt;/p&gt;    &lt;p&gt;-&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;table&gt;      &lt;tr&gt;        &lt;td&gt;          &lt;p&gt; sysctl -w net.core.netdev_max_backlog=2000                &lt;br /&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;    &lt;p&gt;在将数据交给内核协议栈后，协议栈进行分析处理。在协议栈中也有可能丢包，通过netstat-s可以查看是否有协议栈丢包，-u参数指定udp协议，-t参数指定tcp协议，也可以加-c参数持续输出，看各个数据的变化，本文以UDP协议为例进行讲解&lt;/p&gt;    &lt;p&gt;-&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;[root@localhost~]# netstat -s -u&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;IcmpMsg:&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;InType3:1006&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;OutType3:1006&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Udp:&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0packetsreceived&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;1006packetsto unknown port received.&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0packetreceive errors&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;1081packetssent&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0receivebuffer errors&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;0sendbuffer errors&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;UdpLite:&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;IpExt:&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;InMcastPkts:3245&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;OutMcastPkts:11&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;InBcastPkts:6213&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;InOctets:2859135&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;OutOctets:633832&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;InMcastOctets:495247&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;OutMcastOctets:2658&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;InBcastOctets:2038580&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;InNoECTPkts:13895&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;[root@localhost~]#&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;packet receive errors表示接收有丢包&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;packets to unknown port received表示系统接收到的UDP报文的目标端口没有应用在监听，一般影响不严重&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;receive/send buffer errors表示收发队列太小导致的丢包数量&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;对于收发队列太小导致的丢包，可以通过调整收发队列参数来解决，系统默认的receive/sendbuffer大小如下：&lt;/p&gt;    &lt;p&gt;-&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;[root@localhost ~]# sysctlnet.core.rmem_default&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;net.core.rmem_default =229376&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;[root@localhost ~]# sysctlnet.core.wmem_default&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;net.core.wmem_default =229376&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;可以使用以下命令修改buffer大小&lt;/p&gt;    &lt;p&gt;-&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;sysctl-w net.core.rmem_max=26214400# 设置为 25M&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;sysctl -w net.core.wmem_max=26214400# 设置为 25M&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;通过查看/proc/net/snmp文件也可以查看各个协议的收发包情况：&lt;/p&gt;    &lt;p&gt;-&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;Ip: Forwarding DefaultTTL InReceives InHdrErrorsInAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequestsOutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKsFragFails FragCreates&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Ip: 2 64 14757 0 28 0 0 0 4844 5745 512 0 0 0 0 0 0 00&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Icmp: InMsgs InErrors InCsumErrors InDestUnreachsInTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoRepsInTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrorsOutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchosOutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Icmp: 1038 0 0 1038 0 0 0 0 0 0 0 0 0 0 1038 0 1038 00 0 0 0 0 0 0 0 0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;IcmpMsg: InType3 OutType3&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;IcmpMsg: 1038 1038&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpensPassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegsInErrs OutRsts InCsumErrors&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Tcp: 1 200 120000 -1 0 2 0 0 2 2768 3592 0 0 0 0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Udp: InDatagrams NoPorts InErrors OutDatagramsRcvbufErrors SndbufErrors InCsumErrors IgnoredMulti&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Udp: 0 1038 0 1113 0 0 0 0&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;UdpLite: InDatagrams NoPorts InErrors OutDatagramsRcvbufErrors SndbufErrors InCsumErrors IgnoredMulti&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;UdpLite: 0 0 0 0 0 0 0 0/&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;3&lt;/strong&gt;      &lt;strong&gt;、应用丢包&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;内核协议栈把接收到的报文放到socket套接字的buffer中，应用程序从buffer中不断读取报文。所以这里有两个和应用程序有关的因素会影响丢包：socket buffer的大小和应用程序报文读取速度。&lt;/p&gt;    &lt;p&gt;socket buffer大小可在应用程序初始化socket时设置，不过增大buffer的值会增加内存的使用，请根据实际情况配置；对于应用程序报文处理速度，应采用异步方式处理&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;四、其他定位方法&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;1&lt;/strong&gt;      &lt;strong&gt;、dropwatch&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;dropwatch可以输出数据包是在哪个内核函数中丢失的：&lt;/p&gt;    &lt;p&gt;-&lt;/p&gt;    &lt;p&gt;Bash代码&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;ul&gt;&lt;/ul&gt;    &lt;pre&gt;      &lt;code&gt;[root@localhost~]# dropwatch -l kas&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Initalizingkallsyms db&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;dropwatch&amp;gt;start&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Enablingmonitoring...&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;Kernelmonitoring activated.&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;IssueCtrl-C to stop monitoring&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;1drops at skb_queue_purge+20 (0xffff000008708d3c)&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;2drops at __netif_receive_skb_core+504(0xffff00000871bd7c)&lt;/code&gt;      &lt;br /&gt;      &lt;code&gt;1drops at __netif_receive_skb_core+504(0xffff00000871bd7c)&lt;/code&gt;      &lt;br /&gt;&lt;/pre&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62475-linux-%E7%BD%91%E7%BB%9C-%E4%B8%A2%E5%8C%85</guid>
      <pubDate>Thu, 27 Oct 2022 14:56:59 CST</pubDate>
    </item>
    <item>
      <title>Kubernetes网络难懂？快来看这篇文章</title>
      <link>https://itindex.net/detail/62307-kubernetes-%E7%BD%91%E7%BB%9C-%E6%96%87%E7%AB%A0</link>
      <description>&lt;div&gt;  &lt;p&gt;Kubernetes 是为运行分布式集群而建立的，分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分，了解 Kubernetes 网络模型可以使你能够正确运行、监控和排查应用程序故障。   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;img&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt;网络是非常复杂的，拥有许多概念，对于不熟悉这个领域的用户来说，这可能会有一定的难度，这里面有很多概念需要理解，并且还需要把这些概念整合起来形成一个连贯的整体，比如网络命名空间、虚拟接口、IP 转发、NAT 等概念。&lt;/p&gt;  &lt;p&gt;Kubernetes 中对任何网络实现都规定了以下的一些要求：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;所有 Pod 都可以在不使用 NAT 的情况下与所有其他 Pod 进行通信&lt;/li&gt;   &lt;li&gt;所有节点都可以在没有 NAT 的情况下与所有 Pod 进行通信&lt;/li&gt;   &lt;li&gt;Pod 自己的 IP 与其他 Pod 看到的 IP 是相同的&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;鉴于这些限制，我们需要解决几个不同的网络问题：&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;容器到容器的网络&lt;/li&gt;   &lt;li&gt;Pod 到 Pod 的网络&lt;/li&gt;   &lt;li&gt;Pod 到 Service 的网络&lt;/li&gt;   &lt;li&gt;互联网到 Service 的网络&lt;/li&gt;&lt;/ol&gt;  &lt;p&gt;接下来我们将来讨论这些问题及其解决方案。&lt;/p&gt;  &lt;h2&gt;容器到容器网络&lt;/h2&gt;  &lt;p&gt;通常情况下我们将虚拟机中的网络通信视为直接与以太网设备进行交互，如图1所示。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;图1.网络设备的理想视图  &lt;p&gt;实际的情况肯定比这要复杂，在 Linux 中，每个正在运行的进程都在一个网络命名空间内进行通信，该命名空间提供了一个具有自己的路由、防火墙规则和网络设备的逻辑网络栈，从本质上讲，网络命名空间为命名空间内的所有进程提供了一个全新的网络堆栈。&lt;/p&gt;  &lt;p&gt;Linux 用户可以使用    &lt;code&gt;ip&lt;/code&gt; 命令创建网络命名空间。例如，以下命令将创建一个名为 ns1 的网络命名空间。&lt;/p&gt;  &lt;pre&gt;   &lt;code&gt;$ ip netns add ns1     &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt;命名空间创建后，会在    &lt;code&gt;/var/run/netns&lt;/code&gt; 下面为其创建一个挂载点，即使没有附加任何进程，命名空间也是可以保留的。&lt;/p&gt;  &lt;p&gt;你可以通过列出    &lt;code&gt;/var/run/netns&lt;/code&gt; 下的所有挂载点或使用    &lt;code&gt;ip&lt;/code&gt; 命令来列出可用的命名空间。&lt;/p&gt;  &lt;pre&gt;   &lt;code&gt;$ ls /var/run/netns    &lt;br /&gt;ns1    &lt;br /&gt;$ ip netns    &lt;br /&gt;ns1    &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt;默认情况下，Linux 将为每个进程分配到 root network namespace，以提供访问外部的能力，如图2所示。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;图2.root network namespace  &lt;p&gt;对于 Docker 而言，一个 Pod 会被构建成一组共享网络命名空间的 Docker 容器，Pod 中的容器都有相同的 IP 地址和端口空间，它们都是通过分配给 Pod 的网络命名空间来分配的，并且可以通过 localhost 访问彼此，因为它们位于同一个命名空间中。这是使用 Docker 作为 Pod 容器来实现的，它持有网络命名空间，而应用容器则通过 Docker 的    &lt;code&gt;-net=container:sandbox-container&lt;/code&gt; 功能加入到该命名空间中，图3显示了每个 Pod 如何由共享网络命名空间内的多个 Docker 容器（   &lt;code&gt;ctr*&lt;/code&gt;）组成的。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;图3.每个 Pod 的网络命名空间  &lt;p&gt;此外 Pod 中的容器还可以访问共享卷，这些卷被定义为 Pod 的一部分，并且可以挂载到每个容器的文件系统中。&lt;/p&gt;  &lt;h2&gt;Pod 到 Pod 网络&lt;/h2&gt;  &lt;p&gt;在 Kubernetes 中，每个 Pod 都有一个真实的 IP 地址，每个 Pod 都使用该 IP 地址与其他 Pod 进行通信。接下来我们将来了解 Kubernetes 如何使用真实的 IP 来实现 Pod 与 Pod 之间的通信的。我们先来讨论同一节点上的 Pod 通信的方式。&lt;/p&gt;  &lt;p&gt;从 Pod 的角度来看，它存在于自己的网络命名空间中，需要与同一节点上的其他网络命名空间进行通信。值得庆幸的时候，命名空间可以使用 Linux 虚拟以太网设备或由两个虚拟接口组成的    &lt;code&gt;veth&lt;/code&gt; 对进行连接，这些虚拟接口可以分布在多个命名空间上。要连接 Pod 命名空间，我们可以将 veth 对的的一侧分配给 root network namespace，将另一侧分配给 Pod 的网络命名空间。每个 veth 对就像一根网线，连接两侧并允许流量在它们之间流动。这种设置可以复制到节点上的任意数量的 Pod。图4显示了连接虚拟机上每个 Pod 的 root network namespace 的 veth 对。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;图4.Pod 的 veth 对  &lt;p&gt;现在 Pod 都有自己的网络命名空间，这样它们就有自己的网络设备和 IP 地址，并且它们连接到节点的 root 命名空间，现在我们希望 Pod 能够通过 root 命名空间进行通信，那么我们将要使用一个网络    &lt;em&gt;bridge（网桥）&lt;/em&gt;来实现。&lt;/p&gt;  &lt;p&gt;Linux bridge 是用纯软件实现的虚拟交换机，有着和物理交换机相同的功能，例如二层交换，MAC 地址学习等。因此我们可以把 veth pair 等设备绑定到网桥上，就像是把设备连接到物理交换机上一样。bridge 的工作方式是通过检查通过它的数据包目的地，并决定是否将数据包传递给连接到网桥的其他网段，从而在源和目的地之间维护一个转发表。bridge 通过查看网络中每个以太网设备的唯一 MAC 地址来决定是桥接数据还是丢弃数据。&lt;/p&gt;  &lt;p&gt;Bridges 实现了 ARP 协议来发现与指定 IP 地址关联的链路层 MAC 地址。当 bridge 接收到数据帧的时候，bridge 将该帧广播给所有连接的设备（原始发送者除外），响应该帧的设备被存储在一个查找表中，未来具有相同 IP 地址的通信使用查找表来发现正确的 MAC 地址来转发数据包。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;图5.使用桥接连接命名空间  &lt;h3&gt;同节点 Pod 通信&lt;/h3&gt;  &lt;p&gt;网络命名空间将每个 Pod 隔离到自己的网络堆栈中，虚拟以太网设备将每个命名空间连接到根命名空间，以及一个将命名空间连接在一起的网桥，这样我们就准备好在同一节点上的 Pod 之间发送流量了，如下图6所示。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;同节点上的Pod间的数据包移动  &lt;p&gt;这上图中，pod1 向自己的网络设备    &lt;code&gt;eth0&lt;/code&gt; 发送了一个数据包，对于 pod1 来说，   &lt;code&gt;eth0&lt;/code&gt; 通过虚拟网络设备连接到 root netns 的    &lt;code&gt;veth0(1)&lt;/code&gt;，网桥    &lt;code&gt;cbr0&lt;/code&gt; 被配置为与    &lt;code&gt;veth0&lt;/code&gt; 一端相连，一旦数据包到达网桥，网桥就会使用 ARP 协议将数据包发送到    &lt;code&gt;veth1(3)&lt;/code&gt;。当数据包到达虚拟设备    &lt;code&gt;veth1&lt;/code&gt; 时，它被直接转发到 pod2 的命名空间内的    &lt;code&gt;eth0(4)&lt;/code&gt; 设备。这整个过程中，每个 Pod 仅与    &lt;code&gt;localhost&lt;/code&gt; 上的    &lt;code&gt;eth0&lt;/code&gt; 进行通信，流量就会被路由到正确的 Pod。&lt;/p&gt;  &lt;p&gt;Kubernetes 的网络模型决定了 Pod 必须可以通过其 IP 地址跨节点访问，也就是说，一个 Pod 的 IP 地址始终对网络中的其他 Pod 是可见的，每个 Pod 看待自己的 IP 地址的方式与其他 Pod 看待它的方式是相同的。接下来我们来看看不同节点上的 Pod 之间的流量路由问题。&lt;/p&gt;  &lt;h3&gt;跨节点 Pod 通信&lt;/h3&gt;  &lt;p&gt;在研究了如何在同一节点上的 Pod 之间路由数据包之后，接下来我们来看下不同节点上的 Pod 之间的通信。Kubernetes 网络模型要求 Pod 的 IP 是可以通过网络访问的，但它并没有规定必须如何来实现。&lt;/p&gt;  &lt;p&gt;通常集群中的每个节点都分配有一个    &lt;code&gt;CIDR&lt;/code&gt;，用来指定该节点上运行的 Pod 可用的 IP 地址。一旦以    &lt;code&gt;CIDR&lt;/code&gt; 为目的地的流量到达节点，节点就会将流量转发到正确的 Pod。图7展示了两个节点之间的网络通信，假设网络可以将    &lt;code&gt;CIDR&lt;/code&gt; 中的流量转发到正确的节点。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;图7.不同节点上的Pod间通信  &lt;p&gt;上图一样和图6相同的地方开始请求，但是这次目标 Pod（绿色标注）与源 Pod（蓝色标注）位于不同的节点上。数据包首先通过 pod1 的网络设备发送，该设备与 root netns（1）中的虚拟网络设备配对，最终数据包到达 root netns 的网桥（2）上。这个时候网桥上的 ARP 会失败，因为与网桥相连的没有正确的数据包 MAC 地址。一旦失败，网桥会将数据包发送到默认路由上 - root netns 的    &lt;code&gt;eth0&lt;/code&gt; 设备，此时就会路由离开节点，进入网络（3）。我们现在假设网络可以根据分配给节点的    &lt;code&gt;CIDR&lt;/code&gt; 将数据包路由到正确的节点（4）。数据包进入目标节点的 root netns（VM2 上的 eth0），这那里它通过网桥路由到正确的虚拟设备（5）。最后，路由通过位于 pod4 的命名空间（6）中的虚拟设备    &lt;code&gt;eth0&lt;/code&gt; 来完成。一般来说，每个节点都知道如何将数据包传递给其内部运行的 Pod，一旦数据包到达目标节点，数据包的流动方式与同一节点上的 Pod 间通信方式一样。&lt;/p&gt;  &lt;p&gt;我们这里没有介绍如何配置网络来将 Pod IPs 的流量路由到负责这些 IP 的正确节点，这和特定的网络有关系，比如 AWS 就维护了一个 Kubernetes 容器网络插件，该插件允许在 AWS 的 VPC 环境中使用 [容器网络接口（   &lt;code&gt;CNI&lt;/code&gt;）插件]（https://github.com/aws/amazon-vpc-cni-k8s）来进行节点到节点的网络通信。&lt;/p&gt;  &lt;p&gt;在 EC2 中，每个实例都绑定到一个弹性网络接口 (ENI)，并且所有 ENI 都连接在一个 VPC 内 —— ENI 无需额外操作即可相互访问。默认情况下，每个 EC2 实例部署一个 ENI，但你可以创建多个 ENI 并将它们部署到 EC2 实例上。Kubernetes 的 AWS CNI 插件会为节点上的每个 Pod 创建一个新的 ENI，因为 VPC 中的 ENI 已经连接到了现有 AWS 基础设施中，这使得每个 Pod 的 IP 地址可以在 VPC 内自然寻址。当 CNI 插件被部署到集群时，每个节点（EC2 实例）都会创建多个弹性网络接口，并为这些实例分配 IP 地址，从而为每个节点形成了一个    &lt;code&gt;CIDR&lt;/code&gt; 块。当部署 Pod 时，有一个小的二进制文件会作为 DaemonSet 部署到 Kubernetes 集群中，从节点本地的    &lt;code&gt;kubelet&lt;/code&gt; 进程接收任何添加 Pod 到网络的请求，这个二进制文件会从节点的可用 ENI 池中挑选一个可用的 IP 地址，并通过在 Linux 内核中连接虚拟网络设备和网桥将其分配给 Pod，和在同一节点内容的 Pod 通信一样，有了这个，Pod 的流量就可以跨集群内的节点进行通信了。&lt;/p&gt;  &lt;h2&gt;Pod 到 Service&lt;/h2&gt;  &lt;p&gt;上面我们已经介绍了如何在 Pod 和它们相关的 IP 地址之间的通信。但是 Pod 的 IP 地址并不是固定不变的，会随着应用的扩缩容、应用崩溃或节点重启而出现或消失，这些都可能导致 Pod IP 地址发生变化，Kubernetes 中可以通过    &lt;em&gt;Service&lt;/em&gt; 对象来解决这个问题。&lt;/p&gt;  &lt;p&gt;Kubernetes Service 管理一组 Pod，允许你跟踪一组随时间动态变化的 Pod IP 地址，Service 作为对 Pod 的抽象，为一组 Pod 分配一个虚拟的 VIP 地址，任何发往 Service VIP 的流量都会被路由到与其关联的一组 Pod。这就允许与 Service 相关的 Pod 集可以随时变更 - 客户端只需要知道 Service VIP 即可。&lt;/p&gt;  &lt;p&gt;创建 Service 时候，会创建一个新的虚拟 IP（也称为 clusterIP），这集群中的任何地方，发往虚拟 IP 的流量都将负载均衡到与 Service 关联的一组 Pod。实际上，Kubernetes 会自动创建并维护一个分布式集群内的负载均衡器，将流量分配到 Service 相关联的健康 Pod 上。接下来让我们仔细看看它是如何工作的。&lt;/p&gt;  &lt;h3&gt;netfilter 与 iptables&lt;/h3&gt;  &lt;p&gt;为了在集群中执行负载均衡，Kubernetes 会依赖于 Linux 内置的网络框架 -    &lt;code&gt;netfilter&lt;/code&gt;。Netfilter 是 Linux 提供的一个框架，它允许以自定义处理程序的形式实现各种与网络相关的操作，Netfilter 为数据包过滤、网络地址转换和端口转换提供了各种功能和操作，它们提供了引导数据包通过网络所需的功能，以及提供禁止数据包到达计算机网络中敏感位置的能力。&lt;/p&gt;  &lt;p&gt;   &lt;code&gt;iptables&lt;/code&gt; 是一个用户空间程序，它提供了一个基于 table 的系统，用于定义使用 netfilter 框架操作和转换数据包的规则。在 Kubernetes 中，iptables 规则由 kube-proxy 控制器配置，该控制器会 watch kube-apiserver 的变更，当对 Service 或 Pod 的变化更新了 Service 的虚拟 IP 地址或 Pod 的 IP 地址时，iptables 规则会被自动更新，以便正确地将指向 Service 的流量路由到支持 Pod。iptables 规则会监听发往 Service VIP 的流量，并且在匹配时，从可用 Pod 集中选择一个随机 Pod IP 地址，并且 iptables 规则将数据包的目标 IP 地址从 Service 的 VIP 更改为所选的 Pod IP。当 Pod 启动或关闭时，iptables 规则集也会更新以反映集群的变化状态。换句话说，iptables 已经在节点上做了负载均衡，以将指向 Service VIP 的流量路由到实际的 Pod 的 IP 上。&lt;/p&gt;  &lt;p&gt;在返回路径上，IP 地址来自目标 Pod，在这种情况下，iptables 再次重写 IP 头以将 Pod IP 替换为 Service 的 IP，以便 Pod 认为它一直只与 Service 的 IP 通信。&lt;/p&gt;  &lt;h3&gt;IPVS&lt;/h3&gt;  &lt;p&gt;Kubernetes 新版本已经提供了另外一个用于集群负载均衡的选项：IPVS， IPVS 也是构建在 netfilter 之上的，并作为 Linux 内核的一部分实现了传输层的负载均衡。IPVS 被合并到了 LVS（Linux 虚拟服务器）中，它在主机上运行并充当真实服务器集群前面的负载均衡器，IPVS 可以将基于 TCP 和 UDP 的服务请求定向到真实服务器，并使真实服务器的服务作为虚拟服务出现在一个 IP 地址上。这使得 IPVS 非常适合 Kubernetes 服务。&lt;/p&gt;  &lt;p&gt;这部署 kube-proxy 时，可以指定使用 iptables 或 IPVS 来实现集群内的负载均衡。IPVS 专为负载均衡而设计，并使用更高效的数据结构（哈希表），与 iptables  相比允许更大的规模。在使用 IPVS 模式的 Service 时，会发生三件事：在 Node 节点上创建一个虚拟 IPVS 接口，将 Service 的 VIP 地址绑定到虚拟 IPVS 接口，并为每个 Service VIP 地址创建 IPVS 服务器。&lt;/p&gt;  &lt;h3&gt;Pod 到 Service 通信&lt;/h3&gt;  &lt;img&gt;&lt;/img&gt;图8. Pod 与 Service 之间通信  &lt;p&gt;当这 Pod 和 Service 之间路由一个数据包时，流量和以前开始的方式一样，数据包首先通过连接到 Pod 的网络命名空间（1）的    &lt;code&gt;eth0&lt;/code&gt; 离开 Pod，。然后它通过虚拟网络设备到达网桥（2）。网桥上运行的 ARP 是不知道 Service 地址的，所以它通过默认路由    &lt;code&gt;eth0&lt;/code&gt;（3）将数据包传输出去。到这里会有一些不同的地方了，在    &lt;code&gt;eth0&lt;/code&gt; 接收之前，该数据包会被 iptables 过滤，在收到数据包后，iptables 使用 kube-proxy 在节点上安装的规则来响应 Service 或 Pod 事件，将数据包的目的地从 Service VIP 改写为特定的 Pod IP（4）。该数据包现在就要到达 pod4 了，而不是 Service 的 VIP，iptables 利用内核的    &lt;code&gt;conntrack&lt;/code&gt; 工具来记录选择的 Pod，以便将来的流量会被路由到相同的 Pod。从本质上讲，iptables 直接从节点上完成了集群内的负载均衡，然后流量流向 Pod，剩下的就和前面的 Pod 到 Pod 通信一样的了（5）。&lt;/p&gt;  &lt;h3&gt;Service 到 Pod 通信&lt;/h3&gt;  &lt;img&gt;&lt;/img&gt;图9.在 Service 和 Pod 之间通信  &lt;p&gt;相应的回包的时候，收到该数据包的 Pod 将响应，将源 IP 标记为自己的 IP，将目标 IP 标记为最初发送数据包的 Pod(1)。进入节点后，数据包流经 iptables，它使用    &lt;code&gt;conntrack&lt;/code&gt; 记住它之前所做的选择，并将数据包的源重写为 Service 的 VIP 而不是现在 Pod 的 IP(2)。从这里开始，数据包通过网桥流向与 Pod 的命名空间配对的虚拟网络设备 (3)，然后流向我们之前看到的 Pod 的虚拟网络设备 (4)。&lt;/p&gt;  &lt;h2&gt;外网到 Service 通信&lt;/h2&gt;  &lt;p&gt;到这里我们已经了解了 Kubernetes 集群内的流量是如何路由的，但是更多的时候我们需要将服务暴露到外部去。这个时候会涉及到两个主要的问题：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;将流量从 Kubernetes 服务路由到互联网上去&lt;/li&gt;   &lt;li&gt;将流量从互联网传到你的 Kubernetes 服务&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;接下来我们就来讨论这些问题。&lt;/p&gt;  &lt;h3&gt;出流量&lt;/h3&gt;  &lt;p&gt;从节点到公共 Internet 的路由流量也是和特定的网络有关系的，这取决于你的网络如何配置来发布流量的。这里我们以 AWS VPC 为例来进行说明。&lt;/p&gt;  &lt;p&gt;在 AWS 中，Kubernetes 集群在 VPC 中运行，每个节点都分配有一个私有 IP 地址，该地址可从 Kubernetes 集群内访问。要从集群外部访问服务，你可以在 VPC 上附加一个外网网关。外网网关有两个用途：在你的 VPC 路由表中为可路由到外网的流量提供目标，以及为已分配公共 IP 地址的实例执行网络地址转换 (NAT)。NAT 转换负责将集群节点的内部 IP 地址更改为公网中可用的外部 IP 地址。&lt;/p&gt;  &lt;p&gt;有了外网网关，VM 就可以自由地将流量路由到外网。不过有一个小问题，Pod 有自己的 IP 地址，与运行 Pod 的节点 IP 地址不同，并且外网网关的 NAT 转换仅适用于 VM IP 地址，因为它不知道哪些 Pod 在哪些 VM 上运行 —— 网关不支持容器。让我们看看 Kubernetes 是如何使用 iptables 来解决这个问题的。&lt;/p&gt;  &lt;p&gt;在下图中，数据包源自 Pod 的命名空间 (1)，并经过连接到根命名空间 (2) 的 veth 对。一旦进入根命名空间，数据包就会从网桥移动到默认设备，因为数据包上的 IP 与连接到网桥的任何网段都不匹配。在到达根命名空间的网络设备 (3) 之前，iptables 会破坏数据包 (3)。在这种情况下，数据包的源 IP 地址是 Pod，如果我们将源保留为 Pod，外网网关将拒绝它，因为网关 NAT 只了解连接到 VM 的 IP 地址。解决方案是   &lt;strong&gt;让 iptables 执行源 NAT&lt;/strong&gt; —— 更改数据包源，使数据包看起来来自 VM 而不是 Pod。有了正确的源 IP，数据包现在可以离开 VM (4) 并到达外网网关 (5) 了。外网网关将执行另一个 NAT，将源 IP 从 VM 内部 IP 重写为公网IP。最后，数据包将到达互联网上 (6)。在返回的路上，数据包遵循相同的路径，并且任何源 IP 的修改都会被取消，这样系统的每一层都会接收到它理解的 IP 地址：节点或 VM 级别的 VM 内部，以及 Pod 内的 Pod IP命名空间。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;图10.从Pod到互联网通信  &lt;h3&gt;入流量&lt;/h3&gt;  &lt;p&gt;让流量进入你的集群是一个非常难以解决的问题。同样这也和特定的网络环境有关系，但是一般来说入流量可以分为两种解决方案：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Service LoadBalancer&lt;/li&gt;   &lt;li&gt;Ingress 控制器&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;   &lt;strong&gt;LoadBalancer&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;当你创建一个 Kubernetes Service时，你可以选择指定一个 LoadBalancer 来使用它。LoadBalancer 有为你提供服务的云供应商负责创建负载均衡器，创建服务后，它将暴露负载均衡器的 IP 地址。终端用户可以直接通过该 IP 地址与你的服务进行通信。&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;LoadBalancer 到 Service&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在部署了 Service 后，你使用的云提供商将会为你创建一个新的 LoadBalancer（1）。因为 LoadBalancer 不支持容器，所以一旦流量到达 LoadBalancer，它就会分布在集群的各个节点上（2）。每个节点上的 iptables 规则会将来自 LoadBalancer 的传入流量路由到正确的 Pod 上（3）。从 Pod 到客户端的响应将返回 Pod 的 IP，但客户端需要有 LoadBalancer 的 IP 地址。正如我们之前看到的，iptables 和 conntrack 被用来在返回路径上正确重写 IP 地址。&lt;/p&gt;  &lt;p&gt;下图展示的就是托管 Pod 的三个节点前面的负载均衡器。传入流量（1）指向 Service 的 LoadBalancer，一旦 LoadBalancer 接收到数据包（2），它就会随机选择一个节点。我们这里的示例中，我们选择了没有运行 Pod 的节点 VM2（3）。在这里，运行在节点上的 iptables 规则将使用 kube-proxy 安装到集群中的内部负载均衡规则，将数据包转发到正确的 Pod。iptables 执行正确的 NAT 并将数据包转发到正确的 Pod（4）。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;图11.外网访问 Service  &lt;p&gt;   &lt;strong&gt;Ingress 控制器&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在七层网络上 Ingress 在 HTTP/HTTPS 协议范围内运行，并建立在 Service 之上。启用 Ingress 的第一步是使用 Kubernetes 中的 NodePort 类型的 Service，如果你将 Service 设置成 NodePort 类型，Kubernetes master 将从你指定的范围内分配一个端口，并且每个节点都会将该端口代理到你的 Service，也就是说，任何指向节点端口的流量都将使用 iptables 规则转发到 Service。&lt;/p&gt;  &lt;p&gt;将节点的端口暴露在外网，可以使用一个 Ingress 对象，Ingress 是一个更高级别的 HTTP 负载均衡器，它将 HTTP 请求映射到 Kubernetes Service。根据控制器的实现方式，Ingress 的使用方式会有所不同。HTTP 负载均衡器，和四层网络负载均衡器一样，只了解节点 IP（而不是 Pod IP），因此流量路由同样利用由 kube-proxy 安装在每个节点上的 iptables 规则提供的内部负载均衡。&lt;/p&gt;  &lt;p&gt;在 AWS 环境中，ALB Ingress 控制器使用 AWS 的七层应用程序负载均衡器提供 Kubernetes 入口。下图详细介绍了此控制器创建的 AWS 组件，它还演示了 Ingress 流量从 ALB 到 Kubernetes 集群的路由。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;图12.Ingress 控制器  &lt;p&gt;创建后，(1) Ingress Controller 会 watch 来自 Kubernetes APIServer 的 Ingress 事件。当它找到满足其要求的 Ingress 资源时，它会开始创建 AWS 资源。AWS 将 Application Load Balancer (ALB) (2) 用于 Ingress 资源。负载均衡器与用于将请求路由到一个或多个注册节点的 TargetGroup一起工作。(3) 在 AWS 中为 Ingress 资源描述的每个唯一 Kubernetes Service 创建 TargetGroup。(4) Listener 是一个 ALB 进程，它使用你配置的协议和端口检查连接请求。Listener 由 Ingress 控制器为你的 Ingress 资源中描述的每个端口创建。最后，为 Ingress 资源中指定的每个路径创建 TargetGroup 规则。这可以保证到特定路径的流量被路由到正确的 Kubernetes 服务上 (5)。&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;Ingress 到 Service&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;流经 Ingress 的数据包的生命周期与 LoadBalancer 的生命周期非常相似。主要区别在于 Ingress 知道 URL 的路径（可以根据路径将流量路由到 Service）Ingress 和节点之间的初始连接是通过节点上为每个服务暴露的端口。&lt;/p&gt;  &lt;p&gt;部署 Service 后，你使用的云提供商将为你创建一个新的 Ingress 负载均衡器 (1)。因为负载均衡器不支持容器，一旦流量到达负载均衡器，它就会通过为你的服务端口分布在组成集群 (2) 的整个节点中。每个节点上的 iptables 规则会将来自负载均衡器的传入流量路由到正确的 Pod (3)。Pod 到客户端的响应将返回 Pod 的 IP，但客户端需要有负载均衡器的 IP 地址。正如我们之前看到的，iptables 和 conntrack 用于在返回路径上正确重写 IP。&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;图13.从 Ingress 到 Service  &lt;h2&gt;总结&lt;/h2&gt;  &lt;p&gt;本文介绍了 Kubernetes 网络模型以及如何实现常见网络任务。网络知识点既广泛又很深，所以我们这里不可能涵盖所有的内容，但是你可以以本文为起点，然后去深入了解你感兴趣的主题。&lt;/p&gt;  &lt;p&gt;原文链接：https://sookocheff.com/post/kubernetes/understanding-kubernetes-networking-model&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;推荐阅读 点击标题可跳转  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483749&amp;idx=1&amp;sn=ae31929089c172e3517958506b965fd8&amp;chksm=ea18e825dd6f6133ef33e75e44ef2de766870b83174d90ad85e274467a5f58482d748c3205b1&amp;token=1662552961&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Docker是什么？》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483724&amp;idx=1&amp;sn=36d0814216e831d410db4eb4a70f0e83&amp;chksm=ea18e80cdd6f611a2af90234f587e23edaf1ea9cff9b8c1bb442d19eea463c5a2739a2d3f2e0&amp;token=1662552961&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Kubernetes是什么？》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483724&amp;idx=2&amp;sn=7868943b1a31fc7bc65c97110ecfc97e&amp;chksm=ea18e80cdd6f611acfea08392e87b1cfc79791b4eafa0e88607b53ab67f2e4f80891324b9a06&amp;token=1662552961&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Kubernetes和Docker到底有啥关系？》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483866&amp;idx=1&amp;sn=6aaa877352f533358480aabc37021f72&amp;chksm=ea18e89add6f618c474627e635c2bf74a049704e585736041138c43a03230ef573c29ae81fc2&amp;token=2047901948&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《教你如何快捷的查询选择网络仓库镜像tag》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483747&amp;idx=1&amp;sn=fb2065fdc327cbdcfd2f2ab06536b5a9&amp;chksm=ea18e823dd6f613543b2cd1983b635ed0eb419caf1418a76f00c546b9b609647ad11e3ee94c8&amp;token=1662552961&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Docker镜像进阶：了解其背后的技术原理》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483813&amp;idx=1&amp;sn=ea95eeafb5598cab925b13e4fb308172&amp;chksm=ea18e8e5dd6f61f3c7708dd441d2909193ac437923b0006ded6a3acac95ae08c3e97d56db605&amp;token=92043779&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《教你如何修改运行中的容器端口映射》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483903&amp;idx=1&amp;sn=acfe1eae0a0e25d5338a43f7b9eb5732&amp;chksm=ea18e8bfdd6f61a9428784e5985c6706f5e99f25e1ee1fba4d9efde1b31d97aa09d34ba9d4dc&amp;token=2123136639&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《k8s学习笔记：介绍&amp;amp;上手》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483928&amp;idx=1&amp;sn=db9f1214381dd5cedec84b9533a69f4c&amp;chksm=ea18eb58dd6f624e3f12a4c867aa58d1cbece7bf6e537c94cc9eec9ccc8ae0680cd011567a34&amp;token=1315810181&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《k8s学习笔记：缩扩容&amp;amp;更新》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483753&amp;idx=1&amp;sn=7a48dc98ccf25adf42420a552bddeb45&amp;chksm=ea18e829dd6f613f4de7dd5f86b3883d276501841fcf17b35c38aa41cbb81fb6edb22411188b&amp;token=1662552961&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Docker 基础用法和命令帮助》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483933&amp;idx=1&amp;sn=997ba9c8b840426f80406c0f785f8b9b&amp;chksm=ea18eb5ddd6f624b3467ab6b258cb018380f68ffcf321eb92324c77d03aa79d3cf360cbf3866&amp;token=293543975&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《在K8S上搭建Redis集群》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483938&amp;idx=1&amp;sn=94e070f429b8dfdab3c29121ecd89e67&amp;chksm=ea18eb62dd6f6274d13e6217ea70b41d12993aeceb1b4955a36c7cd3547deecc16c4d36d22e3&amp;token=845656495&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《灰度部署、滚动部署、蓝绿部署》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483968&amp;idx=1&amp;sn=246d0de27f6ac8d6097eab60ffedbb1e&amp;chksm=ea18eb00dd6f6216f4798bf11df26083dfced24294456f5137f07c38c995905336b9137eebfb&amp;token=1908076881&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《PM2实践指南》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483972&amp;idx=1&amp;sn=c28354c7968940d824690e8a8ddfb3ef&amp;chksm=ea18eb04dd6f621246cd4bff08fad70a305e2e54f24b01f45096f8882da4249f812069e31f7c&amp;token=1435050357&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Docker垃圾清理》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483976&amp;idx=1&amp;sn=12372df6b289c2195ea6f3ab0f384f02&amp;chksm=ea18eb08dd6f621ebc87c4606b4e6928352ec0bb614c394e1b92758bd27537e3919d1b126536&amp;token=1435050357&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Kubernetes(k8s)底层网络原理刨析》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247483976&amp;idx=1&amp;sn=12372df6b289c2195ea6f3ab0f384f02&amp;chksm=ea18eb08dd6f621ebc87c4606b4e6928352ec0bb614c394e1b92758bd27537e3919d1b126536&amp;token=1435050357&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《容器环境下Node.js的内存管理》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484008&amp;idx=1&amp;sn=ab4aa79f9d6abf1c921a3e2186ea8475&amp;chksm=ea18eb28dd6f623e6e7ce0f6aa80980b5087f5bc493050498e575b5dfdbbe775305c5014b3f4&amp;token=1264335813&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《MySQL 快速创建千万级测试数据》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484016&amp;idx=1&amp;sn=581e35ac3f8261886d42ee0d4530c68d&amp;chksm=ea18eb30dd6f6226312e6df45ade7eb7c4664e45b32e2fec498676d41b383c32a2c9fec608b1&amp;token=1264335813&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Linux 与 Unix 到底有什么不同？》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484025&amp;idx=1&amp;sn=0c4c13a6e713b4c2ffd0ffb908d2e3e2&amp;chksm=ea18eb39dd6f622f8c3f8acf89801dbc2de0058bf21aa16be0456224dd889313916a568a3a98&amp;token=898571997&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《浅谈几种常见 RAID 的异同》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484043&amp;idx=1&amp;sn=55c9bd30daffc67fec5be25e5bbb8f46&amp;chksm=ea18ebcbdd6f62dd050259eb46012401b83adfd46adca5e3e5b15c711f3c001e10d5c6773f76&amp;token=1374986981&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Git 笔记-程序员都要掌握的 Git》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484048&amp;idx=1&amp;sn=49f970d4421cfd8783808c9d63379074&amp;chksm=ea18ebd0dd6f62c68988bfb894d4e4d9e9bdc2d0d44595f5a98d2df59debfec5ea43541c23d1&amp;token=1376660398&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《老司机必须懂的MySQL规范》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484061&amp;idx=1&amp;sn=1c73e0bd6a437a00b1a24fd5e884118f&amp;chksm=ea18ebdddd6f62cbec87fd77b26f4b6bf65891aeee9b4aebf4c84f7500dd091dc41f5e6ab0a5&amp;token=351630413&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Docker中Image、Container与Volume的迁移》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484075&amp;idx=1&amp;sn=0e7ffa8cfa672da587e0ea146e443c4f&amp;chksm=ea18ebebdd6f62fda74091cb9b74af311b1e6be34a248a8d47926674d3dbb5e7817d66632bfe&amp;token=1669482947&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《漫画|如何用Kubernetes搞定CICD》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484107&amp;idx=1&amp;sn=20a051c56622e9cd71f18f81e80be999&amp;chksm=ea18eb8bdd6f629dd8e291c3f4a8518e856695b60caf58f6482a5ae2edf636a83969cff045a3&amp;token=1565146668&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《写给前端的Docker实战教程》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484130&amp;idx=1&amp;sn=3499ae3a251e0f2599db839750a3de14&amp;chksm=ea18eba2dd6f62b445631a5ba120e58b8e2012f7edc88313a51937c470f629a1a7c2d1547a5e&amp;token=1930773406&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《Linux 操作系统知识地图2.0，我看行》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484139&amp;idx=1&amp;sn=707150be4352b3750b2284d99f452a7a&amp;chksm=ea18ebabdd6f62bde1fa4c64b7b1bdac944c4eb7af164f1e946f82f72cedf19b898ea96d9fda&amp;token=1885905392&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《16个概念带你入门 Kubernetes》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484155&amp;idx=1&amp;sn=9238791b24ee68d82cce8cfb98f2db12&amp;chksm=ea18ebbbdd6f62ad42363346a5876ec33e6debc7757744ec39fc90b288c4114ed316d204fefc&amp;token=2089224243&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《程序员因接外包坐牢456天，长文叙述心酸真实经历》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484166&amp;idx=1&amp;sn=3a1dc941960ae6a2b17c86d60fe7f68e&amp;chksm=ea18ea46dd6f6350b9a6f0e3eca70dd4dc4b66b69e9ff2bd56f02c92e14c5ee48cbb8ffb7e6b&amp;token=687868509&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《IT 行业老鸟，有话对你说》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484191&amp;idx=1&amp;sn=8213cd463e5448dc46cbac2dca9ccaa7&amp;chksm=ea18ea5fdd6f63496e36a8147a7e62c36e8f4bc36c10e1876f8d3fc1f4f5e885351d021c99c4&amp;token=1075485654&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;《HTTPS 为什么是安全的？&lt;/a&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484191&amp;idx=1&amp;sn=8213cd463e5448dc46cbac2dca9ccaa7&amp;chksm=ea18ea5fdd6f63496e36a8147a7e62c36e8f4bc36c10e1876f8d3fc1f4f5e885351d021c99c4&amp;token=1075485654&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;说一下他的底层实现原理？&lt;/a&gt;   &lt;a href="https://mp.weixin.qq.com/s?__biz=MzI1NzI5NDM4Mw==&amp;mid=2247484191&amp;idx=1&amp;sn=8213cd463e5448dc46cbac2dca9ccaa7&amp;chksm=ea18ea5fdd6f63496e36a8147a7e62c36e8f4bc36c10e1876f8d3fc1f4f5e885351d021c99c4&amp;token=1075485654&amp;lang=zh_CN&amp;scene=21#wechat_redirect" target="_blank"&gt;》&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;hr&gt;&lt;/hr&gt;  &lt;p&gt;免责声明：本文内容来源于网络，所载内容仅供参考。转载仅为学习和交流之目的，如无意中侵犯您的合法权益，请及时联系Docker中文社区！&lt;/p&gt;  &lt;hr&gt;&lt;/hr&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;img&gt;&lt;/img&gt;  &lt;p&gt;   &lt;img&gt;&lt;/img&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>dev</category>
      <guid isPermaLink="true">https://itindex.net/detail/62307-kubernetes-%E7%BD%91%E7%BB%9C-%E6%96%87%E7%AB%A0</guid>
      <pubDate>Sun, 19 Jun 2022 00:00:00 CST</pubDate>
    </item>
    <item>
      <title>基于 eBPF 的开源项目 eCapture 介绍：无需 CA 证书抓 https 网络明文通讯</title>
      <link>https://itindex.net/detail/62301-ebpf-%E5%BC%80%E6%BA%90-%E9%A1%B9%E7%9B%AE</link>
      <description>&lt;p&gt;  &lt;img&gt;&lt;/img&gt;&lt;/p&gt; &lt;h1&gt;eCapture 介绍&lt;/h1&gt; &lt;p&gt;eCapture 是一款基于 eBPF 技术实现的用户态数据捕获工具。不需要 CA 证书，即可捕获 https/tls 的通讯明文。  &lt;img&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;项目在 2022 年 3 月中旬创建，一经发布，广受大家喜爱，至今不到两周已经 1200 多个 Star。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;h2&gt;作用&lt;/h2&gt; &lt;ol&gt;  &lt;li&gt;不需要 CA 证书，即可捕获 HTTPS/TLS 通信数据的明文。&lt;/li&gt;  &lt;li&gt;在 bash 审计场景，可以捕获 bash 命令。&lt;/li&gt;  &lt;li&gt;数据库审计场景，可以捕获 mysqld/mariadDB 的 SQL 查询。&lt;/li&gt;&lt;/ol&gt; &lt;h2&gt;官网&lt;/h2&gt; &lt;p&gt;代码仓库见：https://github.com/ehids/ecapture ，也可以关注微信公众号「榫卯江湖」获取最新动态。&lt;/p&gt; &lt;h1&gt;产品架构&lt;/h1&gt; &lt;p&gt;eCapture 系统用户态程序使用 Golang 语言开发，具有良好的系统兼容性，无依赖快速部署，更适合云原生场景。内核态代码使用 C 编写，使用 clang/llvm 编译，生产 bpf 字节码后，采用   &lt;code&gt;go-bindata&lt;/code&gt; 转化为 golang 语法文件，之后采用   &lt;code&gt;ehids/ebpfmanager&lt;/code&gt; 类库，调用 bpf syscall 进行加载、HOOK、map 读取。golang 编译后，无其他任何依赖即可运行，兼容 linux kernel 4.18 以上所有版本。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;h2&gt;eBPF 加载机制&lt;/h2&gt; &lt;p&gt;关于 eBPF 详细加载机制，可到 https://ebpf.io/ 查阅相关原理。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;h2&gt;实现原理&lt;/h2&gt; &lt;p&gt;如工作原理的图所示，在用户态的加密解密函数中下钩子。tcpdump (libpcap) 是在数据包接收到，XDP 处理后，进行   &lt;code&gt;clone packet&lt;/code&gt;，进行包的复制，发送给用户态进程。二者工作的所在层不一样。&lt;/p&gt; &lt;h1&gt;功能介绍&lt;/h1&gt; &lt;p&gt;eCapture 有三个模块&lt;/p&gt; &lt;ol&gt;  &lt;li&gt;tls/ssl 明文数据捕获&lt;/li&gt;  &lt;li&gt;bash 命令审计&lt;/li&gt;  &lt;li&gt;mysqld 数据库审计&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;第一个功能适用于基于 tls/ssl 解密需求的运维监控、故障排查、抽样分析场景。&lt;/p&gt; &lt;p&gt;第二个功能适用于安全领域的 bash 入侵发现场景，这里只是简单的功能，可以在此基础上增加其他功能。&lt;/p&gt; &lt;p&gt;第三个功能适用于数据库审计场景，尤其是做数据安全、数据防泄漏，甚至入侵检测等。同样，可以在此基础上扩充其他功能。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;查看其使用说明，如下&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;cfc4n@vm-desktop:~/ehids/ecapture$ ./bin/ecapture   &lt;br /&gt;NAME:   &lt;br /&gt; ecapture - capture text SSL content without CA cert by ebpf hook.   &lt;br /&gt;   &lt;br /&gt;USAGE:   &lt;br /&gt; ecapture [flags]   &lt;br /&gt;   &lt;br /&gt;VERSION:   &lt;br /&gt; 0.1.5-20220325-47edbed   &lt;br /&gt;   &lt;br /&gt;COMMANDS:   &lt;br /&gt; bash  capture bash command   &lt;br /&gt; help  Help about any command   &lt;br /&gt; mysqld56 capture sql queries from mysqld &amp;gt;5.6 .   &lt;br /&gt; tls  alias name:openssl , use to capture tls/ssl text content without CA cert.   &lt;br /&gt;   &lt;br /&gt;DESCRIPTION:   &lt;br /&gt; ecapture是一款无需安装CA证书，即可抓去HTTPS、TLS等明文数据包的工具。   &lt;br /&gt; 也可以捕获bash的命令，适用于安全审计场景。包括mysqld的数据库审计等。   &lt;br /&gt; 仓库地址: https://github.com/ehids/ecapture   &lt;br /&gt;   &lt;br /&gt;OPTIONS:   &lt;br /&gt;      --debug[=false] enable debug logging   &lt;br /&gt;  -h, --help[=false] help for ecapture   &lt;br /&gt;      --hex[=false] print byte strings as hex encoded strings   &lt;br /&gt;  -p, --pid=0  if target_pid is 0 then we target all pids   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;其中，有四个全局参数，分别是&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;--debug ， 用于启动调试日志&lt;/li&gt;  &lt;li&gt;--help  ， 查看帮助&lt;/li&gt;  &lt;li&gt;--hex ，按照 hex 模式打印字符，用于查看不可见字符&lt;/li&gt;  &lt;li&gt;--pid ，用于针对特定进程进行数据捕获&lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;HOOK 机制&lt;/h2&gt; &lt;p&gt;eCapture 采用 eBPF uprobe 相关函数进行 HOOK，故需要目标用户态函数信息，包含函数符号表 (symbol table)，函数偏移地址 (offset)。在大部分 linux 发行版中，使用的二进制可执行文件 (ELF) 都是包含符号表的；少部分发行版，会去掉 ELF 中的符号表。那么针对这种场景，就需要用户自行定位目标函数所在 ELF/SO 中的偏移地址，通过工具的参数来指定。&lt;/p&gt; &lt;p&gt;对于 ELF 文件，可以将目标类库静态编译到自身，也可以通过动态链接库的方式引用。那么对于这两种形式，eCapture 根据不同场景进行自动查找。若查找不到，用户可以通过命令行参数指定。&lt;/p&gt; &lt;p&gt;故 eCapture 支持   &lt;code&gt;HOOK ELF&lt;/code&gt;，以及   &lt;code&gt;HOOK SO&lt;/code&gt; 两种模式。会自动分析 ELF 文件，读取  &lt;code&gt;.dynamic&lt;/code&gt; 和  &lt;code&gt;.dynsym&lt;/code&gt; 等段信息，查找相关链接库名以及函数名、偏移地址。&lt;/p&gt; &lt;p&gt;查找原理如下图：&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;h2&gt;tls/ssl&lt;/h2&gt; &lt;p&gt;  &lt;code&gt;ecapture tls&lt;/code&gt; 命令用于启动 tls/ssl 模块，支持了三类 tls/ssl 加密类库，分别是&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;openssl ，动态链接库名字为    &lt;code&gt;libssl.so&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;gnutls ，动态链接库名字为    &lt;code&gt;libgnutls.so&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;nss/nspr ，动态链接库名字为    &lt;code&gt;libnspr4.so&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;在不同的 linux 发行版中，因为各种原因，会选择不同的类库。比如   &lt;code&gt;wget&lt;/code&gt; 程序，在 ubuntu 跟 centos 中就会使用不同的类库。有的是   &lt;code&gt;openssl&lt;/code&gt;，有的是   &lt;code&gt;gnutls&lt;/code&gt;，甚至两个库都引入了。&lt;/p&gt; &lt;p&gt;具体情况，你可以使用   &lt;code&gt;ldd $ELF_PATH | grep -E &amp;quot;tls|ssl|nspr|nss&amp;quot;&lt;/code&gt; 来查看一个 ELF 文件使用类库情况。&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;cfc4n@vm-desktop:~$ ldd `which wget` |grep -E &amp;quot;tls|ssl|nspr|nss&amp;quot;   &lt;br /&gt; libssl.so.1.1 =&amp;gt; /lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f50699f6000)   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;对于 firefox、chrome 这种进程，需要在程序启动后才能看到 tls 类库依赖情况，那么，你可以使用   &lt;code&gt;sudo pldd $PID | grep -E &amp;quot;tls|ssl|nspr|nss&amp;quot;&lt;/code&gt; 来查看&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;cfc4n@vm-desktop:~$ ps -ef|grep firefox   &lt;br /&gt;cfc4n       6846    1432 45 17:50 ?        00:00:04 /usr/lib/firefox/firefox -new-window   &lt;br /&gt;cfc4n@vm-desktop:~$ sudo pldd 6846 |grep -E &amp;quot;tls|ssl|nspr|nss&amp;quot;   &lt;br /&gt;/usr/lib/firefox/libnspr4.so   &lt;br /&gt;/usr/lib/firefox/libnssutil3.so   &lt;br /&gt;/usr/lib/firefox/libnss3.so   &lt;br /&gt;/usr/lib/firefox/libssl3.so   &lt;br /&gt;/lib/x86_64-linux-gnu/libnss_files.so.2   &lt;br /&gt;/lib/x86_64-linux-gnu/libnss_mdns4_minimal.so.2   &lt;br /&gt;/lib/x86_64-linux-gnu/libnss_dns.so.2   &lt;br /&gt;/usr/lib/firefox/libnssckbi.so   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;eCapture 的 tls 模块命令行参数如下，用户可以使用默认配置外，也可以根据自己环境自行指定。&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;OPTIONS:   &lt;br /&gt;      --curl=&amp;quot;&amp;quot;  curl or wget file path, use to dectet openssl.so path, default:/usr/bin/curl   &lt;br /&gt;      --firefox=&amp;quot;&amp;quot; firefox file path, default: /usr/lib/firefox/firefox.   &lt;br /&gt;      --gnutls=&amp;quot;&amp;quot; libgnutls.so file path, will automatically find it from curl default.   &lt;br /&gt;  -h, --help[=false] help for tls   &lt;br /&gt;      --libssl=&amp;quot;&amp;quot; libssl.so file path, will automatically find it from curl default.   &lt;br /&gt;      --nspr=&amp;quot;&amp;quot;  libnspr44.so file path, will automatically find it from curl default.   &lt;br /&gt;      --wget=&amp;quot;&amp;quot;  wget file path, default: /usr/bin/wget.   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;同时，使用方法也比较简单，  &lt;code&gt;./ecapture tls --hex&lt;/code&gt; 命令即可。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;在 linux 上，firefox 程序中，有很多通讯都使用了   &lt;code&gt;/usr/lib/firefox/libnspr4.so&lt;/code&gt;，但实际上业务请求是可以通过   &lt;code&gt;Socket Thread&lt;/code&gt; 进程来发送的。可以通过这个特点来过滤，对于 chrome 程序，相信细心的你，也能搞定。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;h2&gt;bash&lt;/h2&gt; &lt;p&gt;笔者在安全部门工作，接到过 bash 审计需求，其实现方法无非是修改系统类库、使用内核模块等技术实现，对系统稳定性有一定风险。基于 eBPF 技术实现，可以避开这些问题。这里的 bash 命令的监控，是作为 eBPF 技术在安全审计场景中的一个探索。&lt;/p&gt; &lt;p&gt;eCapture 在实现时首先查找 ENV 的 $SHELL 值，作为 bash 的二进制文件路径进行 HOOK。对于 bash 加载了   &lt;code&gt;libreadline.so&lt;/code&gt; 的场景，也会自动分析，进行符号表查找、offset 定位，再进行 HOOK。&lt;/p&gt; &lt;p&gt;bash 模块的参数有三个，用户可以自定义   &lt;code&gt;bash&lt;/code&gt;、  &lt;code&gt;readlineso&lt;/code&gt; 的路径。&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;OPTIONS:   &lt;br /&gt;      --bash=&amp;quot;&amp;quot;  $SHELL file path, eg: /bin/bash , will automatically find it from $ENV default.   &lt;br /&gt;  -h, --help[=false] help for bash   &lt;br /&gt;      --readlineso=&amp;quot;&amp;quot; readline.so file path, will automatically find it from $BASH_PATH default.   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;img&gt;&lt;/img&gt; &lt;h2&gt;mysql/mariadb&lt;/h2&gt; &lt;p&gt;与 bash 模块一样，也是作为数据库审计的一个探索。笔者环境为 ubuntu 12.04，mysqld 也因为协议关系，使用了衍生的   &lt;code&gt;MariadDB&lt;/code&gt;，用户也可以根据自己实际场景，使用命令行参数进行指定。&lt;/p&gt; &lt;p&gt;mysqld 模块，核心原理是 HOOK 了   &lt;code&gt;dispatch_command&lt;/code&gt; 函数，&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;第一个参数为 CMD 类型，值为 COM_QUERY 时，为查询场景，即审计需求的查询类型。&lt;/li&gt;  &lt;li&gt;第二个参数是 THD 的结构体，在这里我们用不到。&lt;/li&gt;  &lt;li&gt;第三个是查询的 SQL 语句&lt;/li&gt;  &lt;li&gt;第四个参数是 SQL 语句的长度，&lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;// https://github.com/MariaDB/server/blob/b5852ffbeebc3000982988383daeefb0549e058a/sql/sql_parse.h#L112   &lt;br /&gt;dispatch_command_return dispatch_command(enum enum_server_command command, THD *thd,   &lt;br /&gt;   char* packet, uint packet_length, bool blocking = true);   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;mysqld 审计模块参数如下:&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;OPTIONS:   &lt;br /&gt;  -f, --funcname=&amp;quot;&amp;quot;   function name to hook   &lt;br /&gt;  -h, --help[=false]   help for mysqld56   &lt;br /&gt;  -m, --mysqld=&amp;quot;/usr/sbin/mariadbd&amp;quot; mysqld binary file path, use to hook   &lt;br /&gt;      --offset=0   0x710410   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;其中，  &lt;code&gt;--mysqld&lt;/code&gt; 是用来指定 mysqld 的路径。mysqld 二进制程序符号表里虽然有   &lt;code&gt;dispatch_command&lt;/code&gt; 信息，但   &lt;code&gt;dispatch_command&lt;/code&gt; 这个函数名每次编译都是变化的，故不能写死。&lt;/p&gt; &lt;p&gt;eCapture 的查找方式是读取 mysqld 二进制的  &lt;code&gt;.dynamic&lt;/code&gt; 段信息，正则语法   &lt;code&gt;\w+dispatch_command\w+&lt;/code&gt; 去匹配所有符号信息，找到其函数名、偏移地址，再使用。&lt;/p&gt; &lt;p&gt;你也可以通过 objdump 命令来查找，再通过命令行参数自行指定 funcname。&lt;/p&gt; &lt;blockquote&gt;  &lt;p&gt;mariadbd version : 10.5.13-MariaDB-0ubuntu0.21.04.1 objdump -T /usr/sbin/mariadbd |grep dispatch_command 0000000000710410 g    DF .text 0000000000002f35  Base        _Z16dispatch_command19enum_server_commandP3THDPcjbb&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;即 offset 为 0x710410，函数名为  &lt;code&gt;_Z16dispatch_command19enum_server_commandP3THDPcjbb&lt;/code&gt;。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;h2&gt;使用&lt;/h2&gt; &lt;h3&gt;下载二进制包&lt;/h3&gt; &lt;p&gt;eCapture 发布在 https://github.com/ehids/ecapture/releases ，目前最新版为   &lt;code&gt;eCapture v0.1.5&lt;/code&gt;。&lt;/p&gt; &lt;p&gt;可在 linux kernel 4.18 以上版本运行。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;二进制包地址：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;https://github.com/ehids/ecapture/releases/download/v0.1.5/ecapture_v0.1.5.zip&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;国内加速地址：&lt;/strong&gt;https://github.do/https://github.com/ehids/ecapture/releases/download/v0.1.5/ecapture_v0.1.5.zip&lt;/p&gt; &lt;h3&gt;自行编译&lt;/h3&gt; &lt;p&gt;代码仓库在 https://github.com/ehids/ecapture ，你可以自行修改源码编译。&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>dev</category>
      <guid isPermaLink="true">https://itindex.net/detail/62301-ebpf-%E5%BC%80%E6%BA%90-%E9%A1%B9%E7%9B%AE</guid>
      <pubDate>Sun, 12 Jun 2022 00:00:00 CST</pubDate>
    </item>
    <item>
      <title>Kubernetes容器网络及Flannel插件详解</title>
      <link>https://itindex.net/detail/62284-kubernetes-%E5%AE%B9%E5%99%A8-%E7%BD%91%E7%BB%9C</link>
      <description>&lt;hr&gt;&lt;/hr&gt;
 &lt;h2&gt;theme: smartblue
highlight: a11y-dark&lt;/h2&gt;
 &lt;p&gt;持续创作，加速成长！这是我参与「掘金日新计划 · 6 月更文挑战」的第2天，  &lt;a href="https://juejin.cn/post/7099702781094674468" title="https://juejin.cn/post/7099702781094674468"&gt;点击查看活动详情&lt;/a&gt;&lt;/p&gt;
 &lt;h2&gt;1.1.容器网络基础&lt;/h2&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5b23c2657e3f4f7e87fbb7829352b11d~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;Kubernetes是一个开源容器调度编排引擎，管理大规模容器化应用，采用典型的Master-Worker主从分布式技术架构，由集中式管理节点（Master Node）,分布式的工作节点（Worker Node）组成。向下屏蔽底层差异化的分布式基础设施，以应用为中心构建云计算的基础操作系统能力（即云原生操作系统），面向用户提供云原生时代的云计算的新界面。&lt;/p&gt;
 &lt;p&gt;其中，Kubernetes网络至关重要，如果管理节点是控制大脑，运行节点是执行载体，那么网络就是将整个容器集群打通形成一个整体的神经网络；与Docker网络相比，Kubernetes网络最大的特点就是让容器组（Pod）拥有自己的身份证，即独立IP，实现在任何节点上的Pod都可以互相直接通信，而不需要任何的NAT地址转换；在不做限制时，Pod可以访问任何网络，并且拥有独立的网络栈，集群内部可见地址与外部可见地址保持一致。&lt;/p&gt;
 &lt;p&gt;在容器网络的具体实现上，Kubernetes通过开放的CNI标准，以插件化方式引入多种容器网络实现，从而支持各种差异化的场景的需求；当前社区比较常见的网络插件主要有Flannel、Calico、Cilium、OVN等，每个插件有不同的模式，需要按照实际的场景来选择使用。按照POD通信方式，有同主机的容器通信与跨主机的容器通信两大类型。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8fec66a8d5254e18bb9d7b687d5fc66c~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;（一）同主机的容器通信&lt;/p&gt;
 &lt;p&gt;在kubernetes集群的节点上，会创建一个veth(virtual ethernet）虚拟设备，同时将veth一端插入到容器网络的命名空间中，一端连接到主机上的网桥（linux bridge）。这样在同一主机上的POD通过veth实现IP地址相互通信。网桥也会分配一个IP地址，充当从POD到不同节点的出口流量网关。&lt;/p&gt;
 &lt;p&gt;（二）跨主机的容器通信&lt;/p&gt;
 &lt;p&gt;在不同主机上运行的容器POD通过IP地址相互通信，需要通过网络插件实现，按照依赖底层的技术大致可以分为Overlay模式，路由模式，Underlay模式三大类：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/45cd72a58e604edbbc283c7c0c07d6da~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;①　Overlay模式是在二层或三层网络之上再构建起来一个独立的网络，这个网络通常会有自己独立的IP地址空间、交换或者路由的实现。VXLAN协议是目前最流行的Overlay网络隧道协议之一，显著优势就是灵活，对底层网络没有侵入性。&lt;/p&gt;
 &lt;p&gt;②　路由模式放弃了跨主机容器在L2的连通性，而专注于通过路由协议提供容器在L3的通信方案；路由模式更易于集成到现在的数据中心的基础设施之上，便捷地连接容器和主机，并在报文过滤和隔离方面有着更好的扩展能力及更精细的控制模型。&lt;/p&gt;
 &lt;p&gt;③　Underlay模式是借助驱动程序将宿主机的底层网络接口直接暴露给容器使用的一种网络构建技术，较为常见的解决方案有MAC VLAN、IP VLAN和直接路由等。&lt;/p&gt;
 &lt;h2&gt;1.2.Flannel网络插件&lt;/h2&gt;
 &lt;p&gt;Flannel是由go语言开发，是一种基于overlay网络的跨主机容器网络插件。Flannel插件为集群中所有节点重新规划IP地址的分配规则，使得不同节点上的容器能够在同一个子网内，且IP地址不重复，实现不同节点上的容器通过内网IP直接通信。Flannel目前支持udp、vxlan、host-gw、aws-vpc、gce和alloc路由等多种灵活模式。但Flannel缺少必要的安全隔离，Qos等能力，适合常见简单，安全隔离要求较低的场景。以下是Flannel三种模式比较：&lt;/p&gt;
 &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;模式&lt;/td&gt;   &lt;td&gt;底层网络要求&lt;/td&gt;   &lt;td&gt;实现模式&lt;/td&gt;   &lt;td&gt;封包/解包&lt;/td&gt;   &lt;td&gt;overlay网络&lt;/td&gt;   &lt;td&gt;转发效率&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td&gt;Flannel UDP&lt;/td&gt;   &lt;td&gt;三层网络&lt;/td&gt;   &lt;td&gt;overlay&lt;/td&gt;   &lt;td&gt;用户态&lt;/td&gt;   &lt;td&gt;三层&lt;/td&gt;   &lt;td&gt;低&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td&gt;Flannel VXLAN&lt;/td&gt;   &lt;td&gt;三层网络&lt;/td&gt;   &lt;td&gt;overlay&lt;/td&gt;   &lt;td&gt;内核态&lt;/td&gt;   &lt;td&gt;二层&lt;/td&gt;   &lt;td&gt;中&lt;/td&gt;&lt;/tr&gt;  &lt;tr&gt;   &lt;td&gt;Flannel host-gw&lt;/td&gt;   &lt;td&gt;二层网络&lt;/td&gt;   &lt;td&gt;路由&lt;/td&gt;   &lt;td&gt;无&lt;/td&gt;   &lt;td&gt;三层&lt;/td&gt;   &lt;td&gt;高&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
 &lt;p&gt;在Flannel VXLAN模式时，插件会在kubernetes集群的每个节点上创建vxlan设备与路由表。发往不同主机上容器数据包都会通过vxlan设备，封装成UDP数据发往目的地；在目的主机上，封装的UDP数据包会被解压并路由到目标POD。但是具体到POD如何分配IP，以及整个容器生命周期过程中CNI插件与其他组件怎么交互配合，是一个相当复杂的过程，本文通过Flannel插件，以及容器运行时Containerd，详细的说明容器网络运行的全过程。&lt;/p&gt;
 &lt;h2&gt;1.3.Kubelet、Container Runtime和CNI插件&lt;/h2&gt;
 &lt;h3&gt;1.3.1.Pod IP地址分配机制&lt;/h3&gt;
 &lt;p&gt;当节点首次向集群注册时，nodeipam作为选项传递给kube-controller-manager的--controllers参数，控制器就会从集群CIDR（集群网络的IP范围）中为每个节点分配一个专用子网（podCIDR）。由于节点子网podCIDR保证不会重复，所以在为节点POD分配的IP地址也确保了唯一；如果需要更改节点的podCIDR，可以通过取消注册节点再重新注册实现。使用以下命令列出节点的podCIDR：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;$ kubectl get no-o json | jq &amp;apos;.spec.podCIDR&amp;apos;10.244.0.0/24
&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;1.3.2.Pod启动时网络配置过程&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/107c987ffbee442490bf818bc408ca1a~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;当一个POD被调度到节点时，会有很多初始化操作，以下是网络配置相关的配置及初始化过程详细步骤：&lt;/p&gt;
 &lt;p&gt;①　POD被调度到容器集群的某个节点上&lt;/p&gt;
 &lt;p&gt;②　节点的kubelet通过调用CRI插件来创建POD&lt;/p&gt;
 &lt;p&gt;③　CRI插件创建POD Sandbox ID与POD网络命名空间&lt;/p&gt;
 &lt;p&gt;④　CRI插件通过POD网络命名空间和POD Sandbox ID来调用CNI插件&lt;/p&gt;
 &lt;p&gt;⑤　CNI插件配置POD网络，调用顺序从Flannel CNI插件，Bridge CNI 插件到主机IPAM CNI 插件，最后返回POD IP地址。&lt;/p&gt;
 &lt;p&gt;⑥　创建Pause容器，并将其添加第三步创建的POD的网络命名空间&lt;/p&gt;
 &lt;p&gt;⑦　Kubelet调用CRI插件拉取应用容器镜像&lt;/p&gt;
 &lt;p&gt;⑧　容器运行时containerd拉取应用容器镜像&lt;/p&gt;
 &lt;p&gt;⑨　Kubelet调用CRI插件来启动应用容器&lt;/p&gt;
 &lt;p&gt;⑩　CRI插件调用容器运行时containerd来启动和配置在pod cgroup和namespaces中的应用容器。&lt;/p&gt;
 &lt;h3&gt;1.3.3.CRI插件与CNI插件的交互&lt;/h3&gt;
 &lt;p&gt;在POD初始化过程中，CRI插件会调用CNI插件来完成对POD网络的配置。CNI网络插件都会在kubernetes节点上安装配置代理，并附带CNI配置，然后CRI插件通过该配置来确定要调用那个CNI插件。CNI配置文件的位置默认值为/etc/cni/net.d/，可以自定义配置。同时在每个节点上都会有CNI插件，CNI插件位置默认值为/opt/cni/bin，也可以自定义配置。在containerd作为容器运行时，CNI配置和CNI插件二进制文件的路径可以在containerd配置的[plugins.&amp;quot;io.containerd.grpc.v1.cri&amp;quot;.cni]中指定。&lt;/p&gt;
 &lt;p&gt;对于Flannel插件，Flanneld作为Flannel守护进程，通常安装在 kubernetes集群的节点上，而install-cni作为init容器，在每个节点上创建 CNI配置文件-/etc/cni/net.d/10-flannel.conflist。Flanneld创建vxlan设备，从API-SERVER获取并监听POD网络元数据。在创建POD时，为整个集群中的所有POD分配路由，通过路由实现POD IP地址相互通信。CRI插件与CNI插件之间的交互如下：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0657d4cf79e7430fae65693e550dd3a2~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;①　Kubelet通过CRI插件调用容器运行时&lt;/p&gt;
 &lt;p&gt;②　CRI插件通过CNI配置文件调用CNI插件，为POD创建网络命名空间，网络命名空间在/var/run/netns/文件下&lt;/p&gt;
 &lt;p&gt;③　Flannel CNI插件配置和调用Bridge CNI plugin&lt;/p&gt;
 &lt;p&gt;④　Bridge CNI插件在主机上创建cniO网桥，并创建了veth对，一端插入容器网络命名空间，另一端连接到cniO网桥。然后调用已配置的IPAM 插件。&lt;/p&gt;
 &lt;p&gt;⑤　host-local IPAM插件返回容器的IP地址和网关（cniO桥作为容器的网关），将IP地址分配给POD，桥接插件将网关IP地址分配给cniO桥接。所有分配的IP地址都存储在本地磁盘上的/var/lib/cni/networks/cni0/目录下。&lt;/p&gt;
 &lt;h3&gt;1.3.4.CNI插件间的交互&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c6c852def69049009f41eab9083e56c0~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;CNI插件配置POD网络，调用顺序从Flannel CNI插件，Bridge CNI 插件到主机IPAM CNI 插件，最后返回POD IP地址。详情如下：&lt;/p&gt;
 &lt;p&gt;①　Flannel CNI插件：Containerd CRI插件使用CNI配置文件- /etc/cni/net.d/10-flannel.conflist调用Flannel CNI插件：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;$ cat /etc/cni/net.d/10-flannel.conflist{  &amp;quot;name&amp;quot;: &amp;quot;cni0&amp;quot;,  &amp;quot;plugins&amp;quot;: [    {      &amp;quot;type&amp;quot;: &amp;quot;flannel&amp;quot;,      &amp;quot;delegate&amp;quot;: {       &amp;quot;ipMasq&amp;quot;: false,        &amp;quot;hairpinMode&amp;quot;: true,        &amp;quot;isDefaultGateway&amp;quot;: true      }    }  ]}
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;当Flanneld启动时，会从API-SERVER获取podCIDR和其他与网络相关的详细信息，并存储在 -/run/flannel/subnet.env文件中：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;FLANNEL_NETWORK=10.244.0.0/16 
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450 
FLANNEL_IPMASQ=false
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;Flannel CNI插件使用/run/flannel/subnet.env中的信息来配置和调用网桥CNI插件。&lt;/p&gt;
 &lt;p&gt;②　Bridge CNI插件：Flannel CNI插件调用Bridge CNI插件，配置如下：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;cni0&amp;quot;,
  &amp;quot;type&amp;quot;: &amp;quot;bridge&amp;quot;,
  &amp;quot;mtu&amp;quot;: 1450,
  &amp;quot;ipMasq&amp;quot;: false,
  &amp;quot;isGateway&amp;quot;: true,
  &amp;quot;ipam&amp;quot;: {
    &amp;quot;type&amp;quot;: &amp;quot;host-local&amp;quot;,
    &amp;quot;subnet&amp;quot;: &amp;quot;10.244.0.0/24&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;首次调用Bridge CNI插件时，会创建一个linux网桥，并在配置文件中指定“名称”：“cni0”。然后为每一个POD创建veth对，veth对一端位于容器的网络命名空间中，另一端连接到主机网络的网桥上，使用 Bridge CNI插件，主机上的所有容器都连接到主机网络的网桥上。&lt;/p&gt;
 &lt;p&gt;配置veth对后，Bridge插件调用主机本地IPAM CNI插件，可以在CNI config CRI插件中配置使用具体IPAM 插件。&lt;/p&gt;
 &lt;p&gt;③　主机本地 IPAM CNI 插件：Bridge CNI插件使用以下配置调用主机本地 IPAM CNI 插件：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;cni0&amp;quot;,
  &amp;quot;ipam&amp;quot;: {
    &amp;quot;type&amp;quot;: &amp;quot;host-local&amp;quot;,
    &amp;quot;subnet&amp;quot;: &amp;quot;10.244.0.0/24&amp;quot;,
    &amp;quot;dataDir&amp;quot;: &amp;quot;/var/lib/cni/networks&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;Host-local IPAM（IP地址管理）插件从子网返回容器的IP地址，并将分配的IP本地存储在主机上dataDir下指定的目录下- /var/lib/cni/networks/。/var/lib/cni/networks/文件包含分配 IP 的容器 ID。&lt;/p&gt;
 &lt;p&gt;调用时，主机本地IPAM 插件返回以下结果：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;{
  &amp;quot;ip4&amp;quot;: {
    &amp;quot;ip&amp;quot;: &amp;quot;10.244.4.2&amp;quot;,
    &amp;quot;gateway&amp;quot;: &amp;quot;10.244.4.3&amp;quot;
  },
  &amp;quot;dns&amp;quot;: {}
}
&lt;/code&gt;&lt;/pre&gt;
 &lt;h2&gt;1.4.总结&lt;/h2&gt;
 &lt;p&gt;总体来说，容器网络是Kubernetes最复杂部分，同时也是设计精华所在，通过CNI标准开放，根据实际需求实现不同的CNI来满足差异化的需求，尤其是与底层基础云能力深度集成的场景，每个云厂商都有实现各自高效的网络插件。整个容器网络大致从以下三个方面理解：&lt;/p&gt;
 &lt;p&gt;首先，在整体设计上，让POD有唯一的IP地址，通过为每个节点分配一个子网，从而保证节点为POD分配的IP地址，在整个集群内部不会重复。&lt;/p&gt;
 &lt;p&gt;其次，在容器网络是实现上，通过CNI将容器网络标准与具体实现解耦分类，通过插件引入不同的容器网络插件。&lt;/p&gt;
 &lt;p&gt;最后，在容器POD创建时，通过Kubelet，CRI插件，以及CNI插件相互配合，实现容器POD网络配置及初始化。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62284-kubernetes-%E5%AE%B9%E5%99%A8-%E7%BD%91%E7%BB%9C</guid>
      <pubDate>Mon, 30 May 2022 15:07:54 CST</pubDate>
    </item>
    <item>
      <title>轻量的神经网络</title>
      <link>https://itindex.net/detail/62231-%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C</link>
      <description>&lt;p&gt;很久之前我觉得移动端应用几百兆的模型不切实际，在不考虑蒸馏、量化等压缩方法下，发现了 MobileNet 设计的很神奇，大小只有几 MB，可以说是一股清流了。就整理发布了一下，然后今天发现找不到了，神奇。（于是顺手和 ShuffleNet 一并整理到轻量化的神经网络中）&lt;/p&gt; &lt;a&gt;&lt;/a&gt; &lt;h1&gt;  &lt;a href="https://muyuuuu.github.io/#MobileNet-V1" title="MobileNet-V1"&gt;&lt;/a&gt;MobileNet-V1&lt;/h1&gt; &lt;p&gt;基本上可以说这个版本是后面几个版本的出发点。先来看一下创新点：提出 depthwise separable conv 和 pointwise conv 来降低网络的计算次数。还是直接画图吧：&lt;/p&gt; &lt;p&gt;  &lt;img alt=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;对于传统卷积而言，输入一个三通道的图片，如果想要输出五通道，那么就需要 5 个 $3\times 3 \times 3$ 的卷积核。一般一些，假设传统卷积处理图像的大小是 $D_F\times D_F$，有 $M$ 个通道，卷积核的大小是 $D_K$，输出的通道数数 $N$，那么计算量就是 $D_K \cdot D_K \cdot M \cdot N \cdot D_F \cdot D_F$。&lt;/p&gt; &lt;p&gt;在得到相同大小输出的情况下，使用 DW 卷积和 PW 卷积来简化一下这个计算过程：&lt;/p&gt; &lt;p&gt;  &lt;img alt=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;如果换成深度可分离卷积和逐点卷积，可以看到达到同样的输出，参数量从 $27\times 5$ 减少到了 $27+15$，而且计算量为 $D_K \cdot D_K \cdot M \cdot D_F \cdot D_F + M \cdot N \cdot D_F \cdot D_F$。两者的比值是 $1/N+1/D_K^2$。&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;15     &lt;br /&gt;16     &lt;br /&gt;17     &lt;br /&gt;18     &lt;br /&gt;19     &lt;br /&gt;20     &lt;br /&gt;21     &lt;br /&gt;22     &lt;br /&gt;23     &lt;br /&gt;24     &lt;br /&gt;25     &lt;br /&gt;26     &lt;br /&gt;27     &lt;br /&gt;28     &lt;br /&gt;29     &lt;br /&gt;30     &lt;br /&gt;31     &lt;br /&gt;32     &lt;br /&gt;33     &lt;br /&gt;34     &lt;br /&gt;35     &lt;br /&gt;36     &lt;br /&gt;37     &lt;br /&gt;38     &lt;br /&gt;39     &lt;br /&gt;40     &lt;br /&gt;41     &lt;br /&gt;42     &lt;br /&gt;43     &lt;br /&gt;44     &lt;br /&gt;45     &lt;br /&gt;46     &lt;br /&gt;47     &lt;br /&gt;48     &lt;br /&gt;49     &lt;br /&gt;50     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;class MobileNetV1(nn.Module):     &lt;br /&gt;    def __init__(self, ch_in, n_classes):     &lt;br /&gt;        super(MobileNetV1, self).__init__()     &lt;br /&gt;     &lt;br /&gt;        def conv_bn(inp, oup, stride):     &lt;br /&gt;            return nn.Sequential(     &lt;br /&gt;                nn.Conv2d(inp, oup, 3, stride, 1, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(oup),     &lt;br /&gt;                nn.ReLU(inplace=True)     &lt;br /&gt;                )     &lt;br /&gt;     &lt;br /&gt;        def conv_dw(inp, oup, stride):     &lt;br /&gt;            return nn.Sequential(     &lt;br /&gt;                # dw     &lt;br /&gt;                # 输入通道和输出通道相等，groups 表示每个卷积核只处理一个通道     &lt;br /&gt;                nn.Conv2d(inp, inp, 3, stride, 1, groups=inp, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(inp),     &lt;br /&gt;                nn.ReLU(inplace=True),     &lt;br /&gt;     &lt;br /&gt;                # pw     &lt;br /&gt;                # 卷积核大小为 1X1     &lt;br /&gt;                nn.Conv2d(inp, oup, 1, 1, 0, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(oup),     &lt;br /&gt;                nn.ReLU(inplace=True),     &lt;br /&gt;                )     &lt;br /&gt;     &lt;br /&gt;        self.model = nn.Sequential(     &lt;br /&gt;            conv_bn(ch_in, 32, 2),     &lt;br /&gt;            conv_dw(32, 64, 1),     &lt;br /&gt;            conv_dw(64, 128, 2),     &lt;br /&gt;            conv_dw(128, 128, 1),     &lt;br /&gt;            conv_dw(128, 256, 2),     &lt;br /&gt;            conv_dw(256, 256, 1),     &lt;br /&gt;            conv_dw(256, 512, 2),     &lt;br /&gt;            conv_dw(512, 512, 1),     &lt;br /&gt;            conv_dw(512, 512, 1),     &lt;br /&gt;            conv_dw(512, 512, 1),     &lt;br /&gt;            conv_dw(512, 512, 1),     &lt;br /&gt;            conv_dw(512, 512, 1),     &lt;br /&gt;            conv_dw(512, 1024, 2),     &lt;br /&gt;            conv_dw(1024, 1024, 1),     &lt;br /&gt;            nn.AdaptiveAvgPool2d(1)     &lt;br /&gt;        )     &lt;br /&gt;        self.fc = nn.Linear(1024, n_classes)     &lt;br /&gt;     &lt;br /&gt;    def forward(self, x):     &lt;br /&gt;        x = self.model(x)     &lt;br /&gt;        x = x.view(-1, 1024)     &lt;br /&gt;        x = self.fc(x)     &lt;br /&gt;        return x     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h1&gt;  &lt;a href="https://muyuuuu.github.io/#MobileNet-V2" title="MobileNet-V2"&gt;&lt;/a&gt;MobileNet-V2&lt;/h1&gt; &lt;p&gt;V1 的思想可以概括为：首先利用 3×3 的深度可分离卷积提取特征，然后利用 1×1 的卷积来扩张通道。但是有人在实际使用的时候，发现训完之后发现 dw 卷积核有不少是空的。&lt;/p&gt; &lt;p&gt;作者认为这是 ReLU 激活函数导致的。于是做了一个实验，就是对一个 n 维空间中的一个东西乘以矩阵 $T$，而后做 ReLU 运算，然后利用 $T$ 的逆矩阵恢复，对比 ReLU 之后的结果与 Input 的结果相差有多大。作者发现：低维度做 ReLU 运算，很容易造成信息的丢失。而在高维度进行 ReLU 运算的话，信息的丢失则会很少。&lt;/p&gt; &lt;p&gt;由于卷积本身没有改变通道的能力，来的是多少通道输出就是多少通道。上面又得出低维通道不好的结论，因此使用 PW 卷积升维再降维，这也就形成了 Inverted Residuals 这种结构，因为传统的残差结构和本文相反，传统的是先降维在升维。&lt;/p&gt; &lt;p&gt;这样高维的仍然使用 ReLU 激活函数，低维的换成线性激活函数。因为有先升维在降维的结构，因此使用了残差连接来提升性能。&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;15     &lt;br /&gt;16     &lt;br /&gt;17     &lt;br /&gt;18     &lt;br /&gt;19     &lt;br /&gt;20     &lt;br /&gt;21     &lt;br /&gt;22     &lt;br /&gt;23     &lt;br /&gt;24     &lt;br /&gt;25     &lt;br /&gt;26     &lt;br /&gt;27     &lt;br /&gt;28     &lt;br /&gt;29     &lt;br /&gt;30     &lt;br /&gt;31     &lt;br /&gt;32     &lt;br /&gt;33     &lt;br /&gt;34     &lt;br /&gt;35     &lt;br /&gt;36     &lt;br /&gt;37     &lt;br /&gt;38     &lt;br /&gt;39     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;class InvertedResidual(nn.Module):     &lt;br /&gt;    def __init__(self, inp, oup, stride, expand_ratio):     &lt;br /&gt;        super(InvertedResidual, self).__init__()     &lt;br /&gt;        self.stride = stride     &lt;br /&gt;        assert stride in [1, 2]     &lt;br /&gt;     &lt;br /&gt;        hidden_dim = int(inp * expand_ratio)     &lt;br /&gt;        self.use_res_connect = self.stride == 1 and inp == oup     &lt;br /&gt;     &lt;br /&gt;        if expand_ratio == 1:     &lt;br /&gt;            self.conv = nn.Sequential(     &lt;br /&gt;                # dw     &lt;br /&gt;                nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(hidden_dim),     &lt;br /&gt;                nn.ReLU6(inplace=True),     &lt;br /&gt;                # pw-linear     &lt;br /&gt;                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(oup),     &lt;br /&gt;            )     &lt;br /&gt;        else:     &lt;br /&gt;            self.conv = nn.Sequential(     &lt;br /&gt;                # pw 升维     &lt;br /&gt;                nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(hidden_dim),     &lt;br /&gt;                nn.ReLU6(inplace=True),     &lt;br /&gt;                # dw 深度可分离卷积     &lt;br /&gt;                nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(hidden_dim),     &lt;br /&gt;                nn.ReLU6(inplace=True),     &lt;br /&gt;                # pw-linear 激活     &lt;br /&gt;                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(oup),     &lt;br /&gt;            )     &lt;br /&gt;     &lt;br /&gt;    def forward(self, x):     &lt;br /&gt;        if self.use_res_connect:     &lt;br /&gt;            return x + self.conv(x)     &lt;br /&gt;        else:     &lt;br /&gt;            return self.conv(x)     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h1&gt;  &lt;a href="https://muyuuuu.github.io/#MobileNet-V3" title="MobileNet-V3"&gt;&lt;/a&gt;MobileNet-V3&lt;/h1&gt; &lt;p&gt;主要做了两点创新，一个是在 MobileNet V2 残差分支加入了 SE（Squeeze-and-Excitation） 注意力机制的模块，一个是更新了激活函数。SE 注意力就是通过池化得到每个通道的值，并输入到全连接层学习到每个通道的权重，对每个通道的数值进行更新。&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;15     &lt;br /&gt;16     &lt;br /&gt;17     &lt;br /&gt;18     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;class SELayer(nn.Module):     &lt;br /&gt;    def __init__(self, channel, reduction=4):     &lt;br /&gt;        super(SELayer, self).__init__()     &lt;br /&gt;        self.avg_pool = nn.AdaptiveAvgPool2d(1)     &lt;br /&gt;        # 输入维度和输出维度相同     &lt;br /&gt;        self.fc = nn.Sequential(     &lt;br /&gt;            nn.Linear(channel, _make_divisible(channel // reduction, 8)),     &lt;br /&gt;            nn.ReLU(inplace=True),     &lt;br /&gt;            nn.Linear(_make_divisible(channel // reduction, 8), channel),     &lt;br /&gt;            h_sigmoid()     &lt;br /&gt;        )     &lt;br /&gt;     &lt;br /&gt;    def forward(self, x):     &lt;br /&gt;        b, c, _, _ = x.size()     &lt;br /&gt;        y = self.avg_pool(x).view(b, c)     &lt;br /&gt;        y = self.fc(y).view(b, c, 1, 1)     &lt;br /&gt;        # y 是每个通道的权重     &lt;br /&gt;        return x * y     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;在重新设计激活函数方面，使用 h-swish 激活函数代替了 swish 激活函数，因为更容易计算。对于 swish 激活函数：&lt;/p&gt; &lt;p&gt;\begin{equation}  &lt;br /&gt;    \begin{aligned}  &lt;br /&gt;        \text{swish} x &amp;amp;= x \cdot \sigma(x) \\  &lt;br /&gt;        \sigma(x) &amp;amp;= \frac{1}{1+e^{-x}}  &lt;br /&gt;    \end{aligned}  &lt;br /&gt;\end{equation}&lt;/p&gt; &lt;p&gt;这个反向传播和激活的计算过程略显复杂，对量化不够友好。于是使用较为接近的 h-swish 激活函数代替：&lt;/p&gt; &lt;p&gt;\begin{equation}  &lt;br /&gt;    \begin{aligned}  &lt;br /&gt;        \text{h-sigmoid} &amp;amp;= \frac{\text{ReLU6}(x+3)}{6} \\  &lt;br /&gt;        \text{h-swish} &amp;amp;= x \cdot \text{h-sigmoid}  &lt;br /&gt;    \end{aligned}  &lt;br /&gt;\end{equation}&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;15     &lt;br /&gt;16     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;class h_sigmoid(nn.Module):     &lt;br /&gt;    def __init__(self, inplace=True):     &lt;br /&gt;        super(h_sigmoid, self).__init__()     &lt;br /&gt;        self.relu = nn.ReLU6(inplace=inplace)     &lt;br /&gt;     &lt;br /&gt;    def forward(self, x):     &lt;br /&gt;        return self.relu(x + 3) / 6     &lt;br /&gt;     &lt;br /&gt;     &lt;br /&gt;class h_swish(nn.Module):     &lt;br /&gt;    def __init__(self, inplace=True):     &lt;br /&gt;        super(h_swish, self).__init__()     &lt;br /&gt;        self.sigmoid = h_sigmoid(inplace=inplace)     &lt;br /&gt;     &lt;br /&gt;    def forward(self, x):     &lt;br /&gt;        return x * self.sigmoid(x)     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;1     &lt;br /&gt;2     &lt;br /&gt;3     &lt;br /&gt;4     &lt;br /&gt;5     &lt;br /&gt;6     &lt;br /&gt;7     &lt;br /&gt;8     &lt;br /&gt;9     &lt;br /&gt;10     &lt;br /&gt;11     &lt;br /&gt;12     &lt;br /&gt;13     &lt;br /&gt;14     &lt;br /&gt;15     &lt;br /&gt;16     &lt;br /&gt;17     &lt;br /&gt;18     &lt;br /&gt;19     &lt;br /&gt;20     &lt;br /&gt;21     &lt;br /&gt;22     &lt;br /&gt;23     &lt;br /&gt;24     &lt;br /&gt;25     &lt;br /&gt;26     &lt;br /&gt;27     &lt;br /&gt;28     &lt;br /&gt;29     &lt;br /&gt;30     &lt;br /&gt;31     &lt;br /&gt;32     &lt;br /&gt;33     &lt;br /&gt;34     &lt;br /&gt;35     &lt;br /&gt;36     &lt;br /&gt;37     &lt;br /&gt;38     &lt;br /&gt;39     &lt;br /&gt;40     &lt;br /&gt;41     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;   &lt;td&gt;    &lt;pre&gt;class InvertedResidual(nn.Module):     &lt;br /&gt;    def __init__(self, inp, hidden_dim, oup, kernel_size, stride, use_se, use_hs):     &lt;br /&gt;        super(InvertedResidual, self).__init__()     &lt;br /&gt;        assert stride in [1, 2]     &lt;br /&gt;     &lt;br /&gt;        self.identity = stride == 1 and inp == oup     &lt;br /&gt;     &lt;br /&gt;        if inp == hidden_dim:     &lt;br /&gt;            self.conv = nn.Sequential(     &lt;br /&gt;                # dw     &lt;br /&gt;                nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(hidden_dim),     &lt;br /&gt;                h_swish() if use_hs else nn.ReLU(inplace=True),     &lt;br /&gt;                # Squeeze-and-Excite     &lt;br /&gt;                SELayer(hidden_dim) if use_se else nn.Identity(),     &lt;br /&gt;                # pw-linear     &lt;br /&gt;                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(oup),     &lt;br /&gt;            )     &lt;br /&gt;        else:     &lt;br /&gt;            self.conv = nn.Sequential(     &lt;br /&gt;                # pw 升维     &lt;br /&gt;                nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(hidden_dim),     &lt;br /&gt;                h_swish() if use_hs else nn.ReLU(inplace=True),     &lt;br /&gt;                # dw 提取特征     &lt;br /&gt;                nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(hidden_dim),     &lt;br /&gt;                # Squeeze-and-Excite     &lt;br /&gt;                SELayer(hidden_dim) if use_se else nn.Identity(),     &lt;br /&gt;                h_swish() if use_hs else nn.ReLU(inplace=True),     &lt;br /&gt;                # pw-linear 先行激活，降维     &lt;br /&gt;                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),     &lt;br /&gt;                nn.BatchNorm2d(oup),     &lt;br /&gt;            )     &lt;br /&gt;     &lt;br /&gt;    def forward(self, x):     &lt;br /&gt;        if self.identity:     &lt;br /&gt;            return x + self.conv(x)     &lt;br /&gt;        else:     &lt;br /&gt;            return self.conv(x)     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h1&gt;  &lt;a href="https://muyuuuu.github.io/#ShuffleNet-V1" title="ShuffleNet-V1"&gt;&lt;/a&gt;ShuffleNet-V1&lt;/h1&gt; &lt;h1&gt;  &lt;a href="https://muyuuuu.github.io/#ShuffleNet-V2" title="ShuffleNet-V2"&gt;&lt;/a&gt;ShuffleNet-V2&lt;/h1&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>CV</category>
      <guid isPermaLink="true">https://itindex.net/detail/62231-%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C</guid>
      <pubDate>Sat, 30 Apr 2022 20:43:59 CST</pubDate>
    </item>
    <item>
      <title>网络安全应急响应实战笔记</title>
      <link>https://itindex.net/detail/62229-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8-%E7%AC%94%E8%AE%B0</link>
      <description>&lt;p&gt;    &lt;img alt="" src="https://bypass007.github.io/Emergency-Response-Notes/Summary/image/sum-title.png"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt;GitHub  地址：    &lt;a href="https://github.com/Bypass007/Emergency-Response-Notes" target="_blank"&gt;https://github.com/Bypass007/Emergency-Response-Notes&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;GitBook 地址：    &lt;a href="https://bypass007.github.io/Emergency-Response-Notes/" target="_blank"&gt;https://bypass007.github.io/Emergency-Response-Notes/&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;项目介绍&lt;/h3&gt;  &lt;p&gt;面对各种各样的安全事件，我们该怎么处理？&lt;/p&gt;  &lt;p&gt;这是一个关于安全事件应急响应的项目，从系统入侵到事件处理，收集和整理了一些案例进行分析。&lt;/p&gt;  &lt;p&gt;我将持续更新这份笔记，希望能帮到有需要的人。&lt;/p&gt;  &lt;p&gt;如果你看到好的案例，欢迎通过issue提交。&lt;/p&gt;  &lt;h3&gt;项目目录&lt;/h3&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;[第一章：入侵排查篇]&lt;/strong&gt;&lt;/p&gt;      &lt;ul&gt;        &lt;li&gt;          &lt;p&gt;第1篇：Window入侵排查&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第2篇：Linux入侵排查&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第3篇：常见的Webshell查杀工具&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第4篇：如何发现隐藏的Webshell后门&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第5篇：勒索病毒自救指南&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;[第二章：日志分析篇]&lt;/strong&gt;&lt;/p&gt;      &lt;ul&gt;        &lt;li&gt;          &lt;p&gt;第1篇:Window日志分析&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第2篇:Linux日志分析&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第3篇:Web日志分析&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第4篇:MSSQL日志分析&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第5篇:MySQL日志分析&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;[第三章：权限维持篇]&lt;/strong&gt;&lt;/p&gt;      &lt;ul&gt;        &lt;li&gt;          &lt;p&gt;第1篇：Windows权限维持--隐藏篇&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第2篇：Windows权限维持--后门篇&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第3篇：Linux权限维持--隐藏篇&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第4篇：Linux权限维持--后门篇&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第5篇：Windows命令行文件下载方式汇总&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第6篇：三大渗透测试框架权限维持技术&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第7篇：常见WebShell管理工具&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;[第四章:Windows实战篇]&lt;/strong&gt;&lt;/p&gt;      &lt;ul&gt;        &lt;li&gt;          &lt;p&gt;第1篇：FTP暴力破解&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第2篇：蠕虫病毒&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第3篇：勒索病毒&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第4篇：ARP病毒&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第5篇：挖矿病毒（一）&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第6篇：挖矿病毒（二）&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;[第五章：Linux实战篇]&lt;/strong&gt;&lt;/p&gt;      &lt;ul&gt;        &lt;li&gt;          &lt;p&gt;第1篇：SSH暴力破解&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第2篇：捕捉短连接&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第3篇：挖矿病毒&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第4篇：盖茨木马&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第5篇：DDOS病毒&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第6篇：Shell病毒&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;[第六章：Web实战篇]&lt;/strong&gt;&lt;/p&gt;      &lt;ul&gt;        &lt;li&gt;          &lt;p&gt;第1篇：网站被植入Webshell&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第2篇：门罗币恶意挖矿&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第3篇：批量挂黑页&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第4篇：新闻源网站劫持&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第5篇：移动端劫持&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第6篇：搜索引擎劫持&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第7篇：网站首页被篡改&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第8篇：管理员账号被篡改&lt;/p&gt;&lt;/li&gt;        &lt;li&gt;          &lt;p&gt;第9篇：编辑器入侵事件&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;hr&gt;&lt;/hr&gt;  &lt;h3&gt;学习交流&lt;/h3&gt;  &lt;p&gt;后续持续更新内容，将发布在公众号Bypass--，同时公众号提供了该项目的PDF版本，关注后回复&amp;quot;应急响应&amp;quot; 即可下载。&lt;/p&gt;  &lt;p&gt;    &lt;img alt="" src="https://bypass007.github.io/Emergency-Response-Notes/Summary/image/sum-erweima.jpg"&gt;&lt;/img&gt;&lt;/p&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62229-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8-%E7%AC%94%E8%AE%B0</guid>
      <pubDate>Sat, 30 Apr 2022 21:09:41 CST</pubDate>
    </item>
    <item>
      <title>保护自己 - 深入链路探究网络安全</title>
      <link>https://itindex.net/detail/62188-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8</link>
      <description>&lt;h3&gt;前言&lt;/h3&gt; &lt;p&gt;说起基于网络的攻击，大家可能都会想到 SQL注入、SSRF、CSRF 这些比较常见的因为软件漏洞造成的攻击，但网络远不止如此。本文会介绍一些常见的网络安全问题及攻击方式，提高安全上网以及保密意识，帮助大家识别常见的网络信息泄漏、网络故障及发生的阶段。&lt;/p&gt; &lt;p&gt;信息系统的安全，是指完整性、保密性、可用性和不可否认性。&lt;/p&gt; &lt;p&gt;对应的攻击手段有，窃听、篡改、伪造、重放、抵赖和拒绝服务。&lt;/p&gt; &lt;p&gt;有一道常见的前端面试题，在浏览器地址栏中输入 www.baidu.com 并按下回车，会发生什么？我们也顺着这个思路，谈一谈网络上的安全。&lt;/p&gt; &lt;h3&gt;DNS 和名称解析&lt;/h3&gt; &lt;p&gt;要想找到对应的服务器，首先要知道它的 IP 地址。这一过程称为名称解析(name resolution)。对于一个传统浏览器，它通常会直接求助于操作系统进行查询。&lt;/p&gt; &lt;p&gt;当连接网络时，网关会为操作系统分配一个 DNS 地址，它被称为本地名称服务器(LDNS) ，系统通过它的 53 端口，基于 IP - UDP 协议进行 DNS 查询。所以一个 DNS packet 也有 IP 与 UDP 的内容。完整的 DNS packet 是这样的：&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;如果一个名称服务器不能回答我们的查询，根据请求的 RD 标志位，以及自身是否支持递归查询，会选择进行递归查询或迭代查询。LDNS 通常是递归的，即，它会帮我们取得最终结果并返回给我们。而根名称服务器、根域名的名称服务器等通常是迭代的，如下图：&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;DNS 是基于信任关系的协议，路径上所有信息明文传输，整个路径没有任何保护与校验，导致其存在很多问题。&lt;/p&gt; &lt;h4&gt;针对 DNS 的攻击&lt;/h4&gt; &lt;p&gt;假如我们的本地名称服务器(一般是运营商提供)不可信，它可以告诉我们任意错误的服务器地址。比如，以前国内网络治理不严格，经常出现当我们访问某些网站时，跳转到某些运营商的广告导航页面...&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;DNS 服务器通过返回虚假 IP 地址，使得浏览器向错误的服务器请求内容，这被称作 DNS 劫持(DNS hijacking)。&lt;/p&gt; &lt;p&gt;LDNS 是内鬼，那是不是在路由器或者 windows 设置里，手动设置一个信任的 LDNS，就可以了呢？过去上网比较多的话，可能把 DNS 地址改成  &lt;code&gt;114.114.114.114&lt;/code&gt;或者  &lt;code&gt;8.8.8.8&lt;/code&gt;，就能缓解这一问题，也可以访问一些本来无法打开的网站。&lt;/p&gt; &lt;p&gt;但后来，这种方法就没什么用了。&lt;/p&gt; &lt;p&gt;即使设置了 8.8.8.8，当我们访问 Google 或者某些其他网站时，还是无法访问。或是出现证书错误，证书指向 facebook；或是直接超时，无法打开。这还是 DNS 的问题吗？&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;我们通过  &lt;code&gt;nslookup&lt;/code&gt;查询一下试试，向 8.8.8.8 查询竟然只需要 10ms 就返回了，访问谷歌的服务器怎么可能这么快，难道它就在我们旁边？进一步反查它对应的域名，这这这，看它绑定的这些域名，怎么想都是一些非法网站吧。为什么？我把 LDNS 地址改成 8.8.8.8 谷歌 DNS，它为什么会胡乱返回它自己的服务器地址呢？  &lt;img&gt;&lt;/img&gt;  &lt;img&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;8.8.8.8 是Anycast  &lt;sup&gt;[1]&lt;/sup&gt;任播的，但谷歌在中国境内应该没有服务器吧，10ms 的响应速度还是很可疑。&lt;/p&gt; &lt;p&gt;DNS 是明文传输的，即使没有内鬼，还有更糟糕的：实际上链路上的所有人都知道你正在进行这个网站的访问，它们都可以直接看到你的 IP 地址、端口、要查询的域名等信息。&lt;/p&gt; &lt;p&gt;回顾我们的 DNS Packet，受 DNS 协议限制，主机只要收到与请求 Query ID 相同的响应，就认为收到了 DNS 响应，它无法验证响应是否真的来源于对应服务器返回。而明文的 DNS 查询，导致链路上的所有人都有能力看到你查询的 Query ID，它们均可以抢在你查询的服务器返回前，直接返回给你任意的结果，这就是 DNS 抢答。&lt;/p&gt; &lt;p&gt;根据上述分析和文章提到的方法，不管你的 LDNS 如何设置，都有人能根据你的查询内容，抢答一个随机的或者错误的地址。&lt;/p&gt; &lt;p&gt;当然，还有其他多种攻击方式，如，缓存投毒  &lt;sup&gt;[2]&lt;/sup&gt;、DoS(denial of service, 拒绝服务)...&lt;/p&gt; &lt;p&gt;这样看来，对照我们安全的定义，明文的 DNS 协议具有会被 窃听、篡改、伪造 和 拒绝服务 的风险。&lt;/p&gt; &lt;h4&gt;针对 DNS 攻击的缓解方法&lt;/h4&gt; &lt;p&gt;如何解决 DNS 存在的问题呢？&lt;/p&gt; &lt;p&gt;DNSSEC  &lt;sup&gt;[3]&lt;/sup&gt;(Domain Name System Security Extensions, DNS 安全扩展) (中文资料:DNSSEC 实战 - 掘金  &lt;sup&gt;[4]&lt;/sup&gt;)可以解决 DNS 被篡改和伪造的问题。它通过对 DNS 响应进行签名，确保它来自于某一个权威服务器，路径上的人虽然能看到请求和响应，但伪造的响应没有对应服务器的签名，一旦篡改，原签名就失效了。攻击者看得见，却摸不着。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;DNSSEC 需要权威域名服务器启用和设置，并需要链路上所有 DNS 服务器支持以构建信任链。而且，它要求递归名称服务器对响应进行验证，如果递归名称服务器，LDNS，本身就是内鬼，则这个机制就没什么意义了。&lt;/p&gt; &lt;p&gt;那么，怎样让链路上的人看不见我们在查询什么，甚至不知道我们在进行 DNS 查询，避免 DNS 查询被窃听、抢答呢？TCP/IP 层无能为力，我们可以在应用层想想办法。DoH (DNS over HTTPS) 或 DoT (DNS over TLS) 可以解决这个问题。因为基本原理与 HTTPS 一致，其更安全的原理，以及针对其的攻击，将在  &lt;strong&gt;HTTP 与 HTTPS&lt;/strong&gt;这一节中继续。&lt;/p&gt; &lt;p&gt;DoH 需要我们在客户端主动启用。目前，主流浏览器(如 Chrome、Edge) 以及最新版操作系统(如 Windows 11、Mac) 均已支持 DoH(或 DoT)。&lt;/p&gt; &lt;p&gt;  &lt;img&gt;&lt;/img&gt;  &lt;img&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;经过 DNSSEC 和 DoH，链路上内鬼问题被我们逐一解决。DNS 查询看不到，摸不着，甚至不知道我们正在使用 DNS，对我们来说，已经安全很多了。&lt;/p&gt; &lt;p&gt;我们用三张图回顾下(来源: https://www.3key.company/encrypted_dns)：  &lt;img&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;DNS：看得见，摸得着&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;DNSSEC：看得见，摸不着，但如果 ISP DNS 是内鬼，无效&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;DoH：看不见，摸不着，需与 DNSSEC 结合确保安全性&lt;/p&gt; &lt;p&gt;DNS 不只有 A 记录(IPv4)和 AAAA 记录(IPv6)！它还会存储一些特别的信息，如 MX 记录用于邮箱服务器，TXT 记录用于存储各种公开验证数据，如申请 HTTPS 证书时用于验证域名所有权、存储服务发现数据... 因此 DNS 安全是非常重要的。&lt;/p&gt; &lt;p&gt;但假设你是一个顶级黑客，不想被任何人发现你的行踪，这还不够。安全需要不可否认性，而你需要随时否认自己做过任何操作。如果 DoH 服务器  &lt;strong&gt;监守自盗&lt;/strong&gt;，它还是可以知道我们是谁、在访问什么网站...&lt;/p&gt; &lt;p&gt;找一个更好更值得信任的 DoH 服务器固然可以，但极客喜欢在技术上保证这一点。比如，一个办法是通过代理服务器。如果我们总是通过一个可信代理进行查询。这样，DNS 服务器就看不到我们是谁。根据这一点基本原理，ODoH(Oblivious DNS over HTTPS  &lt;sup&gt;[5]&lt;/sup&gt;) 致力于更进一步解决这个问题。  &lt;img&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;Proxy 应该是一个去中心化、随机选中的服务器，否则 proxy 与 target server 可能会  &lt;strong&gt;沆瀣一气&lt;/strong&gt;，这个操作就完全没有意义了。&lt;/p&gt; &lt;p&gt;目前，大多数全球 CDN 都是通过 GeoDNS 实现的，即，权威名称服务器通过请求来源所在区域，返回离其最近机房的 IP 地址。在国内，如果使用国外提供的 DoH，或是通过代理查询 DNS，往往会得到在国外的、路由非常差的机房，拖慢了所有网站的访问速度，相当于为了安全，牺牲了效率。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;可以考虑境外 DNS 代理 +境内 DoH   &lt;sup&gt;[6]&lt;/sup&gt;&lt;/li&gt;  &lt;li&gt;或是区分中国境内网站和境外网站，选择不同的 DoH 服务器&lt;/li&gt;&lt;/ul&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;Geo-based DNS 实现原理&lt;/p&gt; &lt;p&gt;由 DNS 可见，互联网早期出现的协议基本上都是基于信任关系的，而更好的互联网，是在致力于将这些基于信任关系的旧协议，变为技术上保证安全的新协议。&lt;/p&gt; &lt;p&gt;当然，这三种情况都解决不了一件更糟糕的情况：顶级名称服务器或顶级域名名称服务器不可信。&lt;/p&gt; &lt;p&gt;虽然目前还没有过这种情况，但顶级名称服务器宕机  &lt;sup&gt;[7]&lt;/sup&gt;还是时有发生。互联网上有一些人设想并致力于解决这个权威与去中心化之间的矛盾：Handshake 名称解析系统。想知道它是怎么解决这个问题的，可以在这里了解：https://handshake.org/。&lt;/p&gt; &lt;h3&gt;网络层 和 IP 协议&lt;/h3&gt; &lt;p&gt;上一部分我们一直在说内鬼和其他攻击者，他们是怎么获得我们发给目标服务器的信息的呢？这我们就要讲一讲，包裹在链路中是如何路由的。当我们正确地拿到一个服务器的 IP 地址，还远没有万事大吉，我们只解决了 它是谁 的问题，从 IP 找到对应的服务器还有很长的路要走。&lt;/p&gt; &lt;p&gt;我们将继续解决  &lt;strong&gt;它为什么是它&lt;/strong&gt;，  &lt;strong&gt;它在哪&lt;/strong&gt;以及  &lt;strong&gt;如何找到它&lt;/strong&gt;。&lt;/p&gt; &lt;h4&gt;路由策略&lt;/h4&gt; &lt;p&gt;有没有想过，为什么我的 IP 地址是 A，它的 IP 地址是 B？如果我把我的 IP 地址改成它，会不会成为它，收到所有本该发给它的包裹呢？&lt;/p&gt; &lt;p&gt;因为 IP 地址是RIRs(Regional Internet Registries, 区域网络注册商)  &lt;sup&gt;[8]&lt;/sup&gt;统一持有、分配并追踪的，因此，谁持有哪些 IP 地址应该是已知且可查的。如果所有的 网络提供商(ISP) 和 IP 网间互联提供商(IP Transit Provider) 都尽忠职守地验证自己的广播的 IP 地址是否属于自己、转发对方的 IP 地址是否真的属于对方、别人广播的 IP 地址是否真的属于对方，那么他们均有能力发现错误并拒绝信任。因此，正常情况下是不会。&lt;/p&gt; &lt;p&gt;持有对应 IP 地址段的 resource holder 需要将 IP 挂靠在某个(或某些)特定的 AS(Autonomous System, 自治系统) 下（AS 可以自己持有，也可以自己不持有而是授权给其他 AS 广播），由它在某一个区域广播，并最终通过 BGP 接入全球网络。这是我请求将 IP 地址段授权给 Quadranet(AS8100) 广播时的授权书。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;IP 地址在某个区域被广播后，我们就可以通过一定的路由协议，比如，ARP、OSPF、BGP 找到它并与它通信了。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;当你 (192.168.1.100) 访问 某个网站(45.45.212.100) 时，一种可能的路径是:&lt;/p&gt; &lt;p&gt;你的电脑(192.168.1.100) - ARP =&amp;gt; 你的路由器(192.168.1.1 / 23.226.130.100) - NAT(Network Address Translation), ARP, RIP 或 OSPF =&amp;gt; ISP 路由(23.226.130.2) -&amp;gt; OSPF 或 IBGP =&amp;gt; 自治系统 AS 边界(23.226.128.1) - BGP =&amp;gt; 目标 AS 网关(45.45.128.1) -&amp;gt; OSPF、ARP =&amp;gt; 对方服务器(45.45.212.100)&lt;/p&gt; &lt;h4&gt;针对网络链路的攻击&lt;/h4&gt; &lt;p&gt;目前，网络上的通信是基于 IP 协议的。明文传输原 IP 与目标 IP 地址，没有任何加密和校验机制。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;如果这条路径上有内鬼，比如，就是某个 ISP 路由器。&lt;/p&gt; &lt;p&gt;如果它想劫持你对某网站的访问，只要把你 IP 层 header 的 destination 改一下，返回包 header 的 source 改一下，进行一下恶意 &amp;quot;NAT&amp;quot;，那么你就毫不知情地访问了另一个服务器。&lt;/p&gt; &lt;p&gt;或者它想要在你毫不知情的情况下审查你的访问，比如记录你每天都访问哪些网站、屏蔽你对某些网站的访问，这些都是轻而易举的事情。&lt;/p&gt; &lt;p&gt;即使没有内鬼，在这个路径中的所有人(网络意义上的邻居)都可以滥用对应的协议，通过一些手段(如ARP 欺骗  &lt;sup&gt;[9]&lt;/sup&gt;、OSPF 欺骗、BGP 劫持  &lt;sup&gt;[10]&lt;/sup&gt;等)，宣称自己就是对方服务器  &lt;code&gt;104.193.88.77&lt;/code&gt;(ARP)，或者拥有对方服务器的地址段  &lt;code&gt;104.193.88.0/24&lt;/code&gt;(OSPF / IBGP / EBGP)。如果有路由器或权威路由器的验证机制存在漏洞，被欺骗，那么它就会把对应 IP 或网段的所有包裹转发给攻击者，从而轻易地劫持网络流量。&lt;/p&gt; &lt;p&gt;这些协议中，一旦出现问题，影响最大的就是 BGP，它往往会导致本该前往一个区域的网络包裹，被送至另一个区域，造成整个区域的互联网故障甚至中断。在全球网络 BGP 上，错误路由这种事情也时有发生，每一次都会在对应区域对全球互联网产生重大影响。这称作 BGP Incidents，一般分为 BGP Hijacking、BGP Leak 以及 IP address spoofing 三种。&lt;/p&gt; &lt;h1&gt;  &lt;strong&gt;What are Routing Incidents? (Part 4)[11]&lt;/strong&gt;&lt;/h1&gt; &lt;p&gt;CloudFlare 也介绍了一个(可能的)通过 BGP 劫持进行的针对于加密货币的攻击:&lt;/p&gt; &lt;h1&gt;  &lt;strong&gt;BGP leaks and cryptocurrencies[12]&lt;/strong&gt;&lt;/h1&gt; &lt;p&gt;攻击者通过 BGP，宣告自己拥有 Amazon DNS 的 IP 地址段并劫持了 DNS 解析。当用户访问加密货币网站时，返回一个恶意网站，进而窃取用户的 Cookies / 账号密码。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;在国内发生过一次 github 和 京东 被中间人攻击的事件。&lt;/p&gt; &lt;p&gt;很不幸，网络层的所有协议都是  &lt;strong&gt;基于信任关系&lt;/strong&gt;的。除了尽力而为地传输数据，我们无法在这一层解决任何安全问题，网络层说什么，我们就会相信什么。想要缓解这个问题，只能求助于应用层、使用代理或VPN。&lt;/p&gt; &lt;p&gt;我们目前入户的 IP 地址大多数为内网地址，通过 NAT 到公网，有的甚至需要多层转换。这导致一个公网 IPv4 地址被一个或多个区域中的用户共用。&lt;/p&gt; &lt;p&gt;当 IPv6 出现的时候，很多人对它并不看好，因为每个人、每个网站使用独立 IP，运营商就可以精准根据 IP packet 定位到谁在访问什么网站，这种说法有道理吗？&lt;/p&gt; &lt;h3&gt;HTTP 与 HTTPS&lt;/h3&gt; &lt;p&gt;经过 DNS 解析以及路由，不管最终对方是不是我们想要的服务器，现在我们要和它建立连接了。在浏览器中，最常用的协议是 HTTP 和 HTTPS。&lt;/p&gt; &lt;h4&gt;针对 HTTP 协议的攻击&lt;/h4&gt; &lt;p&gt;HTTP(Hypertext Transfer Protocol) 协议通过 TCP 建立连接，然后明文传输所有的内容，包括请求的域名、路径、请求内容、响应内容... 以及能想到的所有信息，而且，无法验证响应服务器的身份。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;明文？缺少验证机制？那么  &lt;strong&gt;内鬼&lt;/strong&gt;又要来了。根据上面路由策略相关的知识，对于它们来说，窃听、篡改、伪造、重放、拒绝服务，都是轻而易举的事情。早期的互联网，运营商可以在页面上插入小广告(不过最常见的还是通过 DNS 劫持来实现)，或是搜索某些关键词时，连接被重置。&lt;/p&gt; &lt;p&gt;在没有 HTTPS 的年代，在注册或登录一些网站，传输密码时，为了防止被窃听，常见的方法是由后端返回一个 RSA 公钥给前端，前端通过这个公钥加密自己的请求发送的密码，后端用私钥解密，在一定程度上提高一下安全性。&lt;/p&gt; &lt;p&gt;比如微博移动版目前还会返回 pubkey，不过已经不用它来加密密码了。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;事实上，如果链路上有内鬼，且盯上了你或者某些服务，这种做法并没有什么大用。虽然看起来很安全，但在攻击者眼中，窃听和篡改的难度几乎一样。它能监视你的请求，那么它同样可以篡改服务器给你的公钥，换成它的公钥，让你一无所知地就把密码加密给攻击者。&lt;/p&gt; &lt;p&gt;（所以早期网上银行的 U盾 或者 ActiveX 控件还是有用的）&lt;/p&gt; &lt;p&gt;好在，我们现在有了广泛应用的 HTTPS。&lt;/p&gt; &lt;h4&gt;针对 HTTPS 的攻击和缓解方法&lt;/h4&gt; &lt;p&gt;HTTPS 通过 TLS(Transport Layer Security, 传输层安全)，完整在应用层实现了防止窃听、篡改、伪造、重放和抵赖的功能。HTTPS 原理也通常在前端面试中被考察。简单回顾一下：&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;来自 https://segmentfault.com/a/1190000021494676，最新的 TLS 1.3 加密方式与之有较大不同&lt;/p&gt; &lt;p&gt;需要注意，HTTPS 的安全性是建立在应用层的，底层的 TCP 和 UDP 协议会泄漏原 IP、目标 IP、使用的协议等信息，并非绝对保密。&lt;/p&gt; &lt;h5&gt;信任证书或 SECRET 泄漏导致的中间人攻击&lt;/h5&gt; &lt;p&gt;HTTPS 在大多数情况下都足够安全，可是，它仍然有很多被攻破的方法。比如，服务端可能因为各种原因导致证书私钥泄漏。或者客户端主动安装了不信任的证书、由于恶意软件等共享了 pre-shared key 等导致的中间人攻击。&lt;/p&gt; &lt;p&gt;比如，如果安装了 Bifrost，且信任了它提供的证书，Bifrost 就可以解密我们的 HTTPS 请求。&lt;/p&gt; &lt;p&gt;  &lt;img&gt;&lt;/img&gt;  &lt;img&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;或是导出了  &lt;code&gt;SSLKEYLOGFILE&lt;/code&gt;后，这段时间的 HTTPS 会话就可以被解密 (如图为 TLS 1. 3 的 key log)。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;还有一些隐秘的、复杂的原因导致 HTTPS 不再安全。&lt;/p&gt; &lt;h5&gt;权威机构错误签发证书或被攻击&lt;/h5&gt; &lt;p&gt;最恐怖的就是权威机构胡乱签发证书。如果权威机构疏于验证就签发证书，或者出于某种目的故意签发错误的证书，那么它可以将全世界所有 HTTPS 变得不再安全。更恐怖的是，这种事情还真的发生过  &lt;sup&gt;[13]&lt;/sup&gt;... 这也导致目前中国境内没有受信任的 Root CA。如果真的发生了这种事情，只能寄希望于浏览器和操作系统快速做出反应，移除对应根证书的信任。&lt;/p&gt; &lt;p&gt;不过好在，目前浏览器均要求证书必须符合Certificate Transparency  &lt;sup&gt;[14]&lt;/sup&gt;才会被信任，很多组织会监督证书的签发及使用，供网站主和监督组织发现这些乱签证书的 CA。而且，TLS 是 完全前向保密(Perfect Forward Secrecy) 的，即使某一天出现了乱签证书或密钥泄漏这种事情，也无法解密之前已经发生的会话，或伪造以前发生的会话。&lt;/p&gt; &lt;p&gt;如果一个权威机构或中间机构被攻击，造成私钥泄漏等，使用其已经签发的证书的网站均不再安全。目前浏览器可以通过 OCSP(Online Certificate Status Protocol) 来检查证书状态是否正常、是否被吊销。&lt;/p&gt; &lt;h5&gt;降级至 http 的降级攻击&lt;/h5&gt; &lt;p&gt;针对 HTTPS 的中间人攻击通常出现于建立连接前，因为一旦建立了 HTTPS 连接，客户端与服务端所有的通信都是加密的，操作起来不太方便。因此，最常见的做法是，攻击者发现你试图建立 HTTPS 连接，会直接拦截这个请求，并伪造服务器返回不支持 HTTPS，请使用 HTTP。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;对于这种攻击，我们并不是毫无对策。HSTS(HTTP Strict Transport Security)  &lt;sup&gt;[15]&lt;/sup&gt;可以在一定程度上缓解这种问题。如果一个网站从不使用 HTTP，那么它可以通过设置 HTTP Header，强制浏览器使用 HTTPS 并记住一段时间。&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;Strict-Transport-Security: max-age=&amp;lt;expire-time&amp;gt;   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;根据标准，配置了 HSTS 的网站，应当没有任何办法继续使用 HTTP 连接。如果 https 失效，浏览器报错时，没有 继续前往 xxx 这一选项，就说明这个网站配置了 HSTS。&lt;/p&gt; &lt;p&gt;  &lt;img&gt;&lt;/img&gt;  &lt;img&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;不过 Chrome 也留了个后门，在这个页面输入  &lt;code&gt;thisisunsafe&lt;/code&gt;后，就可以无视这个警告了。&lt;/p&gt; &lt;p&gt;但 HSTS 的首个请求还是 HTTP，还是可以被劫持，浏览器通常会写死一些域名强制启用 HSTS，但还是不太够，因此，也有人提出基于 DNS 的 HSTS 等更好的实现。&lt;/p&gt; &lt;h5&gt;降级至低版本安全套件或加密方式的降级攻击&lt;/h5&gt; &lt;p&gt;而且，HTTPS 并不是生来就安全的。目前常用的加密方式是 TLS 1.3，而之前曾采用的 SSL 3.0、TLS 1.0、1.1 都各有各的漏洞以及对应的破解方法  &lt;sup&gt;[16]&lt;/sup&gt;。因此，攻击者也在 HSTS 生效的情况下，拦截协商请求，伪造服务器返回只支持低版本 HTTPS 套件，强制浏览器进行降级并加以破解，这也是目前的 HSTS 覆盖不到的。&lt;/p&gt; &lt;p&gt;这是几种常见的针对 HTTPS 的降级攻击。&lt;/p&gt; &lt;h4&gt;HTTPS 的其他缺陷&lt;/h4&gt; &lt;p&gt;假设我们考虑了之前所有的安全方案，去访问 Google：用 Cloudflare DoH，没人能阻止我取得 Google 的 IP 地址；用谷歌最新的 IPv6 地址，没有人能从 IP 知道对方是谷歌；用 HTTPS，没有人知道我在和谁建立连接，访问什么内容，现在链路上的人应该一无所知了吧？&lt;/p&gt; &lt;p&gt; 可是我发现，还是上不了 Google....&lt;/p&gt; &lt;p&gt;这是因为，一个广泛使用的 HTTPS 扩展，SNI(Server Name Indication)，存在致命问题，会泄漏你要访问的域名。因为一个 IP 地址上可以部署多个服务器，而 HTTPS 需要域名正确的证书才能工作，服务器在与你建立连接前，需要知道你要访问的域名，并提供对应域名的 HTTPS 证书。&lt;/p&gt; &lt;p&gt;  &lt;img&gt;&lt;/img&gt;  &lt;img&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;你的浏览器会将域名明文发送给服务器，以供对方决定应该使用哪个证书。&lt;/p&gt; &lt;p&gt;这给内鬼和其他攻击者们提供了可乘之机，导致 HTTPS 的保密性功亏一篑。而且，攻击者还可以用这个信息将域名和 IP 地址建立联系，启发式地知道后续这个 IP 地址对应的域名。&lt;/p&gt; &lt;p&gt;好消息是，TLS 1.3 可以使用ESNI(Encryped SNI)  &lt;sup&gt;[17]&lt;/sup&gt;扩展来解决这个问题。ESNI 依赖 DNS，DNS 依赖 DNSSEC 和 DoH，而 DoH 又依赖 TLS... 安全是薄弱的，也是相辅相成的，任何一个环节出了问题，其他环节再安全也没有用。&lt;/p&gt; &lt;p&gt;CloudFlare 提供了一个检测服务  &lt;sup&gt;[18]&lt;/sup&gt;，可以帮助你确认自己的浏览器是否安全。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;h3&gt;浏览器&lt;/h3&gt; &lt;p&gt;通过这些技术，我们和目标服务器建立好了可信信道，可以正式开始通信了。&lt;/p&gt; &lt;p&gt;但是... 如果对方是坏人，怎么办?&lt;/p&gt; &lt;h4&gt;利用浏览器漏洞的攻击&lt;/h4&gt; &lt;p&gt;在 IE 时代，经常出现点了陌生链接就会中病毒的情况。即使是目前的 Chrome 有比较完善的安全机制，也免不了在某些前提下，出现一些可供恶意利用的漏洞。比如在微信上点击某个链接，就可以启动某个应用程序或执行某些指令...&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;一旦浏览器漏洞被利用，通常会导致整个系统被攻破，影响范围较大，当然，相应地利用难度也大。&lt;/p&gt; &lt;h4&gt;利用 Web 标准漏洞的攻击&lt;/h4&gt; &lt;p&gt;Web 标准不够完善的时候，旧版本浏览器也可能会有很多跨域的问题，攻击者可以通过各种手段跨域访问，窃取 Cookie。现代浏览器会尽可能保护我们的安全，但还是有各种奇奇怪怪的方法进行攻击，而且防不胜防... 我们来举一些已知的例子：&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;DNS&lt;/strong&gt;  &lt;strong&gt;重绑定攻击&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;一般来说，当向不同域发起请求时，会被浏览器认为违反同源策略，并通过 Preflight 方式检查对应请求是否合理或拦截对应的请求，以确保安全性。&lt;/p&gt; &lt;p&gt;假设用户在浏览 A 网站 a.attacker (IP: 192.0.0.1)，B 网站 b.victim (192.0.0.2) 有一个  &lt;code&gt;/get_password&lt;/code&gt;接口，正常情况下，A 无法向 B 请求这个资源。但如果此时 A 修改了自己的 DNS 解析为  &lt;code&gt;192.0.0.2&lt;/code&gt;，此时，它便可以通过访问  &lt;code&gt;a.attacker/get_password&lt;/code&gt;轻而易举地取得 B 的资源，且没有违反同源策略。&lt;/p&gt; &lt;p&gt;在现实中，因为大多数网站都有 Host Check，且不会和 a 持有相同的 HTTPS 证书，因此成功攻击的可能性比较小。它通常被用于外网对内网设备的检测和攻击，比如攻击内网路由器，或是智能设备、物联网设备等。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;浏览器也想了一些办法来解决这些问题，如 DNS Pinning。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;基于跨网络缓存投毒的攻击&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;浏览器会根据服务器的缓存控制，缓存一些资源，并在后续访问时，直接读取这些资源，这在外部网络访问时，通常不会发生什么问题，但是，如果你连接了公共 wifi，就不是这回事了。&lt;/p&gt; &lt;p&gt;假如你的家里有个路由器，它通过  &lt;code&gt;my-awesome-router.com&lt;/code&gt;进行访问，并且会加载一个  &lt;code&gt;/jquery.js&lt;/code&gt;提供用户界面访问。内网设备一般无法提供 HTTPS 证书，否则会有严重安全问题。&lt;/p&gt; &lt;p&gt;通常在外饭店或商场，我们连接的公共 wifi 需要打开一个登录页面，登录后，才可以上网。但如果这个热点是恶意的，当你打开它的登录界面时，它可以跳转到任意域名，如  &lt;code&gt;my-awesome-router.com&lt;/code&gt;用于登录，进而可以在这一域名下缓存资源，比如，  &lt;code&gt;/jquery.js&lt;/code&gt;。&lt;/p&gt; &lt;p&gt;当你回到家，登录自己的路由器管理界面时，攻击者就有能力在不知情的情况下，控制你的整个内网设备。&lt;/p&gt; &lt;p&gt;当然对于那些非 HTTPS 的网站，比如，公司内网某个页面没有 HTTPS (HTTPS 不会和 HTTP 共享缓存，如果攻击者没有能力破解 HTTPS，那么它不能写入 HTTPS 缓存)，它也可以以此方式向对应页面注入脚本，借助安全漏洞向内网进行攻击。&lt;/p&gt; &lt;h4&gt;基于信息收集的旁路攻击&lt;/h4&gt; &lt;p&gt;还有许多针对特定网站的旁路攻击，会泄漏信息。&lt;/p&gt; &lt;p&gt;如果你想要浏览一些不希望被人发现的网站，你会怎么做？隐私模式？开个新用户？使用代理？不幸的是，这些都没有用。一些浏览器特性，会泄漏你的唯一特征，并最终确定你访问过哪些网站。这种技术称为浏览器指纹  &lt;sup&gt;[19]&lt;/sup&gt;。&lt;/p&gt; &lt;p&gt;如 FingerprintJS，它可以轻而易举地识别你是否处于隐私模式，并确定你的身份 (而且，这个网站的恐怖之处是，已知的反指纹方法对它基本都没用)。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;还有一些通过被称作 supercookie 的技术来实现追踪的方法。如，浏览器通常会缓存 favicon，那么它通过给不同访问者生成不同的 favicon 就能确定你是谁，追踪你的访问记录。或者，利用浏览器会缓存 HSTS...&lt;/p&gt; &lt;p&gt;一些相关技术的测试网址&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;https://amiunique.org/fp&lt;/li&gt;  &lt;li&gt;https://fingerprintjs.com/github/&lt;/li&gt;  &lt;li&gt;https://audiofingerprint.openwpm.com/&lt;/li&gt;  &lt;li&gt;https://supercookie.me/&lt;/li&gt;  &lt;li&gt;https://mp.weixin.qq.com/s/gFCGM7ANOxHqYxGItyA_CA&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;最薄弱的环节: 你&lt;/h3&gt; &lt;p&gt;安全系统中最薄弱的环节是人。互联网上最容易成功的的攻击是暴力破解。只要你的 IP 地址在公网上可见，每天就会有成千上万个扫描器尝试各种密码组合，利用各种常见软件的漏洞，攻破你的系统。&lt;/p&gt; &lt;p&gt;一旦你的系统或你被攻破，那么一切网络安全手段都没有任何作用。常见的被攻击的原因：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;连接了某个恶意的公共 Wifi，被劫持、窃听或投毒&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;安装了某个恶意软件，执行了某个病毒文件&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;通过 frp 等软件将端口暴露至公网，使用弱密码，关闭防火墙，开放常见端口&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;使用有安全漏洞的软件，如    &lt;code&gt;redis&lt;/code&gt;，    &lt;code&gt;JAVA Apache log4j&lt;/code&gt;，且没有及时更新&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;社会工程学&lt;/p&gt;&lt;/li&gt;  &lt;ul&gt;   &lt;li&gt;被欺骗点击有病毒的链接、安装恶意软件或者有漏洞的正常软件&lt;/li&gt;   &lt;li&gt;被欺骗主动泄漏你的密码或凭据，如钓鱼、恐吓 或 Self-XSS&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img&gt;&lt;/img&gt;  &lt;img&gt;&lt;/img&gt;&lt;/p&gt; &lt;h3&gt;网络链路前的物理攻击&lt;/h3&gt; &lt;p&gt;如果你的物理位置对攻击者已知，那么它还可以做更多事情。&lt;/p&gt; &lt;p&gt;比如，伪基站。在你的附近放一个信号更强的伪基站，轻而易举地就能骗取你的手机加入它的网络，这是针对 2G 网络的攻击，WLAN 是否有同样的攻击方式呢？&lt;/p&gt; &lt;p&gt;我们工区的厕所和楼梯间 Bytedance Inc. 的信号比较差，如果有人想要攻击 Bytedance，他是不是也可以在这些地方放一个信号更强、也叫 Bytedance Inc 的设备，欺骗你的电脑、手机连接它的路由器，获取你的凭据，进而实施更多的攻击呢？这种攻击方式叫做 Evil Twin，可以通过谷歌详细了解。&lt;/p&gt; &lt;p&gt;当然，我们工区的内网使用的 Wifi 安全性是 WPA2 Enterprise + 证书的方式。在 WPA2 的安全方式下，这样做不太可能会成功，因为设备和路由器之间的认证不是通过密码，而是通过一些方式  &lt;sup&gt;[20]&lt;/sup&gt;证明自己拥有访问对应网络的凭据，就像 SSH 一样。但对于安全性更差的 WPA 或是没有密码的路由器，这样就可以轻而易举地通过 Evil Twin 对其进行攻击。&lt;/p&gt; &lt;h3&gt;总结&lt;/h3&gt; &lt;p&gt;不同方式，不同层会泄露什么信息，有哪些不安全因素？&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;TCP/UDP/IP:&lt;/p&gt;&lt;/li&gt;  &lt;ul&gt;   &lt;li&gt;对运营商：你使用宽带/手机信号的精确位置，你是谁。&lt;/li&gt;   &lt;li&gt;对链路上的所有人：你的 IP 地址及归属地，进行网络劫持或污染，修改请求与响应，社会工程学攻击，进而阻止或监视你的访问。&lt;/li&gt;   &lt;li&gt;缓解：VPN 与 Proxy&lt;/li&gt;&lt;/ul&gt;  &lt;li&gt;   &lt;p&gt;DNS:&lt;/p&gt;&lt;/li&gt;  &lt;ul&gt;   &lt;li&gt;对链路上的所有人：访问的网站，抢答、篡改、拦截返回的 IP 地址进而阻止或监视你的访问。&lt;/li&gt;   &lt;li&gt;缓解：DNSSEC 与 DoH&lt;/li&gt;&lt;/ul&gt;  &lt;li&gt;   &lt;p&gt;HTTP:&lt;/p&gt;&lt;/li&gt;  &lt;ul&gt;   &lt;li&gt;对链路上的所有人：你访问的完整网址、凭据、请求、内容，任意窃听、篡改、伪造、重放。&lt;/li&gt;   &lt;li&gt;缓解：HTTPS&lt;/li&gt;&lt;/ul&gt;  &lt;li&gt;   &lt;p&gt;HTTPS:&lt;/p&gt;&lt;/li&gt;  &lt;ul&gt;   &lt;li&gt;自带防止 窃听、篡改、伪造、重放(TLS 1.3 zero-rtt 除外)、抵赖(client cert) 的功能&lt;/li&gt;   &lt;li&gt;对链路上的所有人：正在使用 HTTPS 协议，(使用 SNI 或 TLS &amp;lt; 1.2) 目标网站的域名。&lt;/li&gt;   &lt;li&gt;缓解：TLS 1.3 + ESNI + 禁用 zero-rtt。&lt;/li&gt;&lt;/ul&gt;  &lt;li&gt;   &lt;p&gt;Chrome:&lt;/p&gt;&lt;/li&gt;  &lt;ul&gt;   &lt;li&gt;对你访问的网站：你访问过哪些网站，关联你是谁、你在做什么、定位，根据授权获取的视频、声音、剪贴板等信息。&lt;/li&gt;   &lt;li&gt;缓解：区分浏览器访问不信任网站，减少授权。&lt;/li&gt;&lt;/ul&gt;  &lt;li&gt;   &lt;p&gt;你以及与你有物理接触的人:&lt;/p&gt;&lt;/li&gt;  &lt;ul&gt;   &lt;li&gt;对所有人：任何信息。&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt; &lt;p&gt;网络不是法外之地，找到你只是时间和成本的问题。怎么办，怎么办呢？&lt;/p&gt; &lt;p&gt;高度匿名的洋葱网络是否可以解决这些问题？去中心化的 Web 3.0 是否可以解决这些问题？这些话题，就只能下次再说了...&lt;/p&gt; &lt;h3&gt;小测验&lt;/h3&gt; &lt;p&gt;Q1: 假如有人不想让你访问 google.com，它可以怎么做？&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;对大多数人来说，基于 DNS 劫持和抢答的方式是最有效的，可以部署在链路中或链路外&lt;/li&gt;  &lt;li&gt;对使用 http 的用户，进行 http 包分析并拦截或抢答&lt;/li&gt;  &lt;li&gt;对使用 https 的用户，通过 SNI 分析目标域名并拦截对应 IP packet，并启发式地记录 IP 与 域名对应关系&lt;/li&gt;  &lt;li&gt;对于使用 ESNI 的用户，根据 IP 域名对应关系，拦截对应 IP packet&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;最近比较火的离职倾向分析...&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;除了上述方式，如果是公司设备，还有更多的可能... 比如描述文件或组策略等&lt;/p&gt; &lt;p&gt;Q2: 当前，很多代理服务器以 HTTPS 方式实现，为什么它们不使用没有特征的更安全的加密方式？&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;没有特征才是最大的特征，可以被轻易识别为异常流量并加以拦截&lt;/li&gt;  &lt;li&gt;混杂在正常流量中的协议更不容易引起注意&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Q3: 假设一个人非常注重网络链路安全，他的网络链路中没有内鬼，如何定位他在哪里？&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;利用对方软件的漏洞，如 QQ、微信、浏览器 等&lt;/li&gt;  &lt;li&gt;进行社会工程学攻击&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Q &amp;amp; A&lt;/h3&gt; &lt;h4&gt;什么是社会工程学&lt;/h4&gt; &lt;ul&gt;  &lt;li&gt;您，抖音，信誉，400，加Q，提现&lt;/li&gt;  &lt;li&gt;您好，公司今天发放新年时，发现您的卡发生异常，请及时点击链接   &lt;sup&gt;[21]&lt;/sup&gt;更新您的工资卡信息。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;社会工程学核心特点：&lt;/p&gt; &lt;p&gt;对方没有掌握你的某些信息，如，刷抖音时间长，或者掌握了部分信息，如，今天公司发红包，你的工资卡号、生日、手机号。通过一些途径，获取更多信息。大体上分为以下三种基本方法：&lt;/p&gt; &lt;p&gt;猜。对方通过你的生日、姓名缩写、各种弱密码，直接登录了你的手机、 SSO 以及 某些系统。&lt;/p&gt; &lt;p&gt;可以在这里查查你的 email、密码和电话有没有泄漏：https://haveibeenpwned.com/&lt;/p&gt; &lt;p&gt;骗。通过聊天工具、钓鱼邮件、电话、短信，骗取你提供给它更多的信息。打开恶意网站，运行病毒、木马程序等也属于社会工程学的一种。&lt;/p&gt; &lt;p&gt;骗的 6 大特点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;冒充权威：您好，我是抖音官方人员，我们这边有兼职刷抖音赚钱的活动。&lt;/li&gt;  &lt;li&gt;威胁：请于 1 月 26 日 12:00 前，确认您的银行卡信息，否则红包将无法发放。&lt;/li&gt;  &lt;li&gt;共识：您身边人都在做，比如您的同事小王，3 天就提现了 3000 块&lt;/li&gt;  &lt;li&gt;稀缺性：您可是我们挑选的幸运用户，只需支付 8000 元就能买下抖音公司。&lt;/li&gt;  &lt;li&gt;紧急：我们这个活动可就剩半天了，您再不买我们就要永久降价了，以后没办法用这个价格买到了。&lt;/li&gt;  &lt;li&gt;亲近感：我正在公司实习，如果笔卖不出去我就要被开除了，您能帮忙扫扫码帮帮我，交个朋友？点个链接，就耽误您 3 分钟时间。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;非交互式。对方通过公开信息搜集(如搜索引擎、QQ 空间、微博、论坛)、社工库 等获取你的 群关系、开房记录 等更多信息。或者通过以上提到的网络或物理攻击方法，如，在常用网站上挂马、黑掉路由器等方法，在不知情中进行监视或攻击。&lt;/p&gt; &lt;h2&gt;❤️ 谢谢支持&lt;/h2&gt; &lt;p&gt;以上便是本次分享的全部内容，希望对你有所帮助^_^&lt;/p&gt; &lt;p&gt;喜欢的话别忘了   &lt;strong&gt;分享、点赞、收藏&lt;/strong&gt; 三连哦~。&lt;/p&gt; &lt;p&gt;欢迎关注公众号   &lt;strong&gt;ELab团队&lt;/strong&gt; 收获大厂一手好文章~&lt;/p&gt; &lt;blockquote&gt;  &lt;p&gt;我们来自字节跳动，是旗下大力教育前端部门，负责字节跳动教育全线产品前端开发工作。&lt;/p&gt;  &lt;p&gt;我们围绕产品品质提升、开发效率、创意与前沿技术等方向沉淀与传播专业知识及案例，为业界贡献经验价值。包括但不限于性能监控、组件库、多端技术、Serverless、可视化搭建、音视频、人工智能、产品设计与营销等内容。&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;字节跳动校/社招内推码: UCDW4MK&lt;/p&gt; &lt;p&gt;投递链接: job.toutiao.com/s/Rb21Dk9  &lt;sup&gt;[22]&lt;/sup&gt;&lt;/p&gt; &lt;h3&gt;参考资料&lt;/h3&gt;[1] &lt;p&gt;Anycast:  &lt;em&gt;https://en.wikipedia.org/wiki/Anycast&lt;/em&gt;&lt;/p&gt;[2] &lt;p&gt;缓存投毒:  &lt;em&gt;https://www.cloudflare.com/learning/dns/dns-cache-poisoning/&lt;/em&gt;&lt;/p&gt;[3] &lt;p&gt;DNSSEC:  &lt;em&gt;https://www.icann.org/resources/pages/dnssec-what-is-it-why-important-2019-03-20-zh&lt;/em&gt;&lt;/p&gt;[4] &lt;p&gt;DNSSEC 实战 - 掘金:  &lt;em&gt;https://juejin.cn/post/7044416908921159717&lt;/em&gt;&lt;/p&gt;[5] &lt;p&gt;Oblivious DNS over HTTPS:  &lt;em&gt;https://blog.cloudflare.com/oblivious-dns/&lt;/em&gt;&lt;/p&gt;[6] &lt;p&gt;境内 DoH:  &lt;em&gt;https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD%20DoH&lt;/em&gt;&lt;/p&gt;[7] &lt;p&gt;顶级名称服务器宕机:  &lt;em&gt;https://en.wikipedia.org/wiki/Distributed_denial-of-service_attacks_on_root_nameservers&lt;/em&gt;&lt;/p&gt;[8] &lt;p&gt;RIRs(Regional Internet Registries, 区域网络注册商):  &lt;em&gt;https://en.wikipedia.org/wiki/Regional_Internet_registry&lt;/em&gt;&lt;/p&gt;[9] &lt;p&gt;ARP 欺骗:  &lt;em&gt;https://en.wikipedia.org/wiki/ARP_spoofing&lt;/em&gt;&lt;/p&gt;[10] &lt;p&gt;BGP 劫持:  &lt;em&gt;https://en.wikipedia.org/wiki/BGP_hijacking&lt;/em&gt;&lt;/p&gt;[11] &lt;p&gt;What are Routing Incidents? (Part 4):  &lt;em&gt;https://en.wikipedia.org/wiki/ARP_spoofing&lt;/em&gt;&lt;/p&gt;[12] &lt;p&gt;BGP leaks and cryptocurrencies:  &lt;em&gt;https://blog.cloudflare.com/bgp-leaks-and-crypto-currencies/&lt;/em&gt;&lt;/p&gt;[13] &lt;p&gt;还真的发生过:  &lt;em&gt;https://en.wikipedia.org/wiki/Root_certificate#Incidents_of_root_certificate_misuse&lt;/em&gt;&lt;/p&gt;[14] &lt;p&gt;Certificate Transparency:  &lt;em&gt;https://certificate.transparency.dev/&lt;/em&gt;&lt;/p&gt;[15] &lt;p&gt;HSTS(HTTP Strict Transport Security) :  &lt;em&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security&lt;/em&gt;&lt;/p&gt;[16] &lt;p&gt;漏洞以及对应的破解方法:  &lt;em&gt;https://en.wikipedia.org/wiki/Transport_Layer_Security#Security&lt;/em&gt;&lt;/p&gt;[17] &lt;p&gt;ESNI(Encryped SNI):  &lt;em&gt;https://blog.cloudflare.com/encrypted-sni/&lt;/em&gt;&lt;/p&gt;[18] &lt;p&gt;一个检测服务:  &lt;em&gt;https://encryptedsni.com/&lt;/em&gt;&lt;/p&gt;[19] &lt;p&gt;浏览器指纹:  &lt;em&gt;https://zhuanlan.zhihu.com/p/94158920&lt;/em&gt;&lt;/p&gt;[20] &lt;p&gt;一些方式:  &lt;em&gt;https://en.wikipedia.org/wiki/IEEE_802.11i-2004#Four-way_handshake&lt;/em&gt;&lt;/p&gt;[21] &lt;p&gt;点击链接:  &lt;em&gt;https://www.youtube.com/watch?v=dQw4w9WgXcQ&lt;/em&gt;&lt;/p&gt;[22] &lt;p&gt;job.toutiao.com/s/Rb21Dk9:  &lt;em&gt;https://job.toutiao.com/s/Rb21Dk9&lt;/em&gt;&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>dev</category>
      <guid isPermaLink="true">https://itindex.net/detail/62188-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8</guid>
      <pubDate>Sun, 03 Apr 2022 00:00:00 CST</pubDate>
    </item>
    <item>
      <title>使用 Cilium 增强 Kubernetes 网络安全</title>
      <link>https://itindex.net/detail/62111-cilium-%E5%A2%9E%E5%BC%BA-kubernetes</link>
      <description>&lt;h2&gt;TL;DR&lt;/h2&gt; &lt;p&gt;在本篇，我们分别使用了 Kubernetes 原生的网络策略和 Cilium 的网络策略实现了 Pod 网络层面的隔离。不同的是，前者只提供了基于 L3/4 的网络策略；后者支持 L3/4、L7 的网络策略。&lt;/p&gt; &lt;p&gt;通过网络策略来提升网络安全，可以极大降低了实现和维护的成本，同时对系统几乎没有影响。&lt;/p&gt; &lt;p&gt;尤其是基于 eBPF 技术的 Cilium，解决了内核扩展性不足的问题，从内核层面为工作负载提供安全可靠、可观测的网络连接。&lt;/p&gt; &lt;h2&gt;背景&lt;/h2&gt; &lt;p&gt;为什么说 Kubernetes 网络存在安全隐患？集群中的 Pod 默认是未隔离的，也就是 Pod 之间的网络是互通的，可以互相通信的。&lt;/p&gt; &lt;p&gt;这里就会有问题，比如由于数据敏感服务 B 只允许特定的服务 A 才能访问，而服务 C 无法访问 B。要禁止服务 C 对服务 B 的访问，可以有几种方案：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;在 SDK 中提供通用的解决方案，实现白名单的功能。首先请求要带有来源的标识，然后服务端可以接收规则设置放行特定标识的请求，拒绝其他的请求。&lt;/li&gt;  &lt;li&gt;云原生的解决方案，使用服务网格的 RBAC、mTLS 功能。RBAC 实现原理与应用层的 SDK 方案类似，但是属于基础设施层的抽象通用方案；mTLS 则会更加复杂一些，在连接握手阶段进行身份验证，涉及证书的签发、验证等操作。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;以上两种方案各有利弊：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;SDK 的方案实现简单，但是规模较大的系统会面临升级推广困难、多语言支持成本高等问题。&lt;/li&gt;  &lt;li&gt;服务网格的方案是基础设施层的通用方案，天生支持多语言。但是对于未落地网格的用户来说，架构变化大，成本高。如果单纯为了解决安全问题，使用网格方案性价比又很低，且不说现有网格实现等落地难度大及后期的使用维护成本高。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;继续向基础设施下层找方案，从网络层入手。Kubernetes 提供了的网络策略 *NetworkPolicy*  &lt;sup&gt;[1]&lt;/sup&gt;，则可以实现“网络层面的隔离”。&lt;/p&gt; &lt;h2&gt;示例应用&lt;/h2&gt; &lt;p&gt;在进一步演示 NetworkPolicy 的方案之前，先介绍用于演示的示例应用。我们使用 Cilium 在互动教程 Cilium getting started  &lt;sup&gt;[2]&lt;/sup&gt; 中使用的“星球大战”场景。&lt;/p&gt; &lt;p&gt;这里有三个应用，星战迷估计不会陌生：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;死星 deathstar：在    &lt;code&gt;80&lt;/code&gt; 端口提供 web 服务，有 2 个 副本，通过 Kubernetes Service 的负载均衡为   &lt;strong&gt;帝国战机&lt;/strong&gt;对外提供”登陆“服务。&lt;/li&gt;  &lt;li&gt;钛战机 tiefighter：执行登陆请求。&lt;/li&gt;  &lt;li&gt;X翼战机 xwing：执行登陆请求。&lt;/li&gt;&lt;/ul&gt; &lt;img&gt;&lt;/img&gt; &lt;blockquote&gt;  &lt;p&gt;如图所示，我们使用了 Label 对三个应用进行了标识：   &lt;code&gt;org&lt;/code&gt; 和    &lt;code&gt;class&lt;/code&gt;。在执行网络策略时，我们会使用这两个标签识别负载。&lt;/p&gt;&lt;/blockquote&gt; &lt;pre&gt;  &lt;code&gt;# app.yaml   &lt;br /&gt;---   &lt;br /&gt;apiVersion: v1   &lt;br /&gt;kind: Service   &lt;br /&gt;metadata:   &lt;br /&gt;  name: deathstar   &lt;br /&gt;  labels:   &lt;br /&gt;    app.kubernetes.io/name: deathstar   &lt;br /&gt;spec:   &lt;br /&gt;  type: ClusterIP   &lt;br /&gt;  ports:   &lt;br /&gt;  - port: 80   &lt;br /&gt;  selector:   &lt;br /&gt;    org: empire   &lt;br /&gt;    class: deathstar   &lt;br /&gt;---   &lt;br /&gt;apiVersion: apps/v1   &lt;br /&gt;kind: Deployment   &lt;br /&gt;metadata:   &lt;br /&gt;  name: deathstar   &lt;br /&gt;  labels:   &lt;br /&gt;    app.kubernetes.io/name: deathstar   &lt;br /&gt;spec:   &lt;br /&gt;  replicas: 2   &lt;br /&gt;  selector:   &lt;br /&gt;    matchLabels:   &lt;br /&gt;      org: empire   &lt;br /&gt;      class: deathstar   &lt;br /&gt;  template:   &lt;br /&gt;    metadata:   &lt;br /&gt;      labels:   &lt;br /&gt;        org: empire   &lt;br /&gt;        class: deathstar   &lt;br /&gt;        app.kubernetes.io/name: deathstar   &lt;br /&gt;    spec:   &lt;br /&gt;      containers:   &lt;br /&gt;      - name: deathstar   &lt;br /&gt;        image: docker.io/cilium/starwars   &lt;br /&gt;---   &lt;br /&gt;apiVersion: v1   &lt;br /&gt;kind: Pod   &lt;br /&gt;metadata:   &lt;br /&gt;  name: tiefighter   &lt;br /&gt;  labels:   &lt;br /&gt;    org: empire   &lt;br /&gt;    class: tiefighter   &lt;br /&gt;    app.kubernetes.io/name: tiefighter   &lt;br /&gt;spec:   &lt;br /&gt;  containers:   &lt;br /&gt;  - name: spaceship   &lt;br /&gt;    image: docker.io/tgraf/netperf   &lt;br /&gt;---   &lt;br /&gt;apiVersion: v1   &lt;br /&gt;kind: Pod   &lt;br /&gt;metadata:   &lt;br /&gt;  name: xwing   &lt;br /&gt;  labels:   &lt;br /&gt;    app.kubernetes.io/name: xwing   &lt;br /&gt;    org: alliance   &lt;br /&gt;    class: xwing   &lt;br /&gt;spec:   &lt;br /&gt;  containers:   &lt;br /&gt;  - name: spaceship   &lt;br /&gt;    image: docker.io/tgraf/netperf   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;Kubernetes 网络策略&lt;/h2&gt; &lt;p&gt;可以通过官方文档  &lt;sup&gt;[3]&lt;/sup&gt;获取更多详细信息，这里我们直接放出配置：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;# native/networkpolicy.yaml   &lt;br /&gt;apiVersion: networking.k8s.io/v1   &lt;br /&gt;kind: NetworkPolicy   &lt;br /&gt;metadata:   &lt;br /&gt;  name: policy   &lt;br /&gt;  namespace: default   &lt;br /&gt;spec:   &lt;br /&gt;  podSelector:   &lt;br /&gt;    matchLabels:   &lt;br /&gt;      org: empire   &lt;br /&gt;      class: deathstar   &lt;br /&gt;  policyTypes:   &lt;br /&gt;  - Ingress   &lt;br /&gt;  ingress:   &lt;br /&gt;  - from:   &lt;br /&gt;    - podSelector:   &lt;br /&gt;        matchLabels:   &lt;br /&gt;          org: empire   &lt;br /&gt;    ports:   &lt;br /&gt;    - protocol: TCP   &lt;br /&gt;      port: 80   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;ul&gt;  &lt;li&gt;   &lt;code&gt;podSelector&lt;/code&gt; ：表示要应用网络策略的工作负载均衡，通过 label 选择到了 deathstar 的 2 个 Pod。&lt;/li&gt;  &lt;li&gt;   &lt;code&gt;policyTypes&lt;/code&gt; ：表示流量的类型，可以是    &lt;code&gt;Ingress&lt;/code&gt; 或    &lt;code&gt;Egress&lt;/code&gt; 或两者兼具。这里使用    &lt;code&gt;Ingress&lt;/code&gt;，表示对选择的 deathstar Pod 的入站流量执行规则。&lt;/li&gt;  &lt;li&gt;   &lt;code&gt;ingress.from&lt;/code&gt;：表示流量的来源工作负载，也是使用    &lt;code&gt;podSelector&lt;/code&gt; 和 Label 进行选择，这里选中了    &lt;code&gt;org=empire&lt;/code&gt; 也就是所有“帝国的战机”。&lt;/li&gt;  &lt;li&gt;   &lt;code&gt;ingress.ports&lt;/code&gt;：表示流量的进入端口，这里列出了 deathstar 的服务端口。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;接下来，我们测试下。&lt;/p&gt; &lt;h3&gt;测试&lt;/h3&gt; &lt;p&gt;先准备环境，我们使用 K3s  &lt;sup&gt;[4]&lt;/sup&gt; 作为 Kubernetes 环境。但由于 K3s 默认的 CNI 插件 Flannel 不支持网络策略，我们需要换个插件，这里选择 Calico  &lt;sup&gt;[5]&lt;/sup&gt;，即 K3s + Calico 的方案。&lt;/p&gt; &lt;p&gt;先创建一个单节点的集群：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE=&amp;quot;644&amp;quot; INSTALL_K3S_EXEC=&amp;quot;--flannel-backend=none --cluster-cidr=10.42.0.0/16 --disable-network-policy --disable=traefik&amp;quot; sh -   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;此时，所有的 Pod 都处于   &lt;code&gt;Pending&lt;/code&gt; 状态，因为还需要安装 Calico：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;kubectl apply -f https://projectcalico.docs.tigera.io/manifests/calico.yaml   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;待 Calico 成功运行后，所有的 Pod 也会成功运行。&lt;/p&gt; &lt;p&gt;接下来就是部署应用：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;kubectl apply -f app.yaml   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;strong&gt;执行策略前&lt;/strong&gt;，执行下面的命令看看“战机能否登陆死星”：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing   &lt;br /&gt;Ship landed   &lt;br /&gt;   &lt;br /&gt;kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing   &lt;br /&gt;Ship landed   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;从结果来看，两种 ”战机“（Pod 负载）都可以访问 deathstar 服务。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;此时执行网络策略：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;kubectl apply -f native/networkpolicy.yaml   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;再次尝试”登陆“，xwing 的登陆请求会停在那（需要使用 ctrl+c 退出，或者请求时加上   &lt;code&gt;--connect-timeout 2&lt;/code&gt;）。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;h3&gt;思考&lt;/h3&gt; &lt;p&gt;使用 Kubernetes 网络策略实现了我们想要的，从网络层面为服务增加了白名单的功能，这种方案没有改造成本，对系统也几乎无影响。&lt;/p&gt; &lt;p&gt;Cilium 还没出场就结束了？我们继续看：&lt;/p&gt; &lt;p&gt;有时我们的服务会对外暴露一些管理端点，由系统调用执行一些管理上的操作，比如热更新、重启等。这些端点是不允许普通服务来调用，否则会造成严重的后果。&lt;/p&gt; &lt;p&gt;比如示例中，tiefighter 访问了 deathstar 的管理端点   &lt;code&gt;/exhaust-port&lt;/code&gt;：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port   &lt;br /&gt;Panic: deathstar exploded   &lt;br /&gt;   &lt;br /&gt;goroutine 1 [running]:   &lt;br /&gt;main.HandleGarbage(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)   &lt;br /&gt;        /code/src/github.com/empire/deathstar/   &lt;br /&gt;        temp/main.go:9 +0x64   &lt;br /&gt;main.main()   &lt;br /&gt;        /code/src/github.com/empire/deathstar/   &lt;br /&gt;        temp/main.go:5 +0x85   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;出现了 Panic 错误，检查 Pod 你会发现 dealthstar 挂了。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;Kubernetes 的网络策略仅能工作在 L3/4 层，对 L7 层就无能为力了。&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;还是要请出 Cilium。&lt;/p&gt; &lt;h2&gt;Cilium 网络策略&lt;/h2&gt; &lt;p&gt;  &lt;strong&gt;由于 Cilium 涉及了 Linux 内核、网络等众多知识点，要讲清实现原理篇幅极大。故这里仅摘取了官网的介绍，后期希望有时间再写一篇关于实现的。&lt;/strong&gt;&lt;/p&gt; &lt;h3&gt;Cilium 简介&lt;/h3&gt; &lt;blockquote&gt;  &lt;p&gt;Cilium   &lt;sup&gt;[6]&lt;/sup&gt; 是一个开源软件，用于提供、保护和观察容器工作负载（云原生）之间的网络连接，由革命性的内核技术 eBPF   &lt;sup&gt;[7]&lt;/sup&gt; 推动。&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;  &lt;strong&gt;eBPF 是什么？&lt;/strong&gt;&lt;/p&gt; &lt;blockquote&gt;  &lt;p&gt;Linux 内核一直是实现监控/可观测性、网络和安全功能的理想地方。不过很多情况下这并非易事，因为这些工作需要修改内核源码或加载内核模块， 最终实现形式是在已有的层层抽象之上叠加新的抽象。eBPF 是一项革命性技术，它能在内核中运行沙箱程序（sandbox programs）， 而无需修改内核源码或者加载内核模块。&lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote&gt;  &lt;p&gt;将 Linux 内核变成可编程之后，就能基于现有的（而非增加新的）抽象层来打造更加智能、 功能更加丰富的基础设施软件，而不会增加系统的复杂度，也不会牺牲执行效率和安全性。&lt;/p&gt;&lt;/blockquote&gt; &lt;img&gt;&lt;/img&gt; &lt;p&gt;我们来看下 Cilium 的网络策略：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;# cilium/networkpolicy-L4.yaml   &lt;br /&gt;apiVersion: &amp;quot;cilium.io/v2&amp;quot;   &lt;br /&gt;kind: CiliumNetworkPolicy   &lt;br /&gt;metadata:   &lt;br /&gt;  name: &amp;quot;rule1&amp;quot;   &lt;br /&gt;spec:   &lt;br /&gt;  description: &amp;quot;L7 policy to restrict access to specific HTTP call&amp;quot;   &lt;br /&gt;  endpointSelector:   &lt;br /&gt;    matchLabels:   &lt;br /&gt;      org: empire   &lt;br /&gt;      class: deathstar   &lt;br /&gt;  ingress:   &lt;br /&gt;  - fromEndpoints:   &lt;br /&gt;    - matchLabels:   &lt;br /&gt;        org: empire   &lt;br /&gt;    toPorts:   &lt;br /&gt;    - ports:   &lt;br /&gt;      - port: &amp;quot;80&amp;quot;   &lt;br /&gt;        protocol: TCP   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;与 Kubernetes 的原生网络策略差异不大，参考前面的介绍也都看懂，我们直接进入测试。&lt;/p&gt; &lt;h3&gt;测试&lt;/h3&gt; &lt;p&gt;由于 Cilium 本身就实现了 CNI，所以之前的集群就不能用了，先卸载集群：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;k3s-uninstall.sh   &lt;br /&gt;# ！！！切记要清理之前的 cni 插件   &lt;br /&gt;sudo rm -rf /etc/cni/net.d   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;还是使用同样的命令创建单节点的集群：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE=&amp;quot;644&amp;quot; INSTALL_K3S_EXEC=&amp;quot;--flannel-backend=none --cluster-cidr=10.42.0.0/16 --disable-network-policy --disable=traefik&amp;quot; sh -   &lt;br /&gt;   &lt;br /&gt;# cilium 会使用该变量   &lt;br /&gt;export KUBECONFIG=/etc/rancher/k3s/k3s.yaml   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;接下来安装 Cilium CLI：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;curl -L --remote-name-all https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz{,.sha256sum}   &lt;br /&gt;sha256sum --check cilium-linux-amd64.tar.gz.sha256sum   &lt;br /&gt;sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin   &lt;br /&gt;rm cilium-linux-amd64.tar.gz{,.sha256sum}   &lt;br /&gt;   &lt;br /&gt;cilium version   &lt;br /&gt;cilium-cli: v0.10.2 compiled with go1.17.6 on linux/amd64   &lt;br /&gt;cilium image (default): v1.11.1   &lt;br /&gt;cilium image (stable): v1.11.1   &lt;br /&gt;cilium image (running): unknown. Unable to obtain cilium version, no cilium pods found in namespace &amp;quot;kube-system&amp;quot;   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;安装 Cilium 到集群：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;cilium install   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;待 Cilium 成功运行：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;cilium status   &lt;br /&gt;    /¯¯\   &lt;br /&gt; /¯¯\__/¯¯\    Cilium:         OK   &lt;br /&gt; \__/¯¯\__/    Operator:       OK   &lt;br /&gt; /¯¯\__/¯¯\    Hubble:         disabled   &lt;br /&gt; \__/¯¯\__/    ClusterMesh:    disabled   &lt;br /&gt;    \__/   &lt;br /&gt;   &lt;br /&gt;Deployment        cilium-operator    Desired: 1, Ready: 1/1, Available: 1/1   &lt;br /&gt;DaemonSet         cilium             Desired: 1, Ready: 1/1, Available: 1/1   &lt;br /&gt;Containers:       cilium             Running: 1   &lt;br /&gt;                  cilium-operator    Running: 1   &lt;br /&gt;Cluster Pods:     3/3 managed by Cilium   &lt;br /&gt;Image versions    cilium-operator    quay.io/cilium/operator-generic:v1.11.1@sha256:977240a4783c7be821e215ead515da3093a10f4a7baea9f803511a2c2b44a235: 1   &lt;br /&gt;                  cilium             quay.io/cilium/cilium:v1.11.1@sha256:251ff274acf22fd2067b29a31e9fda94253d2961c061577203621583d7e85bd2: 1   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;部署应用：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;kubectl apply -f app.yaml   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;待应用启动后测试服务调用：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing   &lt;br /&gt;Ship landed   &lt;br /&gt;kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing   &lt;br /&gt;Ship landed   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;执行 L4 网络策略：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;kubectl apply -f cilium/networkpolicy-L4.yaml   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;再次尝试“登陆”死星，xwing 战机同样无法登陆，说明 L4 层的规则生效。&lt;/p&gt; &lt;p&gt;我们再尝试 L7 层的规则：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;# cilium/networkpolicy-L7.yaml   &lt;br /&gt;apiVersion: &amp;quot;cilium.io/v2&amp;quot;   &lt;br /&gt;kind: CiliumNetworkPolicy   &lt;br /&gt;metadata:   &lt;br /&gt;  name: &amp;quot;rule1&amp;quot;   &lt;br /&gt;spec:   &lt;br /&gt;  description: &amp;quot;L7 policy to restrict access to specific HTTP call&amp;quot;   &lt;br /&gt;  endpointSelector:   &lt;br /&gt;    matchLabels:   &lt;br /&gt;      org: empire   &lt;br /&gt;      class: deathstar   &lt;br /&gt;  ingress:   &lt;br /&gt;  - fromEndpoints:   &lt;br /&gt;    - matchLabels:   &lt;br /&gt;        org: empire   &lt;br /&gt;    toPorts:   &lt;br /&gt;    - ports:   &lt;br /&gt;      - port: &amp;quot;80&amp;quot;   &lt;br /&gt;        protocol: TCP   &lt;br /&gt;      rules:   &lt;br /&gt;        http:   &lt;br /&gt;        - method: &amp;quot;POST&amp;quot;   &lt;br /&gt;          path: &amp;quot;/v1/request-landing&amp;quot;   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;执行规则：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;kubectl apply -f cilium/networkpolicy-L7.yaml   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;这回，使用 tiefighter 调用死星的管理接口：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port   &lt;br /&gt;Access denied   &lt;br /&gt;# 登陆接口工作正常   &lt;br /&gt;kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing   &lt;br /&gt;Ship landed   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;这回返回了 Access denied，说明 L7 层的规则生效了。&lt;/p&gt; &lt;img&gt;&lt;/img&gt; &lt;h3&gt;参考资料&lt;/h3&gt;[1]  &lt;p&gt;网络策略 NetworkPolicy: https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/&lt;/p&gt;[2]  &lt;p&gt;Cilium getting started: https://play.instruqt.com/isovalent/tracks/cilium-getting-started&lt;/p&gt;[3]  &lt;p&gt;官方文档: https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/&lt;/p&gt;[4]  &lt;p&gt;K3s: https://k3s.io&lt;/p&gt;[5]  &lt;p&gt;Calico: https://www.tigera.io/project-calico/&lt;/p&gt;[6]  &lt;p&gt;Cilium: https://cilium.io&lt;/p&gt;[7]  &lt;p&gt;eBPF: https://ebpf.io&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>dev</category>
      <guid isPermaLink="true">https://itindex.net/detail/62111-cilium-%E5%A2%9E%E5%BC%BA-kubernetes</guid>
      <pubDate>Tue, 15 Feb 2022 00:00:00 CST</pubDate>
    </item>
    <item>
      <title>Kubernetes Service iptables 网络通信验证</title>
      <link>https://itindex.net/detail/62058-kubernetes-service-iptables</link>
      <description>&lt;blockquote&gt;  &lt;p&gt;Kubernetes gives Pods their own IP addresses and a single DNS name for a setof Pods, and can load-balance across them.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;K8s   &lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/" rel="noopener" target="_blank"&gt;Service&lt;/a&gt;会为每个 Pod 都设置一个它自己的 IP，并为一组 Pod 提供一个统一的 DNS 域名，还可以提供在它们间做负载均衡的能力。这篇文章会对 kube-proxy 的 iptables 模式内部的机制做一个验证。大体上涉及的内容如下：&lt;/p&gt; &lt;img src="https://lotabout.me/2022/Kubernetes-Service-Model-Verification/service.svg" title="Service with IP tables"&gt;&lt;/img&gt; &lt;h2&gt;  &lt;a href="https://lotabout.me/#&amp;#23454;&amp;#39564;&amp;#37197;&amp;#32622;"&gt;&lt;/a&gt;实验配置&lt;/h2&gt; &lt;p&gt;创建一个 Service，配置如下：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;apiVersion: v1     &lt;br /&gt;kind: Service     &lt;br /&gt;metadata:     &lt;br /&gt;  creationTimestamp: &amp;quot;2022-01-23T02:32:38Z&amp;quot;     &lt;br /&gt;  name: spring-test     &lt;br /&gt;  namespace: default     &lt;br /&gt;  resourceVersion: &amp;quot;94418&amp;quot;     &lt;br /&gt;  uid: cdaab6bc-a518-4235-a161-a4cae6f564cf     &lt;br /&gt;spec:     &lt;br /&gt;  clusterIP: 10.1.68.7     &lt;br /&gt;  clusterIPs:     &lt;br /&gt;  - 10.1.68.7     &lt;br /&gt;  externalTrafficPolicy: Cluster     &lt;br /&gt;  internalTrafficPolicy: Cluster     &lt;br /&gt;  ipFamilies:     &lt;br /&gt;  - IPv4     &lt;br /&gt;  ipFamilyPolicy: SingleStack     &lt;br /&gt;  ports:     &lt;br /&gt;  - nodePort: 31080     &lt;br /&gt;    port: 8080     &lt;br /&gt;    protocol: TCP     &lt;br /&gt;    targetPort: 8080     &lt;br /&gt;  selector:     &lt;br /&gt;    app: spring-test     &lt;br /&gt;  sessionAffinity: None     &lt;br /&gt;  type: NodePort     &lt;br /&gt;status:     &lt;br /&gt;  loadBalancer: {}     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;创建后的 service 如下：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;$ k get svc -o wide -A     &lt;br /&gt;NAMESPACE     NAME          TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                  AGE     SELECTOR     &lt;br /&gt;default       kubernetes    ClusterIP   10.1.0.1       &amp;lt;none&amp;gt;        443/TCP                  2d22h   &amp;lt;none&amp;gt;     &lt;br /&gt;default       sender        NodePort    10.1.177.169   &amp;lt;none&amp;gt;        8081:31081/TCP           46h     app=sender     &lt;br /&gt;default       spring-test   NodePort    10.1.68.7      &amp;lt;none&amp;gt;        8080:31080/TCP           2d4h    app=spring-test     &lt;br /&gt;kube-system   kube-dns      ClusterIP   10.1.0.10      &amp;lt;none&amp;gt;        53/UDP,53/TCP,9153/TCP   2d22h   k8s-app=kube-dns     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;注意其中的 spring-test 和 kube-dns 两项，后面会用到。另外 service 对应的 podIP 如下：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;$ k get ep     &lt;br /&gt;NAME          ENDPOINTS                         AGE     &lt;br /&gt;kubernetes    192.168.50.48:6443                2d23h     &lt;br /&gt;sender        10.244.1.7:8080,10.244.2.7:8080   47h     &lt;br /&gt;spring-test   10.244.1.3:8080,10.244.2.3:8080   2d4h     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h2&gt;  &lt;a href="https://lotabout.me/#dns"&gt;&lt;/a&gt;DNS&lt;/h2&gt; &lt;p&gt;K8s 会为 Service 创建一个   &lt;a href="https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#a-aaaa-records" rel="noopener" target="_blank"&gt;DNS&lt;/a&gt;域名，格式为   &lt;code&gt;&amp;lt;svc&amp;gt;.&amp;lt;namespace&amp;gt;.svc.&amp;lt;cluster-domain&amp;gt;&lt;/code&gt;，例如我们创建的  &lt;code&gt;spring-test&lt;/code&gt; Service 则会有  &lt;code&gt;spring-test.default.svc.cluster.local&lt;/code&gt;  &lt;sup&gt;   &lt;a href="https://lotabout.me/#fn1"&gt;[1]&lt;/a&gt;&lt;/sup&gt; 域名。&lt;/p&gt; &lt;p&gt;我们首先进入 pod，看一下   &lt;code&gt;/etc/resolv.conf&lt;/code&gt; 文件，关于域名解析的配置：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;nameserver 10.1.0.10     &lt;br /&gt;search default.svc.cluster.local svc.cluster.local cluster.local     &lt;br /&gt;options ndots:5     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;这里的     &lt;code&gt;10.1.0.10&lt;/code&gt; 是 kube-dns service 的 cluster IP&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;文件中配置了多个 search 域，因此我们写     &lt;code&gt;spring-test&lt;/code&gt; 或    &lt;code&gt;spring-test.default&lt;/code&gt; 或     &lt;code&gt;spring-test.default.svc&lt;/code&gt; 都是可以解析的，另外注意解析后的 IP 也不是具体哪个 POD 的地址，而是为 Service 创建的虚拟地址ClusterIP。&lt;/p&gt;     &lt;table&gt;    &lt;tr&gt;     &lt;td&gt;      &lt;pre&gt;root@spring-test-77d9d6dcb5-m9mvr:/# nslookup spring-test       &lt;br /&gt;Server:         10.1.0.10       &lt;br /&gt;Address:        10.1.0.10#53       &lt;br /&gt;       &lt;br /&gt;Name:   spring-test.default.svc.cluster.local       &lt;br /&gt;Address: 10.1.68.7       &lt;br /&gt;       &lt;br /&gt;root@spring-test-77d9d6dcb5-m9mvr:/# nslookup spring-test.default       &lt;br /&gt;Server:         10.1.0.10       &lt;br /&gt;Address:        10.1.0.10#53       &lt;br /&gt;       &lt;br /&gt;Name:   spring-test.default.svc.cluster.local       &lt;br /&gt;Address: 10.1.68.7       &lt;br /&gt;       &lt;br /&gt;root@spring-test-77d9d6dcb5-m9mvr:/# nslookup spring-test.default.svc       &lt;br /&gt;Server:         10.1.0.10       &lt;br /&gt;Address:        10.1.0.10#53       &lt;br /&gt;       &lt;br /&gt;Name:   spring-test.default.svc.cluster.local       &lt;br /&gt;Address: 10.1.68.7       &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;    &lt;code&gt;ndots:5&lt;/code&gt; 指的是如果域名中的     &lt;code&gt;.&lt;/code&gt; 大于等于 5 个，则不走 search 域，目的是减少常规域名的解析次数    &lt;sup&gt;     &lt;a href="https://lotabout.me/#fn2"&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;  &lt;a href="https://lotabout.me/#iptables-&amp;#36716;&amp;#21457;"&gt;&lt;/a&gt;iptables 转发&lt;/h2&gt; &lt;p&gt;DNS 里创建的记录解决了域名到 ClusterIP 的转换问题，发送到 ClusterIP 的请求，如何转发到对应的 POD 里呢？K8s Service 有几种实现方式，这里验证的是 iptables 的实现方式：kube-proxy 会监听 etcd 中关于 k8s 的事件，并动态地对 iptables 做配置，最终由 iptables 来完成转发。先看看跟这个 Service 相关的规则如下：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;0.  -A PREROUTING -j KUBE-SERVICES     &lt;br /&gt;1.  -A KUBE-NODEPORTS -p tcp -m tcp --dport 31080 -j KUBE-SVC-S     &lt;br /&gt;2.  -A KUBE-SEP-A -s 10.244.2.3/32 -j KUBE-MARK-MASQ     &lt;br /&gt;3.  -A KUBE-SEP-A -p tcp -m tcp -j DNAT --to-destination 10.244.2.3:8080     &lt;br /&gt;4.  -A KUBE-SEP-B -s 10.244.1.3/32 -j KUBE-MARK-MASQ     &lt;br /&gt;5.  -A KUBE-SEP-B -p tcp -m tcp -j DNAT --to-destination 10.244.1.3:8080     &lt;br /&gt;6.  -A KUBE-SERVICES -d 10.1.68.7/32 -p tcp -m tcp --dport 8080 -j KUBE-SVC-S     &lt;br /&gt;7.  -A KUBE-SVC-S ! -s 10.244.0.0/16 -d 10.1.68.7/32 -p tcp -m tcp --dport 8080 -j KUBE-MARK-MASQ     &lt;br /&gt;8.  -A KUBE-SVC-S -p tcp -m tcp --dport 31080 -j KUBE-MARK-MASQ     &lt;br /&gt;9.  -A KUBE-SVC-S -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-B     &lt;br /&gt;10. -A KUBE-SVC-S -j KUBE-SEP-A     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;我们先用   &lt;code&gt;iptables-save&lt;/code&gt; 打印出所有的规则，筛选出和   &lt;code&gt;spring-test&lt;/code&gt; service相关的规则，删除了一些 comment，并对名字做了简化。可以看到有这么几类：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;code&gt;KUBE-NODEPORTS&lt;/code&gt;，这类规则用来将发送到 NodePort 的报文转到    &lt;code&gt;KUBE-SVC-*&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;   &lt;code&gt;KUBE-SERVICES&lt;/code&gt;：是识别目标地址为 ClusterIP(   &lt;code&gt;10.1.68.7&lt;/code&gt;)，命中的报文转到   &lt;code&gt;KUBE-SVC-*&lt;/code&gt; 做处理&lt;/li&gt;  &lt;li&gt;   &lt;code&gt;KUBE-SVC&lt;/code&gt; 的作用是做负载均衡，将请求分配到    &lt;code&gt;KUBE-SEP&lt;/code&gt; 中&lt;/li&gt;  &lt;li&gt;   &lt;code&gt;KUBE-SEP&lt;/code&gt; 通过 DNAT 替换目标地址为 Pod IP，转发到具体的 POD 中&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;另外经常看到   &lt;code&gt;-j KUBE-MARK-MASQ&lt;/code&gt;，它的作用是在请求里加上 mark，在  &lt;code&gt;POSTROUTING&lt;/code&gt; 规则中做 SNAT，这点后面再细说。&lt;/p&gt; &lt;p&gt;我们开启 iptables 的 trace 模式  &lt;sup&gt;   &lt;a href="https://lotabout.me/#fn3"&gt;[3]&lt;/a&gt;&lt;/sup&gt;，并在其中一个 pod 发送一个请求，检查 TRACE 中规则的命中情况（由于输出特别多，这里挑选了重要的输出并做了精简）：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;0:  nat:PREROUTING    IN=cni0 OUT=           SRC=10.244.1.7 DST=10.1.68.7  DPT=8080     &lt;br /&gt;6:  nat:KUBE-SERVICES IN=cni0 OUT=           SRC=10.244.1.7 DST=10.1.68.7  DPT=8080     &lt;br /&gt;10: nat:KUBE-SVC-S    IN=cni0 OUT=           SRC=10.244.1.7 DST=10.1.68.7  DPT=8080     &lt;br /&gt;3:  nat:KUBE-SEP-A    IN=cni0 OUT=           SRC=10.244.1.7 DST=10.1.68.7  DPT=8080     &lt;br /&gt;    mangle:FORWARD    IN=cni0 OUT=flannel.1  SRC=10.244.1.7 DST=10.244.2.3 DPT=8080     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;ul&gt;  &lt;li&gt;在    &lt;code&gt;PREROUTING&lt;/code&gt; 时，进入第 6 条进判定&lt;/li&gt;  &lt;li&gt;   &lt;code&gt;KUBE-SERVICES&lt;/code&gt; 判断目标地址为    &lt;code&gt;10.1.68.7&lt;/code&gt; 且目标端口为    &lt;code&gt;8080&lt;/code&gt;，于是跳转进入    &lt;code&gt;KUBE-SVC-S&lt;/code&gt; 链的判断&lt;/li&gt;  &lt;li&gt;   &lt;code&gt;KUBE-SVC-S&lt;/code&gt; 有多条规则，从日志看最终是从第 10 条退出，进入    &lt;code&gt;KUBE-SEP-A&lt;/code&gt; 链&lt;/li&gt;  &lt;li&gt;   &lt;code&gt;KUBE-SEP-A&lt;/code&gt; 最终命中第 3 条规则退出，但此时会进行 DNAT 转换目标地址&lt;/li&gt;  &lt;li&gt;下一条日志显示，   &lt;code&gt;DST&lt;/code&gt; 目标地址已经变成 pod 地址    &lt;code&gt;10.244.2.3&lt;/code&gt; 了&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;类似的，如果我们是通过 NodePort 来访问 Service，则 Trace 日志如下：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;0: nat:PREROUTING:      IN=eth0 OUT=     SRC=192.168.50.135 DST=192.168.50.238 DPT=31080     &lt;br /&gt;6: nat:KUBE-SERVICES:   IN=eth0 OUT=     SRC=192.168.50.135 DST=192.168.50.238 DPT=31080     &lt;br /&gt;1: nat:KUBE-NODEPORTS:  IN=eth0 OUT=     SRC=192.168.50.135 DST=192.168.50.238 DPT=31080     &lt;br /&gt;9: nat:KUBE-SVC-S:      IN=eth0 OUT=     SRC=192.168.50.135 DST=192.168.50.238 DPT=31080     &lt;br /&gt;9: nat:KUBE-SVC-S:      IN=eth0 OUT=     SRC=192.168.50.135 DST=192.168.50.238 DPT=31080     &lt;br /&gt;5: nat:KUBE-SEP-A:      IN=eth0 OUT=     SRC=192.168.50.135 DST=192.168.50.238 DPT=31080     &lt;br /&gt;   mangle:FORWARD:      IN=eth0 OUT=cni0 SRC=192.168.50.135 DST=10.244.1.3     DPT=8080     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;h2&gt;  &lt;a href="https://lotabout.me/#iptables-&amp;#36127;&amp;#36733;&amp;#22343;&amp;#34913;"&gt;&lt;/a&gt;iptables 负载均衡&lt;/h2&gt; &lt;p&gt;上一节我们比较关注 iptables 转发的内容，那么如何做负载均衡？这部分是比较纯粹的iptables 知识  &lt;sup&gt;   &lt;a href="https://lotabout.me/#fn4"&gt;[4]&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt; &lt;p&gt;首先：iptables 对于规则的解析是严格顺序的，所以如果只是单纯列出两个条目，则会永远命中第一条：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;-A KUBE-SVC-S -j KUBE-SEP-A     &lt;br /&gt;-A KUBE-SVC-S -j KUBE-SEP-B     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;于是，我们需要第一条规则在某些条件下不命中。这样 iptables 就有机会执行后面的规则。iptables 提供了两种方法，第一种是有随机数，也是上一节我们看到的：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;-A KUBE-SVC-S -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-B     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;这条规则在执行时，iptables 会随机生成一个数，并以   &lt;code&gt;probability&lt;/code&gt; 的概率命中当前规则。换句话说，第一条命中的概率是   &lt;code&gt;p&lt;/code&gt;，则第二条规则就是   &lt;code&gt;1-p&lt;/code&gt;。如果有 3 个副本，则会类似下面这样的规则，大家可以计算下最后三个 Pod 是不是平均分配：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;-A KUBE-SVC-S --mode random --probability 0.33333333349 -j KUBE-SEP-A     &lt;br /&gt;-A KUBE-SVC-S --mode random --probability 0.50000000000 -j KUBE-SEP-B     &lt;br /&gt;-A KUBE-SVC-S -j KUBE-SEP-C     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;另外一种模式是 round-robin，但是 kubernetes 的 iptables 模式不支持，这里就不细说了。猜想 kubernetes iptables 模式下不支持的原因是虽然单机 iptables 能支持round-robin，但多机模式下，无法做到全局的 round-robin。&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://lotabout.me/#snat"&gt;&lt;/a&gt;SNAT&lt;/h2&gt; &lt;p&gt;前面我们提到 KUBE 系列的规则经常看到   &lt;code&gt;-j KUBE-MARK-MASQ&lt;/code&gt;，和它相关的规则有这些：&lt;/p&gt; &lt;table&gt;  &lt;tr&gt;   &lt;td&gt;    &lt;pre&gt;-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000     &lt;br /&gt;-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN     &lt;br /&gt;-A KUBE-POSTROUTING -j MARK --set-xmark 0x4000/0x0     &lt;br /&gt;-A KUBE-POSTROUTING -m comment --comment &amp;quot;kubernetes service traffic requiring SNAT&amp;quot; -j MASQUERADE     &lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;首先   &lt;code&gt;KUBE-MARK-MASQ&lt;/code&gt; 的作用是把报文打上   &lt;code&gt;0x4000/0x4000&lt;/code&gt; 的标记，在  &lt;code&gt;KUBE-POSTROUTING&lt;/code&gt; 时，如果报文中包含这个标记，会执行   &lt;code&gt;-j MASQUERADE&lt;/code&gt; 操作，而这个操作的作用就是做源地址转换（SNAT）。那 SNAT 是什么，为什么要做 SNAT 呢？&lt;/p&gt; &lt;p&gt;这里引用  &lt;a href="https://www.asykim.com/blog/deep-dive-into-kubernetes-external-traffic-policies" rel="noopener" target="_blank"&gt;这篇文章&lt;/a&gt;里的图做说明：&lt;/p&gt; &lt;img src="https://lotabout.me/2022/Kubernetes-Service-Model-Verification/SNAT.svg" title="SNAT or Not"&gt;&lt;/img&gt; &lt;p&gt;如果没有 SNAT，被转发到 POD 的请求返回时，会尝试把请求直接返回给 Client，我们知道一个 TCP 连接的依据是(src_ip, src_port, dst_ip, dst_port)，现在client 在等待   &lt;code&gt;eIP/NP&lt;/code&gt; 返回的报文，等到的却是   &lt;code&gt;pod IP&lt;/code&gt; 的返回，client 不认这个报文。换句话说，经过 proxy 的流量都正常情况下都应该原路返回才能工作。&lt;/p&gt; &lt;p&gt;在一些情况下可能希望关闭 SNAT，K8S 提供   &lt;code&gt;externalTrafficPolicy: Local&lt;/code&gt; 的配置项，但流量的流转也会发生变化，这里不深入。&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://lotabout.me/#&amp;#23567;&amp;#32467;"&gt;&lt;/a&gt;小结&lt;/h2&gt; &lt;p&gt;这篇文章和上一篇  &lt;a href="https://lotabout.me/2022/Flannel-Verification/"&gt;Flannel 网络通信验证&lt;/a&gt;类似，都是尝试搭建环境，在学习 kube-proxy 工作机制的同时，对 kube-proxy 的产出iptables 做一些验证。文章中验证了这些内容：&lt;/p&gt; &lt;ol&gt;  &lt;li&gt;验证了 service ClusterIP 和 domain 的创建，及 pod 中    &lt;code&gt;/etc/resolv.conf&lt;/code&gt; 中搜索域的设置&lt;/li&gt;  &lt;li&gt;验证了 kube-proxy 生成的 iptables 规则，并验证请求在这些规则中的流转&lt;/li&gt;  &lt;li&gt;学习了 iptables 负载均衡的工作机制&lt;/li&gt;  &lt;li&gt;了解了 SNAT 是什么，kube-proxy 需要做 SNAT 的原因&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;这篇文章的信息量不大，希望读者也撸起袖子，实打实地做一些验证，能让我们对kube-proxy 涉及的 iptables 的操作有更深刻的理解。&lt;/p&gt; &lt;h2&gt;  &lt;a href="https://lotabout.me/#&amp;#21442;&amp;#32771;"&gt;&lt;/a&gt;参考&lt;/h2&gt; &lt;ul&gt;  &lt;li&gt;   &lt;a href="https://sookocheff.com/post/kubernetes/understanding-kubernetes-networking-model/" rel="noopener" target="_blank"&gt;A Guide to the Kubernetes Networking Model&lt;/a&gt; 讲解了 K8S 的网络模型，有一些（动）图描述网络包的走向&lt;/li&gt;  &lt;li&gt;   &lt;a href="https://serenafeng.github.io/2020/03/26/kube-proxy-in-iptables-mode/" rel="noopener" target="_blank"&gt;Deep Dive kube-proxy with iptables mode&lt;/a&gt; 深挖 kube-proxy 在 iptables 模式下的工作原理，比本文更深入&lt;/li&gt;  &lt;li&gt;   &lt;a href="https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/" rel="noopener" target="_blank"&gt;Debug Service&lt;/a&gt; K8S 官方文档，讲解 Service 不工作时常见的 Debug 方法&lt;/li&gt;&lt;/ul&gt; &lt;hr&gt;&lt;/hr&gt; &lt;ol&gt;  &lt;li&gt;   &lt;p&gt;    &lt;code&gt;cluster.local&lt;/code&gt; 是可以改的，但是比较麻烦，参考：    &lt;a href="https://stackoverflow.com/a/66106716" rel="noopener" target="_blank"&gt;https://stackoverflow.com/a/66106716&lt;/a&gt;     &lt;a href="https://lotabout.me/#fnref1"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;参考     &lt;a href="https://hansedong.github.io/2018/11/20/9/" rel="noopener" target="_blank"&gt;https://hansedong.github.io/2018/11/20/9/&lt;/a&gt;     &lt;a href="https://lotabout.me/#fnref2"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;    &lt;a href="https://www.opensourcerers.org/2016/05/27/how-to-trace-iptables-in-rhel7-centos7/" rel="noopener" target="_blank"&gt;https://www.opensourcerers.org/2016/05/27/how-to-trace-iptables-in-rhel7-centos7/&lt;/a&gt;     &lt;a href="https://lotabout.me/#fnref3"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;    &lt;a href="https://scalingo.com/blog/iptables" rel="noopener" target="_blank"&gt;Turning IPTables into a TCP load balancer for fun and profit&lt;/a&gt;     &lt;a href="https://lotabout.me/#fnref4"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Knowledge k8s iptables kube-proxy service</category>
      <guid isPermaLink="true">https://itindex.net/detail/62058-kubernetes-service-iptables</guid>
      <pubDate>Tue, 25 Jan 2022 07:01:26 CST</pubDate>
    </item>
    <item>
      <title>网络数字身份认证术</title>
      <link>https://itindex.net/detail/61989-%E7%BD%91%E7%BB%9C-%E6%95%B0%E5%AD%97%E8%BA%AB%E4%BB%BD-%E8%AE%A4%E8%AF%81</link>
      <description>&lt;p&gt;  &lt;img alt="" height="201" src="https://coolshell.cn/wp-content/uploads/2022/01/iStock-1175502114-300x201.png" width="300"&gt;&lt;/img&gt;这篇文章是《  &lt;a href="https://coolshell.cn/articles/19395.html" rel="noopener" target="_blank" title="HTTP API &amp;#35748;&amp;#35777;&amp;#25480;&amp;#26435;&amp;#26415;"&gt;HTTP API 认证授权术&lt;/a&gt;》的姊妹篇，在那篇文章中，主要介绍了 HTTP API 认证和授权技术中用到的 HTTP Basic, Digest Access, HMAC, OAuth, JWT 等各种方式，主要是 API 上用到的一些技术，这篇文章主要想说的是另一个话题——身份认证。也就是说，怎么确认这个数据就是这个人发出来的？&lt;/p&gt;
 &lt;h4&gt;用户密码&lt;/h4&gt;
 &lt;p&gt;要解决这个问题，我们先来看一个最简单的解——使用密码，通常来说，在网络上要证明一个人的身份的话，都需要这个人的一些私密而唯一的东西。比如，像密码这样的东西，很多地方，只要你提供了你的用户名+密码，就可以确定这个人是你（注明：关于密码管理，强密码设定，密码泄漏，密码破解以及密码哄骗不在这篇文章的话题中），也就是说，这个密码是非常私密的事，我们可以假设，这个事全世界只能有当事人一个人知道，所以，当当事人得供正确的密码，我们就可以认证这个人了。&lt;/p&gt;
 &lt;p&gt;为了加强密码的安全程度，一般会使用 2FA（Two-factor authentication）或 MFA（Multi-factor authentication），双因认证或多因认证，这需要用户提供一个唯一的可信设备，比如用户的手机，然后通过验证手机短信，或是像   &lt;a href="https://en.wikipedia.org/wiki/Google_Authenticator" rel="noopener" target="_blank"&gt;Google Authenticator&lt;/a&gt;  这样的动态口令来完成。这样的安全级别已经算是比较高了。如果能够再加上经常性的变更密码，那么密全级别就更好了。&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;另外，一些公司还使用了生物密码来进行用户的身份验证，比如人脸识别。但是，我个人觉得人脸识别或是生物识别是比较糟糕的方式，因为：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;目前能被验证的生物信息（如人脸和指纹）太容易被别人获得和伪造了。&lt;/li&gt;
  &lt;li&gt;这样东西不能被变更和吊销，密码可以被吊销和重置，人脸则不能。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;密钥对和证书&lt;/h4&gt;
 &lt;p&gt;密码可以解决身证认证的问题有很多问题，最重要的一个问题就是，你要把你的密码提供给对方，对方才能验证你的身份。你不可能把你的密码提供给全世界的人吧，这样的话，全世界的人都有你的密码了，那么任何人都能变成你了。所以，用户密码这个事只能存在于权威机构和普通用户之间，不能存在于普遍应用中。所以，这里需要使用更好的解决方案。&lt;/p&gt;
 &lt;p&gt;使用 ECC（  &lt;a href="https://en.wikipedia.org/wiki/Elliptic-curve_cryptography" rel="noopener" target="_blank" title="Elliptic-Curve Cryptography"&gt;Elliptic-Curve Cryptography&lt;/a&gt;）椭圆曲线密码术，可以通过一个“密钥对”进行非对称加密。这种技术，在对信息进行加密和解密时，使用两个不同的密钥，其中一个用来做加密，另一个做解密。这样一来，我们就可以把其中一个密钥公布出去，称之为公钥，另一个密钥私密地保管好，称之为私钥。&lt;/p&gt;
 &lt;p&gt;比如，我用我的私钥加密信息，然后，我把这个私钥所配对的公钥发布给所有人，大家都用公钥解密信息，不用我的公钥你解密不了这个信息。这样一来，就可以保证这个信息是我发出来的，不但保证了信息安全，还完成了身份认证。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="244" src="https://coolshell.cn/wp-content/uploads/2022/01/key.pair_-1024x390.png" width="640"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;这样的现实案例一般用于网站，也就是用户得要知道我访问的这个网站是真实的，不是别人做的。因为 DNS 很容易被 hack，你连上一个不可信的网络，这个网络里的 DNS 把这个网站的 IP 地址解析成什么 就是什么了。但是有了这个加密的机制后，网站把自己的信息加密后连同公钥给到访问者，访问解密后就知道是不是这个网站了。&lt;/p&gt;
 &lt;p&gt;但是，这里还是会有一个很严重的问题，那就是中间人攻击。如下图所示：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="252" src="https://coolshell.cn/wp-content/uploads/2022/01/middle.man_-e1641105543137.png" width="600"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;中间人 Chad 把 伪装成 Bob 向 Alice 要信息，然后，再伪装成 Alice 对 Bob 说，这就是 Alice 的公钥，于是 Bob 也无法验证是不是 Alice 的公钥，因为公钥里就是一堆乱七八糟的数据，我们完全不能分辨哪个公钥属于 Alice 的。试想，如果我们收到声称属于银行的密钥。我们怎么知道它确实属于你的银行？&lt;/p&gt;
 &lt;p&gt;这里的答案就是  &lt;strong&gt;使用数字证书&lt;/strong&gt;。证书跟我们的身份证非常类似，其需要一个可信机构来颁发和验证的。这个证书机构 CA（Certificate Authority）是一个是大家都相信的权威机构，他用他的人品保证（当然一般会被严格管理和审计），CA 机构同样使用这样的非对称加密的技术来完成颁发和验证的事。下图展示了这一过程。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="333" src="https://coolshell.cn/wp-content/uploads/2022/01/certificate-1024x532.png" width="640"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;说明一下上面这个图：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;为了解决公钥认证的问题的，我们需要一个权威的CA 机构。&lt;/li&gt;
  &lt;li&gt;Alice 把自己的信息（姓名、组织，地址，电邮，网址等 ）和自己的公钥打包成一个 CSR 的文件，发给 CA 机构，&lt;/li&gt;
  &lt;li&gt;CA 机构会来找 Alice 做物理世界的认证，如果通过后，就会用自己的机构私钥，把CSR 变成一个签名证书。&lt;/li&gt;
  &lt;li&gt;Bob 同学拿到 Alice 的证书，用 CA 机构的公钥解密后，得到 Alice 的公钥&lt;/li&gt;
  &lt;li&gt;后面就可以签证 信息是否来自 Alice 了。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;是的，这个过程就是在“套娃”，这种证书机构还可以给下级的证书机构发证，于是就会一层套一层地，形成一个证书链，顶层的叫根证书，你得绝对信任之。对于验证证书真实性的客户端，它需要能够验证链中所有 CA 的签名，这意味着客户端需要访问链中所有 CA 的证书。&lt;/p&gt;
 &lt;h4&gt;证书生成过程演示&lt;/h4&gt;
 &lt;p&gt;并不是所有的场景都需要向这些大型的 CA 机构申请公钥证书，在任何一个企业，组织或是团体内都可以自己形这样的“小王国”，也就是说，你可以自行生成这样的证书，只需要你自己保证自己的生成证书的私钥的安全，以及不需要扩散到整个互联网。下面，我们用   &lt;code&gt;openssl&lt;/code&gt;命令来演示这个过程。&lt;/p&gt;
 &lt;p&gt;1）生成 CA 的证书（公钥）   &lt;code&gt;ca.crt&lt;/code&gt; 和私钥   &lt;code&gt;ca.key&lt;/code&gt;&lt;/p&gt;
 &lt;pre&gt;openssl req -newkey rsa:2048 \
    -new -nodes -x509 \
    -days 365 \
    -out ca.crt \
    -keyout ca.key \
    -subj &amp;quot;/C=SO/ST=Earth/L=Mountain/O=CoolShell/OU=HQ/CN=localhost&amp;quot;&lt;/pre&gt;
 &lt;p&gt;2)  生成 alice 的私钥&lt;/p&gt;
 &lt;pre&gt;openssl genrsa -out alice.key 2048&lt;/pre&gt;
 &lt;p&gt;3）生成 Alice 的 CSR – Certificate Signing Request&lt;/p&gt;
 &lt;pre&gt;openssl req -new -key alice.key 365 -out alice.csr \
    -subj &amp;quot;/C=CN/ST=Beijing/L=Haidian/O=CoolShell/OU=Test/CN=localhost.alice&amp;quot;&lt;/pre&gt;
 &lt;p&gt;4）使用 CA 给 Alice 签名证书&lt;/p&gt;
 &lt;pre&gt;openssl x509  -req -in alice.csr \
    -extfile &amp;lt;(printf &amp;quot;subjectAltName=DNS:localhost.alice&amp;quot;) \ 
    -CA ca.crt -CAkey ca.key  \
    -days 365 -sha256 -CAcreateserial \
    -out alice.crt&lt;/pre&gt;
 &lt;h4&gt;双向认证 mTLS&lt;/h4&gt;
 &lt;p&gt;上面，我们说的基本上都是单向认证，大量的场景都是确保用户方访问的是真正的服务方，如：银行，电商网站，等。这样可以保证用户不会被钓鱼网站或是中间人攻击。但是，很多时候，我们也是需要双向认证的。下面是一个典型的场景——微信支付和商户间交互&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;用户到商家那边买东西，商家要求用户进行支付。&lt;/li&gt;
  &lt;li&gt;用户选择了微信支付，于是，界面从商户侧切到了微信侧&lt;/li&gt;
  &lt;li&gt;微信那边支付完成后，商户这边收到微信那边支付完成的通知，于是开始发货。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;这个过程中有件事非常重要——就是微信通知商户支付完成的时候。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;微信得确保通知到的就是用户所支付商户，而不是别个。&lt;/li&gt;
  &lt;li&gt;商户也得要能确认，来通知我的就是微信，不是别人。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;一般来说，微信会给商户一个 AppID和一个 AppSerct，用这个来确保是我认证过的商户来调用我，然后，需要商户在自己的系统里填一个回调的 URL，并通过平台设置的 key来做 MD5/HMAC的签名来确保是官方的回调。这都是在《  &lt;a href="https://coolshell.cn/articles/19395.html" rel="noopener" target="_blank" title="HTTP API &amp;#35748;&amp;#35777;&amp;#25480;&amp;#26435;&amp;#26415;"&gt;HTTP API 认证授权术&lt;/a&gt;》中提到过的技术，是相对传统的技术。&lt;/p&gt;
 &lt;p&gt;如今，  &lt;strong&gt;mTLS是&lt;/strong&gt;确保云原生应用程序中服务之间的通信安全的首选协议。 也就是双向认证。&lt;/p&gt;
 &lt;p&gt;传统的 TLS 认证过程是：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;客户端连接到服务器&lt;/li&gt;
  &lt;li&gt;服务器提供其 TLS 证书&lt;/li&gt;
  &lt;li&gt;客户端验证服务器的证书&lt;/li&gt;
  &lt;li&gt;客户端和服务器通过加密的 TLS 连接交换信息&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;在 mTLS 中，客户端和服务器都有一个证书，双方都使用他们的公钥/私钥对进行身份验证。与常规 TLS 相比，mTLS 中有额外的步骤来验证双方（以  &lt;strong&gt;粗体显示的&lt;/strong&gt;额外步骤）：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;客户端连接到服务器&lt;/li&gt;
  &lt;li&gt;服务器提供其 TLS 证书&lt;/li&gt;
  &lt;li&gt;客户端验证服务器的证书&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;客户端出示其 TLS 证书&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;服务器验证客户端的证书&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;服务器授予访问权限&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;客户端和服务器通过加密的 TLS 连接交换信息&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;mTLS 需要“根”TLS 证书；这我们自己来完成证书颁发机构的职责。授权客户端和服务器使用的证书必须与此根证书相对应。根证书是自签名的，这意味着我们需要自己创建它。（注：此方法不适用于公共 Internet 上的单向 TLS，因为外部证书颁发机构必须颁发这些证书）&lt;/p&gt;
 &lt;p&gt;那么，为什么整个互联网上都用了 TLS 了，为什么 不升级一下使用 mTLS？这里有两方面的原因：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;公共互联网上要解决的问题是：A) 确保用户访问到的是正确的网站，而不是钓鱼网站。B）网站传输的内容是安全和私密且不会被篡改的。&lt;/li&gt;
  &lt;li&gt;将 TLS 证书分发到所有最终用户设备将非常困难。生成、管理和验证为此所需的数十亿个证书几乎是不可能的任务。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;在较小的范围内，mTLS 对于单个组织非常有用且非常实用，尤其是当这些组织采用零信任方法来确保网络安全时。由于默认情况下零信任方法不信任任何用户、设备或请求，因此组织必须能够在每次尝试访问网络中的任何点时对每个用户、设备和请求进行身份验证。mTLS 通过对用户进行身份验证和设备验证来帮助实现这一目标。&lt;/p&gt;
 &lt;p&gt;关于 mTLS，这里有一个我用 Golang 写的示例 –   &lt;a href="https://github.com/haoel/mTLS" rel="noopener" target="_blank"&gt;https://github.com/haoel/mTLS&lt;/a&gt;，大家可以参考一下。&lt;/p&gt;
 &lt;p&gt;P.S. 本文图版中的卡司来自安全圈的标准 Cast，参看  &lt;a href="https://en.wikipedia.org/wiki/Alice_and_Bob" rel="noopener" target="_blank"&gt; Alice and Bob&lt;/a&gt;。&lt;/p&gt;
 &lt;p&gt;（全文完）&lt;/p&gt;
 &lt;p align="center"&gt;  &lt;img src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"&gt;&lt;/img&gt;   &lt;img height="300" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300"&gt;&lt;/img&gt;   &lt;br /&gt;关注CoolShell微信公众账号和微信小程序&lt;/p&gt;
 &lt;div&gt;
  &lt;p align="center"&gt;   &lt;strong&gt;（转载本站文章请注明作者和出处     &lt;a href="https://coolshell.cn/"&gt;酷 壳 – CoolShell&lt;/a&gt; ，请勿用于任何商业用途）&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
 &lt;div&gt;——===   &lt;strong&gt;访问    &lt;a href="http://coolshell.cn/404/" target="_blank"&gt;酷壳404页面&lt;/a&gt; 寻找遗失儿童。&lt;/strong&gt; ===——&lt;/div&gt;

 &lt;div&gt;  &lt;div&gt;   &lt;h3&gt;相关文章&lt;/h3&gt;   &lt;ul&gt;    &lt;li&gt;     &lt;a href="https://coolshell.cn/articles/19395.html"&gt;      &lt;img alt="HTTP API &amp;#35748;&amp;#35777;&amp;#25480;&amp;#26435;&amp;#26415;" height="150" src="https://coolshell.cn/wp-content/uploads/2019/05/Authorization-360x200-1-150x150.png" width="150"&gt;&lt;/img&gt;&lt;/a&gt;     &lt;a href="https://coolshell.cn/articles/19395.html"&gt;HTTP API 认证授权术&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="https://coolshell.cn/articles/21003.html"&gt;      &lt;img alt="&amp;#35745;&amp;#26102;&amp;#25915;&amp;#20987; Timing Attacks" height="150" src="https://coolshell.cn/wp-content/uploads/2020/06/time-bomb-150x150.png" width="150"&gt;&lt;/img&gt;&lt;/a&gt;     &lt;a href="https://coolshell.cn/articles/21003.html"&gt;计时攻击 Timing Attacks&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="https://coolshell.cn/articles/19840.html"&gt;      &lt;img alt="HTTP&amp;#30340;&amp;#21069;&amp;#19990;&amp;#20170;&amp;#29983;" height="150" src="https://coolshell.cn/wp-content/uploads/2019/10/HTTP-770x513-300x200-1-150x150.jpg" width="150"&gt;&lt;/img&gt;&lt;/a&gt;     &lt;a href="https://coolshell.cn/articles/19840.html"&gt;HTTP的前世今生&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="https://coolshell.cn/articles/18094.html"&gt;      &lt;img alt="&amp;#22914;&amp;#20309;&amp;#20813;&amp;#36153;&amp;#30340;&amp;#35753;&amp;#32593;&amp;#31449;&amp;#21551;&amp;#29992;HTTPS" height="150" src="https://coolshell.cn/wp-content/uploads/2017/08/enable-https-banner-150x150.png" width="150"&gt;&lt;/img&gt;&lt;/a&gt;     &lt;a href="https://coolshell.cn/articles/18094.html"&gt;如何免费的让网站启用HTTPS&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="https://coolshell.cn/articles/17607.html"&gt;      &lt;img alt="&amp;#20174; MongoDB &amp;#8220;&amp;#36174;&amp;#37329;&amp;#20107;&amp;#20214;&amp;#8221; &amp;#30475;&amp;#23433;&amp;#20840;&amp;#38382;&amp;#39064;" height="150" src="https://coolshell.cn/wp-content/uploads/2017/01/MongoDB-150x150.jpg" width="150"&gt;&lt;/img&gt;&lt;/a&gt;     &lt;a href="https://coolshell.cn/articles/17607.html"&gt;从 MongoDB “赎金事件” 看安全问题&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="https://coolshell.cn/articles/17066.html"&gt;      &lt;img alt="&amp;#20851;&amp;#20110;&amp;#31227;&amp;#21160;&amp;#31471;&amp;#30340;&amp;#38035;&amp;#40060;&amp;#24335;&amp;#25915;&amp;#20987;" height="150" src="https://coolshell.cn/wp-content/uploads/2015/04/phishing-1-150x150.jpg" width="150"&gt;&lt;/img&gt;&lt;/a&gt;     &lt;a href="https://coolshell.cn/articles/17066.html"&gt;关于移动端的钓鱼式攻击&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;The post  &lt;a href="https://coolshell.cn/articles/21708.html"&gt;网络数字身份认证术&lt;/a&gt; first appeared on  &lt;a href="https://coolshell.cn"&gt;酷 壳 - CoolShell&lt;/a&gt;.&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>程序设计 网络安全 mTLS Security TLS</category>
      <guid isPermaLink="true">https://itindex.net/detail/61989-%E7%BD%91%E7%BB%9C-%E6%95%B0%E5%AD%97%E8%BA%AB%E4%BB%BD-%E8%AE%A4%E8%AF%81</guid>
      <pubDate>Sun, 02 Jan 2022 16:38:13 CST</pubDate>
    </item>
    <item>
      <title>网络成瘾消除了读书的习惯？</title>
      <link>https://itindex.net/detail/61968-%E7%BD%91%E7%BB%9C%E6%88%90%E7%98%BE-%E6%B6%88%E9%99%A4-%E8%AF%BB%E4%B9%A6</link>
      <description>2021 年即将结束，你阅读了多少本书？是不是手机屏幕占据了你越来越多的时间？世界各地的统计数据都显示，人们在网络上投入的时间越来越长（手机或 PC 都是互联网的载体）。伴随着碎片化的上网冲浪， &lt;a href="https://benwajdi.com/2021/12/18/is-internet-addiction-eradicating-the-habit-of-reading/"&gt;一种显而易见的现象是&lt;/a&gt;：人们的注意力越来越难以集中。而阅读是一个需要摆脱干扰集中注意力的过程。很多人对此现象进行反思，认为需要主动限制上网。许多人认为不能上网能让他们走得更慢，思考更深入，做出选择时能更理性。你只需观察周围的人，就能注意到网络成瘾的危险性。而被认为带来信息自由流动的的互联网却更有可能会加固阶级差异，最受益的是前 1% 的精英，底层的 99% 都在信息过剩的洪流中漂浮，无法攀登社会经济的阶梯。这是互联网的矛盾之处，它在结构上类似民主，但间接增加了不平等。阅读需要缓慢深入的思考，但互联网则让人变成快速的反应者，不断汲取信息的服务员。西班牙作家 Miguel de Unamuno 曾说过，纳粹主义通过阅读治愈，种族主义通过旅行治愈。 &lt;div&gt;
  &lt;a href="http://feeds.feedburner.com/~ff/solidot?a=WaNbBYtryZw:QX4IaZksBrc:yIl2AUoC8zA"&gt;   &lt;img border="0" src="http://feeds.feedburner.com/~ff/solidot?d=yIl2AUoC8zA"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;a href="http://feeds.feedburner.com/~ff/solidot?a=WaNbBYtryZw:QX4IaZksBrc:7Q72WNTAKBA"&gt;   &lt;img border="0" src="http://feeds.feedburner.com/~ff/solidot?d=7Q72WNTAKBA"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61968-%E7%BD%91%E7%BB%9C%E6%88%90%E7%98%BE-%E6%B6%88%E9%99%A4-%E8%AF%BB%E4%B9%A6</guid>
      <pubDate>Sun, 19 Dec 2021 22:47:02 CST</pubDate>
    </item>
    <item>
      <title>使用python打造自己的信息收集工具 - FreeBuf网络安全行业门户</title>
      <link>https://itindex.net/detail/61796-python-%E4%BF%A1%E6%81%AF-%E5%B7%A5%E5%85%B7</link>
      <description>&lt;div&gt;    &lt;p&gt;      &lt;strong&gt;介绍：&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;该篇章主要介绍如何编写自己的信息收集工具，主要流程如下：&lt;/p&gt;    &lt;p&gt;1、向bing搜索引擎发起request请求，获取url数据&lt;/p&gt;    &lt;p&gt;2、使用正则表达式对获取的数据进行处理&lt;/p&gt;    &lt;p&gt;3、用多线程，对处理的数据进行二次请求，返回标题等数据&lt;/p&gt;    &lt;p&gt;4、使用openyxl模块，将数据保存为.xlsx格式&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;请注意：&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;该篇章目的是熟悉python编程，学习python的一些常见模块，在编写程序的过程中会有很多操作和方式方法，望大家能共同加油学到东西。本文仅用于技术讨论与研究，这里使用的技术仅用于学习教育目的，如果列出的技术用于其他任何目标，本站及作者概不负责。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;本文涉及到模块有：&lt;/strong&gt;&lt;/p&gt;    &lt;pre&gt;#coding:utf-8        &lt;br /&gt;import requests     #发起request请求      &lt;br /&gt;import urllib3      #处理请求https异常报错问题      &lt;br /&gt;import re       #使用正则表达式对请求到的数据进行处理      &lt;br /&gt;from optparse import OptionParser   #自定义输入参数      &lt;br /&gt;import threading        #多线程模块      &lt;br /&gt;import queue            #多线程辅助模块，使用队列的方式对多线程进行控制      &lt;br /&gt;from bs4 import BeautifulSoup   #与re类似 使用正则表达式对请求到的数据进行处理      &lt;br /&gt;import time,datetime    #获取当前的时间      &lt;br /&gt;from openpyxl import  * #数据处理，将获取到的数据保存在excel文件中&lt;/pre&gt;    &lt;p&gt;      &lt;strong&gt;属性：&lt;/strong&gt;&lt;/p&gt;    &lt;pre&gt;heads = {                       #全局变量  请求头      &lt;br /&gt;&amp;apos;User-Agent&amp;apos;:&amp;apos;Mozilla/5.0 (Windows NT 10.0; Win64; x64)                          AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36&amp;apos;,   #模拟浏览器请求      &lt;br /&gt;&amp;apos;Connection&amp;apos;:&amp;apos;close&amp;apos;,        &lt;br /&gt;&amp;apos;Accept-Encoding&amp;apos;:&amp;apos;gzip, deflate&amp;apos;      &lt;br /&gt;}      &lt;br /&gt;count=1                         #全局变量  用于序号字段      &lt;br /&gt;queueLock = threading.Lock()    #全局变量  使用线程锁处理 线程异常问题      &lt;br /&gt;class DoRun(threading.Thread):  #自定义 多线程运行时使用的类&lt;/pre&gt;    &lt;p&gt;      &lt;strong&gt;方法：&lt;/strong&gt;&lt;/p&gt;    &lt;pre&gt;def get_Input():    #获取search语句 和 page      &lt;br /&gt;def getUrls(search,page):       #构造搜索语句，在bing搜索引擎搜索数据并返回urls      &lt;br /&gt;def req(url):   #对url进行验证，返回numb,url,title,status      &lt;br /&gt;def init_excel(filename):  #创建.xlsx表格，并初始化内容      &lt;br /&gt;def Save_Date(date,filename):   #将数据存储到表格当中      &lt;br /&gt;def run():     #核心代码&lt;/pre&gt;    &lt;p&gt;      &lt;strong&gt;完整代码如下：&lt;/strong&gt;&lt;/p&gt;    &lt;pre&gt;#coding:utf-8        &lt;br /&gt;import requests     #发起request请求      &lt;br /&gt;import urllib3      #处理请求https异常报错问题      &lt;br /&gt;import re       #使用正则表达式对请求到的数据进行处理      &lt;br /&gt;from optparse import OptionParser   #自定义输入参数      &lt;br /&gt;import threading        #多线程模块      &lt;br /&gt;import queue            #多线程辅助模块，使用队列的方式对多线程进行控制      &lt;br /&gt;from bs4 import BeautifulSoup   #与re类似 使用正则表达式对请求到的数据进行处理      &lt;br /&gt;import time,datetime    #获取当前的时间      &lt;br /&gt;from openpyxl import  * #数据处理，将获取到的数据保存在excel文件中      &lt;br /&gt;​      &lt;br /&gt;heads = {                       #全局变量  请求头      &lt;br /&gt;&amp;apos;User-Agent&amp;apos;:&amp;apos;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36&amp;apos;,   #模拟浏览器请求      &lt;br /&gt;&amp;apos;Connection&amp;apos;:&amp;apos;close&amp;apos;,        &lt;br /&gt;&amp;apos;Accept-Encoding&amp;apos;:&amp;apos;gzip, deflate&amp;apos;      &lt;br /&gt;}      &lt;br /&gt;count=1                         #全局变量  用于序号字段      &lt;br /&gt;queueLock = threading.Lock()    #全局变量  使用线程锁处理 线程异常问题      &lt;br /&gt;class DoRun(threading.Thread):  #自定义 多线程运行时使用的类      &lt;br /&gt;def __init__(self,queue,filename):      &lt;br /&gt;threading.Thread.__init__(self)      &lt;br /&gt;self._queue=queue      &lt;br /&gt;self._filename=filename      &lt;br /&gt;def run(self):      &lt;br /&gt;while not self._queue.empty():      &lt;br /&gt;js=req(self._queue.get())      &lt;br /&gt;#print(js)      &lt;br /&gt;queueLock.acquire()      &lt;br /&gt;if(js):      &lt;br /&gt;Save_Date(js,self._filename)      &lt;br /&gt;queueLock.release()              &lt;br /&gt;def init_excel(filename):  #创建.xlsx表格，并初始化内容      &lt;br /&gt;wb=Workbook()      &lt;br /&gt;filename=filename+&amp;quot;.xlsx&amp;quot;      &lt;br /&gt;ws=wb.create_sheet(index=0,title=&amp;quot;域名&amp;quot;)      &lt;br /&gt;head=[&amp;apos;序号&amp;apos;,&amp;apos;域名&amp;apos;,&amp;apos;标题&amp;apos;,&amp;apos;状态&amp;apos;]      &lt;br /&gt;for i in range(0,4):      &lt;br /&gt;ws.cell(1,i+1).value=head[i]      &lt;br /&gt;wb.save(filename)      &lt;br /&gt;def Save_Date(date,filename):   #将数据存储到表格当中      &lt;br /&gt;filename=filename+&amp;quot;.xlsx&amp;quot;      &lt;br /&gt;wb_save=load_workbook(filename)      &lt;br /&gt;ws_save=wb_save.worksheets[0]      &lt;br /&gt;current_row=ws_save.max_row+1      &lt;br /&gt;current_col=1      &lt;br /&gt;for key in date:      &lt;br /&gt;ws_save.cell(date[&amp;apos;numb&amp;apos;]+1,current_col).value=str(date[key])      &lt;br /&gt;current_col+=1      &lt;br /&gt;wb_save.save(filename)      &lt;br /&gt;def req(url):   #对域名进行验证，返回状态码，title      &lt;br /&gt;global count      &lt;br /&gt;dir={&amp;apos;numb&amp;apos;:0,&amp;apos;url&amp;apos;:&amp;apos;url&amp;apos;,&amp;apos;title&amp;apos;:&amp;apos;None&amp;apos;,&amp;apos;status&amp;apos;:0}      &lt;br /&gt;stat=0      &lt;br /&gt;title=&amp;quot;None&amp;quot;      &lt;br /&gt;      &lt;br /&gt;try:      &lt;br /&gt;urllib3.disable_warnings()      &lt;br /&gt;response = requests.get(url=url,headers=heads,verify=False,timeout=10)   #请求漏洞的url      &lt;br /&gt;if response.status_code == 200:      &lt;br /&gt;bs=BeautifulSoup(response.content,&amp;quot;html.parser&amp;quot;)      &lt;br /&gt;title=bs.find(&amp;quot;title&amp;quot;).text      &lt;br /&gt;stat=response.status_code      &lt;br /&gt;dir[&amp;apos;numb&amp;apos;]=count      &lt;br /&gt;dir[&amp;apos;url&amp;apos;]=url      &lt;br /&gt;dir[&amp;apos;title&amp;apos;]=title      &lt;br /&gt;dir[&amp;apos;status&amp;apos;]=stat      &lt;br /&gt;count+=1      &lt;br /&gt;print(&amp;quot;[+]&amp;quot;+url+&amp;quot;\ttitle:&amp;quot;+title)      &lt;br /&gt;return dir      &lt;br /&gt;else:      &lt;br /&gt;print(&amp;apos;[-]请求失败：\t{}\t{}&amp;apos;.format(url,response.status_code))      &lt;br /&gt;except Exception as e:      &lt;br /&gt;print(&amp;apos;[-]请求失败: {}\t&amp;apos;.format(e,url))      &lt;br /&gt;def getUrls(search,page):       #构造搜索语句，在bing搜索引擎 搜索数据并返回urls      &lt;br /&gt;count=1      &lt;br /&gt;urls=[]      &lt;br /&gt;url=&amp;quot;https://cn.bing.com/search?q={}&amp;amp;first={}&amp;quot;      &lt;br /&gt;for i in range(1,page):      &lt;br /&gt;if(i!=1):      &lt;br /&gt;count=(i-2)*10+9      &lt;br /&gt;url=url.format(search,i)      &lt;br /&gt;try:      &lt;br /&gt;resp=requests.get(url=url,headers=heads)      &lt;br /&gt;html=resp.text      &lt;br /&gt;if(resp.status_code==200):      &lt;br /&gt;res=re.findall(r&amp;apos;&amp;lt;a target=&amp;quot;_blank&amp;quot; href=&amp;quot;(.*?)&amp;quot;&amp;apos;,html)      &lt;br /&gt;for u in res:      &lt;br /&gt;if(u not in urls):      &lt;br /&gt;urls.append(u)      &lt;br /&gt;else:      &lt;br /&gt;print(&amp;apos;[-]请求失败：\t{}\t{}&amp;apos;.format(url,resp.status_code))      &lt;br /&gt;except Exception as e:      &lt;br /&gt;print(&amp;apos;[-]请求失败: {}\t&amp;apos;.format(e,url))      &lt;br /&gt;​      &lt;br /&gt;return urls      &lt;br /&gt;def get_Input():    #获取search语句 和 page      &lt;br /&gt;optParser = OptionParser()      &lt;br /&gt;optParser.add_option(&amp;apos;-s&amp;apos;,&amp;apos;--search&amp;apos;,action = &amp;apos;store&amp;apos;,type = &amp;quot;string&amp;quot; ,dest = &amp;apos;search&amp;apos;,help=&amp;apos;漏扫文件的目录&amp;apos;,default=&amp;quot;search_def&amp;quot;)      &lt;br /&gt;optParser.add_option(&amp;quot;-p&amp;quot;,&amp;quot;--page&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;int&amp;quot;,dest=&amp;quot;page&amp;quot;,help=&amp;apos;要搜索的页数&amp;apos;,default=10)                  &lt;br /&gt;optParser.add_option(&amp;quot;-t&amp;quot;,&amp;quot;--threads&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;int&amp;quot;,dest=&amp;quot;threads&amp;quot;,help=&amp;apos;线程数量，默认为10&amp;apos;,default=10)                  &lt;br /&gt;(options , args) = optParser.parse_args()      &lt;br /&gt;return options.search,options.page,options.threads      &lt;br /&gt;def run():                &lt;br /&gt;que=queue.Queue()      &lt;br /&gt;print(datetime.datetime.now())              #打印开始时间      &lt;br /&gt;search,page,thread_count=get_Input()        #获取输入的参数 如searce 、线程数、页面数      &lt;br /&gt;if(search==&amp;quot;search_def&amp;quot;):      &lt;br /&gt;print(r&amp;quot;[-]错误，未输入指定参数：python3 temp.py -s site:qq.com [-p 10] [-t 20] &amp;quot;)      &lt;br /&gt;return      &lt;br /&gt;print(search)      &lt;br /&gt;threads=[]      &lt;br /&gt;urls=getUrls(search,page)     #获取urls      &lt;br /&gt;filename=&amp;apos;&amp;apos;.join(re.findall(&amp;quot;([a-z,0-9])&amp;quot;,search))      #将输入的内容进行处理 ，作为文件的名称      &lt;br /&gt;init_excel(filename)        #创建并初始化excel        &lt;br /&gt;for url in urls:      &lt;br /&gt;que.put(url)            #将获取的urls添加到queue中        &lt;br /&gt;for i in range(thread_count):      &lt;br /&gt;threads.append(DoRun(que,filename))     #使用多线程 默认调用 run()函数      &lt;br /&gt;for i in threads:      &lt;br /&gt;i.start()               #启动多线程      &lt;br /&gt;for i in threads:      &lt;br /&gt;i.join()                #等待线程结束      &lt;br /&gt;​      &lt;br /&gt;print(datetime.datetime.now())      #打印结束时间      &lt;br /&gt;run()&lt;/pre&gt;    &lt;p&gt;      &lt;strong&gt;使用说明：*&lt;/strong&gt;***&lt;/p&gt;    &lt;pre&gt;python3 .\bingying.py -s &amp;quot;site:.com&amp;quot; -p 10 -t 30      &lt;br /&gt;Options:      &lt;br /&gt;-h, --help  show this help message and exit      &lt;br /&gt;-s SEARCH, --search=SEARCH    搜索的语法(默认 site:.com)      &lt;br /&gt;-p PAGE, --page=PAGE          要搜索的页数（一页10条数据，默认10页）      &lt;br /&gt;-t THREADS, --threads=THREADS 线程数量，(默认为10)&lt;/pre&gt;    &lt;p&gt;      &lt;strong&gt;结果呈现&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img alt="1632291957_614acc75cf719787794df.png!small" src="https://image.3001.net/images/20210922/1632291957_614acc75cf719787794df.png!small"&gt;&lt;/img&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61796-python-%E4%BF%A1%E6%81%AF-%E5%B7%A5%E5%85%B7</guid>
      <pubDate>Thu, 23 Sep 2021 17:36:12 CST</pubDate>
    </item>
    <item>
      <title>在理解通用近似定理之前，你可能都不会理解神经网络</title>
      <link>https://itindex.net/detail/61762-%E7%90%86%E8%A7%A3-%E9%80%9A%E7%94%A8-%E8%BF%91%E4%BC%BC</link>
      <description>&lt;section&gt;此前，图灵奖得主、&lt;mark data-id="01946acc-d031-4c0e-909c-f062643b7273" data-type="tech_methods"&gt;深度学习&lt;/mark&gt;先驱 Yann LeCun 的一条推文引来众多网友的讨论。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;在该推文中，LeCun 表示：「&lt;mark data-id="01946acc-d031-4c0e-909c-f062643b7273" data-type="tech_methods"&gt;深度学习&lt;/mark&gt;并不像你想象的那么令人印象深刻，因为它仅仅是通过&lt;mark data-id="0990c89d-43f1-494a-aaca-532efc111735" data-type="tech_tasks"&gt;曲线拟合&lt;/mark&gt;产生的&lt;mark data-id="8c0112be-a657-49af-b386-f7aee73cb752" data-type="tech_methods"&gt;插值&lt;/mark&gt;结果。但在高维空间中，不存在&lt;mark data-id="8c0112be-a657-49af-b386-f7aee73cb752" data-type="tech_methods"&gt;插值&lt;/mark&gt;这样的情况。在高维空间中，一切都是外推。」&lt;/section&gt;&lt;p&gt;&lt;img data-cropselx1="0" data-cropselx2="578" data-cropsely1="0" data-cropsely2="456" data-ratio="0.6514195583596214" data-s="300,640" src="https://image.jiqizhixin.com/uploads/editor/90270476-9ef0-44a9-af15-f39773b21829/640.jpeg" data-type="jpeg" data-w="634" data-imgqrcoded="1" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;而 LeCun 转发的内容来自哈佛认知科学家 Steven Pinker 的一条推文，Pinker 表示：「 通用近似定理很好地解释了为什么&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;能工作以及为什么它们经常不起作用。只有理解了 Andre Ye 的通用近似定理，你才能理解&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;。」&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="1.0916030534351144" data-s="300,640" src="https://image.jiqizhixin.com/uploads/editor/1c080e3b-e695-43ad-a465-cb2b642619b4/640.png" data-type="png" data-w="524" data-imgqrcoded="1" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;Pinker 所提到的 Andre Ye，正是接下来要介绍《You Don’t Understand Neural Networks Until You Understand the Universal Approximation Theorem》文章的作者。虽然该文章是去年的，但在理解&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;方面起到非常重要的作用。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;在人工&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;的数学理论中， 通用近似定理（或称万能近似定理）指出人工&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;近似任意函数的能力。通常此定理所指的&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;为前馈&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;，并且被近似的&lt;mark data-id="a3ee878c-7013-408b-8e6b-7b1038057f8f" data-type="concepts"&gt;目标函数&lt;/mark&gt;通常为输入输出都在欧几里得空间的连续函数。但亦有研究将此定理扩展至其他类型的&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;，如卷积&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;、放射状基底函数网络、或其他特殊&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;此定理意味着&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;可以用来近似任意的复杂函数，并且可以达到任意近似精准度。但它并没有告诉我们如何选择&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;&lt;mark data-id="2e982b73-88e2-41e8-a430-f7ae5a9af4bf" data-type="concepts"&gt;参数&lt;/mark&gt;（&lt;mark data-id="149a12cf-10c2-4555-9899-cc6dee319ef5" data-type="concepts"&gt;权重&lt;/mark&gt;、&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;数量、神经层层数等等）来达到我们想近似的&lt;mark data-id="a3ee878c-7013-408b-8e6b-7b1038057f8f" data-type="concepts"&gt;目标函数&lt;/mark&gt;。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;1989 年，George Cybenko 最早提出并证明了单一隐藏层、任意宽度、并使用 S 函数作为激励函数的前馈&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;的通用近似定理。两年后 1991 年，Kurt Hornik 研究发现，&lt;mark data-id="1697e627-30e7-48a6-b799-39e2338ffab5" data-type="concepts"&gt;激活函数&lt;/mark&gt;的选择不是关键，前馈&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;的多层神经层及多&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;架构才是使&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;有成为通用逼近器的关键。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;最重要的是，该定理解释了为什么&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;似乎表现得如此聪明。理解它是发展对&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;深刻理解的关键一步。&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;更深层次的探索&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;紧凑（有限、封闭）集合上的任何连续函数都可以用分段函数逼近。以 - 3 和 3 之间的正弦波为例，它可以用三个函数来近似——两个二次函数和一个线性函数，如下图所示。&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.275" data-s="300,640" src="https://image.jiqizhixin.com/uploads/editor/cc056851-7dce-4661-94ea-44d71970a3ad/640.png" data-type="png" data-w="1000" data-imgqrcoded="1" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;然而，Cybenko 对这个分段函数描述更为具体，因为它可以是恒定，本质上通过 step 来拟合函数。有了足够多的恒定域 (step)，我们就可以在给定的范围内合理地估计函数。&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.33" data-s="300,640" src="https://image.jiqizhixin.com/uploads/editor/96f7292f-72d8-401b-9af4-0f6f21dcb77b/640.png" data-type="png" data-w="1000" data-imgqrcoded="1" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;基于这种近似，我们可以将&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;当做 step 来构建网络。利用权值和偏差作为「门」来确定哪个输入下降，哪个&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;应该被激活，一个有足够数量&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;的&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;可以简单地将一个函数划分为几个恒定区域来估计。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;对于落在&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;下降部分的输入信号，通过将&lt;mark data-id="149a12cf-10c2-4555-9899-cc6dee319ef5" data-type="concepts"&gt;权重&lt;/mark&gt;放大到较大的值，最终的值将接近 1(当使用 sigmoid 函数计算时)。如果它不属于这个部分，将&lt;mark data-id="149a12cf-10c2-4555-9899-cc6dee319ef5" data-type="concepts"&gt;权重&lt;/mark&gt;移向负无穷将产生接近于 0 的最终结果。使用 sigmoid 函数作为某种处理器来确定&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;的存在程度，只要有大量的&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;，任何函数都可以近乎完美地近似。在多维空间中，Cybenko 推广了这一思想，每个&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;在多维函数中控制空间的超立方体。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;通用近似定理的关键在于，它不是在输入和输出之间建立复杂的数学关系，而是使用简单的线性操作将复杂的函数分割成许多小的、不那么复杂的部分，每个部分由一个&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;处理。&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.262" data-s="300,640" src="https://image.jiqizhixin.com/uploads/editor/d0dbf342-23ba-4317-b2b5-24f3b840fb87/640.png" data-type="png" data-w="1000" data-imgqrcoded="1" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;自 Cybenko 的初始证明以后，学界已经形成了许多新的改进，例如针对不同的&lt;mark data-id="1697e627-30e7-48a6-b799-39e2338ffab5" data-type="concepts"&gt;激活函数&lt;/mark&gt;（例如 ReLU），或者具有不同的架构（循环网络、卷积等）测试通用近似定理。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;不管怎样，所有这些探索都围绕着一个想法——&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;在&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;数量中找到优势。每个&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;监视特征空间的一个模式或区域，其大小由网络中&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;的数量决定。&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;越少，每个&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;需要监视的空间就越多，因此近似能力就会下降。但是，随着&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;增多，无论&lt;mark data-id="1697e627-30e7-48a6-b799-39e2338ffab5" data-type="concepts"&gt;激活函数&lt;/mark&gt;是什么，任何函数都可以用许多小片段拼接在一起。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;泛化和外推&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;有人可能指出，通用近似定理虽然简单，但有点过于简单（至少在概念上）。&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;可以分辨数字、生成音乐等，并且通常表现得很智能，但实际上只是一个复杂的逼近器。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;旨在对给定的数据点，能够建模出复杂的数学函数。&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;是个很好的逼近器，但是，如果输入超出了训练范围，它们就失去了作用。这类似于有限泰勒级数近似，在一定范围内可以拟合正弦波，但超出范围就失效了。&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.18285714285714286" data-s="300,640" src="https://image.jiqizhixin.com/uploads/editor/ea9422c6-cecf-401a-b12a-a313b9ef9c3a/640.png" data-type="png" data-w="700" data-imgqrcoded="1" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;外推，或者说在给定的训练范围之外做出合理预测的能力，这并不是&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;设计的目的。从通用近似定理，我们了解到&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;并不是真正的智能，而是隐藏在多维度伪装下的估计器，在二维或三维中看起来很普通。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;定理的实际意义&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;当然，通用逼近定理假设可以继续向无穷大添加&lt;mark data-id="b5cce590-1c61-4d22-8e75-fe74128079c3" data-type="concepts"&gt;神经元&lt;/mark&gt;，这在实践中是不可行的。此外，使用&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;近乎无限的&lt;mark data-id="2e982b73-88e2-41e8-a430-f7ae5a9af4bf" data-type="concepts"&gt;参数&lt;/mark&gt;组合来寻找性能最佳的组合也是不切实际的。然而，该定理还假设只有一个隐藏层，并且随着添加更多隐藏层，复杂性和通用逼近的潜力呈指数增长。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;取而代之的是，&lt;mark data-id="1a0e9c5e-6502-4cd7-8683-6b5ca6c48be2" data-type="tech_methods"&gt;机器学习&lt;/mark&gt;工程师依据直觉和经验决定了如何构造适合给定问题的&lt;mark data-id="72b0bcc0-d8f9-4edd-919f-fa7c2560388c" data-type="tech_methods"&gt;神经网络&lt;/mark&gt;架构，以便它能够很好地逼近多维空间，知道这样一个网络的存在，但也要权衡计算性能。&lt;/section&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61762-%E7%90%86%E8%A7%A3-%E9%80%9A%E7%94%A8-%E8%BF%91%E4%BC%BC</guid>
      <pubDate>Tue, 07 Sep 2021 14:31:00 CST</pubDate>
    </item>
    <item>
      <title>国家新闻出版署：未成年人仅可在周五六日和法定节假日玩1小时网络游戏</title>
      <link>https://itindex.net/detail/61748-%E5%9B%BD%E5%AE%B6-%E6%96%B0%E9%97%BB-%E5%87%BA%E7%89%88</link>
      <description>&lt;p&gt;【TechWeb】8月30日消息，据新华社消息，国家新闻出版署近日印发《关于进一步严格管理切实防止未成年人沉迷网络游戏的通知》，针对未成年人过度使用甚至沉迷网络游戏问题，进一步严格管理措施。 &lt;/p&gt;
 &lt;p&gt;通知针对防止未成年人沉迷网络游戏的关键环节，主要提出四方面举措：&lt;/p&gt;
 &lt;p&gt;一是在原有规定基础上，进一步限制向未成年人提供网络游戏服务的时段时长，要求网络游戏企业大幅压缩向未成年人提供网络游戏的时间，所有网络游戏企业仅可在周五、周六、周日和法定节假日每日的20时至21时向未成年人提供1小时服务，其他时间一律不得向未成年人提供网络游戏服务。&lt;/p&gt;
 &lt;p&gt;二是在国家新闻出版署网络游戏防沉迷实名验证系统已建成运行后，重申严格落实网络游戏账号实名注册要求，明确所有网络游戏必须接入该系统，所有网络游戏用户必须使用真实有效身份信息进行游戏账号注册和登录，网络游戏企业不得以任何形式(含游客体验模式)向未实名注册和登录的用户提供游戏服务。&lt;/p&gt;
 &lt;p&gt;三是加强对防沉迷措施落实情况的监督检查。针对网络游戏企业提供游戏服务的时间限制、实名注册、规范付费等方面要求的落实情况，出版管理部门将加大检查频次和力度，对未严格落实的网络游戏企业，依法依规严肃处理。&lt;/p&gt;
 &lt;p&gt;四是积极引导家庭、学校等社会各方面行动起来，切实承担监护守护职责，共同营造有利于未成年人健康成长的良好环境，形成防止未成年人沉迷网络游戏的工作合力。&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#25991;&amp;#31456;" border="0" src="http://s1.techweb.com.cn/static/img/20180614.png"&gt;&lt;/img&gt;&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>TechWeb</category>
      <guid isPermaLink="true">https://itindex.net/detail/61748-%E5%9B%BD%E5%AE%B6-%E6%96%B0%E9%97%BB-%E5%87%BA%E7%89%88</guid>
      <pubDate>Mon, 30 Aug 2021 17:35:00 CST</pubDate>
    </item>
    <item>
      <title>国家中小学网络云平台</title>
      <link>https://itindex.net/detail/61670-%E5%9B%BD%E5%AE%B6-%E5%B0%8F%E5%AD%A6-%E7%BD%91%E7%BB%9C</link>
      <description>&lt;div&gt;【国家中小学网络云平台】教育部推出的免费小学、初中、高中的所有学习科目，上下册都有，点开就能学习，不用下载app，＂双减＂下的国家配套支持。http://t.cn/A6IArcfe ​​​  &lt;br /&gt;&lt;/div&gt; &lt;div&gt;  &lt;br /&gt;&lt;/div&gt; &lt;ul&gt;    &lt;div&gt;&lt;/div&gt;    &lt;li&gt;      &lt;div&gt;小学：&lt;/div&gt;      &lt;div&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njs001&amp;xkcode=yuwen0" target="_self"&gt;一年级上&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njs002&amp;xkcode=yuwen0" target="_self"&gt;二年级上&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njs003&amp;xkcode=yuwen0" target="_self"&gt;三年级上&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njs004&amp;xkcode=yuwen0" target="_self"&gt;四年级上&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njs005&amp;xkcode=yuwen0" target="_self"&gt;五年级上&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njs006&amp;xkcode=yuwen0" target="_self"&gt;六年级上&lt;/a&gt;        &lt;div&gt;&lt;/div&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njx001&amp;xkcode=yuwen0" target="_self"&gt;一年级下&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njx002&amp;xkcode=yuwen0" target="_self"&gt;二年级下&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njx003&amp;xkcode=yuwen0" target="_self"&gt;三年级下&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njx004&amp;xkcode=yuwen0" target="_self"&gt;四年级下&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njx005&amp;xkcode=yuwen0" target="_self"&gt;五年级下&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0001&amp;njcode=njx006&amp;xkcode=yuwen0" target="_self"&gt;六年级下&lt;/a&gt;&lt;/div&gt;      &lt;div&gt;&lt;/div&gt;&lt;/li&gt;    &lt;li&gt;      &lt;div&gt;初中：&lt;/div&gt;      &lt;div&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0002&amp;njcode=njs007&amp;xkcode=yuwen0" target="_self"&gt;七年级上&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0002&amp;njcode=njs008&amp;xkcode=yuwen0" target="_self"&gt;八年级上&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0002&amp;njcode=njs009&amp;xkcode=yuwen0" target="_self"&gt;九年级上&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0002&amp;njcode=njx007&amp;xkcode=yuwen0" target="_self"&gt;七年级下&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0002&amp;njcode=njx008&amp;xkcode=yuwen0" target="_self"&gt;八年级下&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0002&amp;njcode=njx009&amp;xkcode=yuwen0" target="_self"&gt;九年级下&lt;/a&gt;&lt;/div&gt;      &lt;div&gt;&lt;/div&gt;&lt;/li&gt;    &lt;li&gt;      &lt;div&gt;高中：&lt;/div&gt;      &lt;div&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0003&amp;njcode=njs0010&amp;xkcode=yuwen0" target="_self"&gt;高一上&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0003&amp;njcode=njs0011&amp;xkcode=yuwen0" target="_self"&gt;高二上&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0003&amp;njcode=njx0010&amp;xkcode=yuwen0" target="_self"&gt;高一下&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0003&amp;njcode=njx0011&amp;xkcode=yuwen0" target="_self"&gt;高二下&lt;/a&gt;        &lt;a href="https://tongbu.eduyun.cn/tbkt/tbkthtml/h5.html?xdcode=xd0003&amp;njcode=njx0012&amp;xkcode=yuwen0" target="_self"&gt;高三&lt;/a&gt;&lt;/div&gt;      &lt;div&gt;&lt;/div&gt;&lt;/li&gt;    &lt;li&gt;温馨提示：控制上网时间，保护视力、锻炼身体！&lt;/li&gt;&lt;/ul&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61670-%E5%9B%BD%E5%AE%B6-%E5%B0%8F%E5%AD%A6-%E7%BD%91%E7%BB%9C</guid>
      <pubDate>Mon, 09 Aug 2021 08:18:25 CST</pubDate>
    </item>
    <item>
      <title>k8s 重置，更换网络插件_云深不知处的技术博客_51CTO博客</title>
      <link>https://itindex.net/detail/61649-k8s-%E7%BD%91%E7%BB%9C-%E6%8F%92%E4%BB%B6</link>
      <description>&lt;div&gt;    &lt;h1&gt;一，重置k8s&lt;/h1&gt;    &lt;p&gt;1，主节点：      &lt;br /&gt;kubectl delete node node01 node02 master      &lt;br /&gt;kubeadm reset      &lt;br /&gt;rm -rf  .kube /var/log/containers /var/log/pods      &lt;br /&gt;2，从节点      &lt;br /&gt;kubeadm reset      &lt;br /&gt;rm -rf  .kube /var/log/containers /var/log/pods&lt;/p&gt;    &lt;h1&gt;二，更换网络插件&lt;/h1&gt;    &lt;p&gt;卸载flannel：      &lt;br /&gt;在master节点删除flannel      &lt;br /&gt;kubectl delete -f kube-flannel.yml      &lt;br /&gt;重启kubelet      &lt;br /&gt;sytemctl restart kubelet      &lt;br /&gt;安装calico：      &lt;br /&gt;wget      &lt;a href="https://docs.projectcalico.org/manifests/calico.yaml" rel="nofollow"&gt;https://docs.projectcalico.org/manifests/calico.yaml&lt;/a&gt;      &lt;br /&gt;kubectl apply -f calico.yaml      &lt;br /&gt;安装完毕后使用docker images 查看容器镜像可以看见如下以calico打头的镜像      &lt;br /&gt;      &lt;img alt="k8s&amp;#23398;&amp;#20064;&amp;#31508;&amp;#35760;&amp;#20043;&amp;#23433;&amp;#35013;&amp;#20108;&amp;#8212;&amp;#8212;&amp;#37325;&amp;#32622;&amp;#65292;&amp;#26356;&amp;#25442;&amp;#32593;&amp;#32476;&amp;#25554;&amp;#20214;" src="https://s4.51cto.com/images/blog/202006/15/e13dc20cbf128e944eb46b8b8725c101.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk="&gt;&lt;/img&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61649-k8s-%E7%BD%91%E7%BB%9C-%E6%8F%92%E4%BB%B6</guid>
      <pubDate>Wed, 28 Jul 2021 19:27:17 CST</pubDate>
    </item>
    <item>
      <title>k8s网络之Flannel网络 - 金色旭光 - 博客园</title>
      <link>https://itindex.net/detail/61631-k8s-%E7%BD%91%E7%BB%9C-flannel</link>
      <description>&lt;div&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;k8s网络主题系列：&lt;/p&gt;    &lt;p&gt;      &lt;a href="https://www.cnblogs.com/goldsunshine/p/10740090.html" target="_blank"&gt;一、k8s网络之设计与实现&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;      &lt;a href="https://www.cnblogs.com/goldsunshine/p/10740928.html%20" target="_blank"&gt;二、k8s网络之Flannel网络&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;      &lt;a href="https://www.cnblogs.com/goldsunshine/p/10701242.html" target="_blank"&gt;三、k8s网络之Calico网络&lt;/a&gt;&lt;/p&gt;    &lt;h1&gt;      &lt;strong&gt;简介&lt;/strong&gt;&lt;/h1&gt;    &lt;p&gt;Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务，简单来说，它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。&lt;/p&gt;    &lt;p&gt;在默认的Docker配置中，每个节点上的Docker服务会分别负责所在节点容器的IP分配。这样导致的一个问题是，不同节点上容器可能获得相同的内外IP地址。并使这些容器之间能够之间通过IP地址相互找到，也就是相互ping通。&lt;/p&gt;    &lt;p&gt;Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则，从而使得不同节点上的容器能够获得“同属一个内网”且”不重复的”IP地址，并让属于不同节点上的容器能够直接通过内网IP通信。&lt;/p&gt;    &lt;p&gt;Flannel实质上是一种“覆盖网络(overlaynetwork)”，也就是将TCP数据包装在另一种网络包里面进行路由转发和通信，目前已经支持udp、vxlan、host-gw、aws-vpc、gce和alloc路由等数据转发方式，默认的节点间数据通信方式是UDP转发。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;简单总结Flannel的特点&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;1.使集群中的不同Node主机创建的Docker容器都具有全集群唯一的虚拟IP地址。&lt;/p&gt;    &lt;p&gt;2.建立一个覆盖网络（overlay network），通过这个覆盖网络，将数据包原封不动的传递到目标容器。覆盖网络是建立在另一个网络之上并由其基础设施支持的虚拟网络。覆盖网络通过将一个分组封装在另一个分组内来将网络服务与底层基础设施分离。在将封装的数据包转发到端点后，将其解封装。&lt;/p&gt;    &lt;p&gt;3.创建一个新的虚拟网卡flannel0接收docker网桥的数据，通过维护路由表，对接收到的数据进行封包和转发（vxlan）。&lt;/p&gt;    &lt;p&gt;4.etcd保证了所有node上flanned所看到的配置是一致的。同时每个node上的flanned监听etcd上的数据变化，实时感知集群中node的变化。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt; &lt;/strong&gt;&lt;/p&gt;    &lt;h1&gt;      &lt;strong&gt;Flannel&lt;/strong&gt;      &lt;strong&gt;对网络要求&lt;/strong&gt;      &lt;strong&gt;提出的解决办法&lt;/strong&gt;&lt;/h1&gt;    &lt;h2&gt;      &lt;strong&gt;互相不冲突的ip        &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;1.flannel利用Kubernetes API或者etcd用于存储整个集群的网络配置，根据配置记录集群使用的网段。&lt;/p&gt;    &lt;p&gt;2.flannel在每个主机中运行flanneld作为agent，它会为所在主机从集群的网络地址空间中，获取一个小的网段subnet，本主机内所有容器的IP地址都将从中分配。&lt;/p&gt;    &lt;p&gt;如测试环境中ip分配：&lt;/p&gt;    &lt;p&gt;1.master节点&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145028603-1562039245.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;2.node1&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145159494-804778941.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;3.node2&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145219198-1737771650.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145226180-224637322.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt;在flannel network中，每个pod都会被分配唯一的ip地址，且每个K8s node的subnet各不重叠，没有交集。&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;Pod之间互相访问&lt;/strong&gt;&lt;/h2&gt;    &lt;ol&gt;      &lt;li&gt;flanneld将本主机获取的subnet以及用于主机间通信的Public IP通过etcd存储起来，需要时发送给相应模块。&lt;/li&gt;      &lt;li&gt;flannel利用各种backend mechanism，例如udp，vxlan等等，跨主机转发容器间的网络流量，完成容器间的跨主机通信。&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt; &lt;/p&gt;    &lt;h1&gt;      &lt;strong&gt;Flannel架构原理&lt;/strong&gt;&lt;/h1&gt;    &lt;p&gt;      &lt;strong&gt;Flannel&lt;/strong&gt;      &lt;strong&gt;架构图(根据个人理解画的图，和官网的图有一些小差距)&lt;/strong&gt;：&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145249573-1127241268.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p align="justify"&gt;各个组件的解释：&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;strong&gt;Cni0&lt;/strong&gt;:网桥设备，每创建一个pod都会创建一对veth pair。其中一端是pod中的eth0，另一端是Cni0网桥中的端口（网卡）。Pod中从网卡eth0发出的流量都会发送到Cni0网桥设备的端口（网卡）上。&lt;/p&gt;    &lt;p&gt;       &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145308681-317197626.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; Cni0设备获得的ip地址是该节点分配到的网段的第一个地址。&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p align="justify"&gt;      &lt;strong&gt;Flannel.1&lt;/strong&gt;: overlay网络的设备，用来进行vxlan报文的处理（封包和解包）。不同node之间的pod数据流量都从overlay设备以隧道的形式发送到对端。&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145322264-465199087.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p align="justify"&gt;      &lt;strong&gt;Flanneld&lt;/strong&gt;：flannel在每个主机中运行flanneld作为agent，它会为所在主机从集群的网络地址空间中，获取一个小的网段subnet，本主机内所有容器的IP地址都将从中分配。同时Flanneld监听K8s集群数据库，为flannel.1设备提供封装数据时必要的mac，ip等网络数据信息。&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p align="justify"&gt;      &lt;strong&gt;不同node上的pod的通信流程：&lt;/strong&gt;&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;pod中产生数据，根据pod的路由信息，将数据发送到Cni0&lt;/li&gt;      &lt;li&gt;Cni0根据节点的路由表，将数据发送到隧道设备flannel.1&lt;/li&gt;      &lt;li&gt;Flannel.1查看数据包的目的ip，从flanneld获得对端隧道设备的必要信息，封装数据包。&lt;/li&gt;      &lt;li&gt;Flannel.1将数据包发送到对端设备。对端节点的网卡接收到数据包，发现数据包为overlay数据包，解开外层封装，并发送内层封装到flannel.1设备。&lt;/li&gt;      &lt;li&gt;Flannel.1设备查看数据包，根据路由表匹配，将数据发送给Cni0设备。&lt;/li&gt;      &lt;li&gt;Cni0匹配路由表，发送数据给网桥上对应的端口。&lt;/li&gt;&lt;/ol&gt;    &lt;p align="justify"&gt;      &lt;strong&gt; &lt;/strong&gt;&lt;/p&gt;    &lt;h1&gt;      &lt;strong&gt;通信流程&lt;/strong&gt;&lt;/h1&gt;    &lt;h2&gt;      &lt;strong&gt;1.Pod1中的容器到cni0&lt;/strong&gt;&lt;/h2&gt;    &lt;p align="justify"&gt;Pod1与Pod3能够互相ping通&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145345725-337345611.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p align="justify"&gt;Ping包的dst ip为192.20.1.43，根据路由匹配到最后一条路由表项，去往192.20.0.0/12的包都转发给192.20.0.1。&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145401389-532913287.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p align="justify"&gt;192.20.0.1为cni0的ip地址。&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145413015-1004337524.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;2.cni0到flannel1.1&lt;/strong&gt;&lt;/h2&gt;    &lt;p align="justify"&gt;当icmp包达到cni0之后，cni0发现dst为192.20.1.43，cni根据主机路由表来查找匹配项。&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145427108-2140471234.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt;根据最小匹配原则，匹配到图上的一条路由表项。去往192.20.1.0/24网段的包，发送192.20.1.0网关，网关设备是flannel.1。&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;h2&gt;3.      &lt;strong&gt;Flannel.1&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;flannel.1为vxlan设备，当数据包来到flannel.1时，需要将数据包封装起来。此时的dst ip为192.20.1.43，src ip为192.20.0.51。数据包继续封装需要知道192.20.1.43 ip地址对应的mac地址。此时，flannel.1不会发送arp请求去获得192.20.1.42的mac地址，而是由Linux kernel将一个“L3 Miss”事件请求发送的用户空间的flanned程序。Flanned程序收到内核的请求事件之后，从etcd查找能够匹配该地址的子网的flannel.1设备的mac地址，即发往的pod所在host中flannel.1设备的mac地址。Flannel在为Node节点分配ip网段时记录了所有的网段和mac等信息，所以能够知道。交互流程如下图所示：&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145440459-866148029.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p align="justify"&gt;flanned将查询到的信息放入master node host的arp cache表中：&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145453004-206623983.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p align="justify"&gt;到这里，vxlan的内层数据包就完成了封装。格式是这样的：&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145506201-1839601264.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p align="justify"&gt;简单总结这个流程：&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;数据包到达flannel.1，通过查找路由表，知道数据包要通过flannel.1发往192.20.1.0&lt;/li&gt;      &lt;li&gt;通过arp cache表，知道了目的ip192.20.1.0的mac地址。&lt;/li&gt;&lt;/ol&gt;    &lt;p align="justify"&gt;kernel需要查看node上的fdb(forwarding database)以获得内层封包中目的vtep设备所在的node地址。因为已经从arp table中查到目的设备mac地址为52:77:71:e6:4f:58，同时在fdb中存在该mac地址对应的node节点的IP地址。如果fdb中没有这个信息，那么kernel会向用户空间的flanned程序发起”L2 MISS”事件。flanneld收到该事件后，会查询etcd，获取该vtep设备对应的node的”Public IP“，并将信息注册到fdb中。&lt;/p&gt;    &lt;p align="justify"&gt;当内核获得了发往机器的ip地址后，arp得到mac地址，之后就能完成vxlan的外层封装。&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145524328-1990216206.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;4.对端flannel.1&lt;/strong&gt;&lt;/h2&gt;    &lt;p align="justify"&gt;Node节点的eth0网卡接收到vxlan设备包，kernal将识别出这是一个vxlan包，将包拆开之后转给节点上的flannel.1设备。这样数据包就从发送节点到达目的节点，flannel.1设备将接收到一个如下的数据包：      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145537234-1878339801.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p&gt;目的地址为192.20.1.43，flannel.1查找自己的路由表，根据路由表完成转发。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145551119-2117095430.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt;根据最下匹配原则，flannel.1将去往192.20.1.0/24的流量转发到cni0上去。&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;5.cnio到Pod&lt;/strong&gt;&lt;/h2&gt;    &lt;p align="justify"&gt;cni0是一个网桥设备。当cni0拿到数据包之后，通过veth pair，将数据包发送给pod。查看Node节点中的网桥。 &lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145612880-2009563108.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p align="justify"&gt;在node节点上通过arp解析可以开出，192.20.1.43的mac地址为 66:57:8e:3d:00:85      &lt;br /&gt;&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145627101-1742990375.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p align="justify"&gt;该地址为pod的网卡eth0的地址。&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145642859-905674623.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p align="justify"&gt;同时通过veth pair的配对关系可以看出，pod中的eth0是veth pair的一端，另一端在node节点行上，对应的网卡是vethd356ffc1@if3。所以，在cni0网桥上挂载的pod的veth pair为vethd356ffc1，即：&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145704371-1775051009.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p align="justify"&gt;eth0@if50和vethd356ffc1@if3组成的一对veth，pair。其效果相当于将pod中的eth0直接插在到cni0上。所以简单总结cni0转发流量的原理：&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;首先通过arp查找出ip地址对应的mac地址&lt;/li&gt;      &lt;li&gt;将流量转发给mac地址所在eth0网的对应的veth pair端口&lt;/li&gt;      &lt;li&gt;veth pair端口接收到流量，直接将流量注入到pod的eth0网卡上。&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt; &lt;/p&gt;    &lt;h1&gt;      &lt;strong&gt;不同后端的封装&lt;/strong&gt;&lt;/h1&gt;    &lt;p align="justify"&gt;Flannel可以指定不同的转发后端网络，常用的有hostgw，udp，vxlan等。&lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;Hostgw        &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;    &lt;p align="justify"&gt;hostgw是最简单的backend，它的原理非常简单，直接添加路由，将目的主机当做网关，直接路由原始封包。&lt;/p&gt;    &lt;p align="justify"&gt;例如，我们从etcd中监听到一个EventAdded事件subnet为10.1.15.0/24被分配给主机Public IP 192.168.0.100，hostgw要做的工作就是在本主机上添加一条目的地址为10.1.15.0/24，网关地址为192.168.0.100，输出设备为上文中选择的集群间交互的网卡即可。&lt;/p&gt;    &lt;p align="justify"&gt;优点：简单，直接，效率高&lt;/p&gt;    &lt;p align="justify"&gt;缺点：要求所有的pod都在一个子网中，如果跨网段就无法通信。&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;UDP        &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;    &lt;p align="justify"&gt;如何应对Pod不在一个子网里的场景呢？将Pod的网络包作为一个应用层的数据包，使用UDP封装之后在集群里传输。即overlay。&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145722726-793566440.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p align="justify"&gt;上图来自flannel官方，其中右边Packer的封装格式就是使用udp完成overlay的格式&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145739216-374032378.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p align="justify"&gt;当容器10.1.15.2/24要和容器10.1.20.2/24通信时，&lt;/p&gt;    &lt;p align="justify"&gt;1.因为该封包的目的地不在本主机subnet内，因此封包会首先通过网桥转发到主机中。&lt;/p&gt;    &lt;p align="justify"&gt;2.在主机上经过路由匹配，进入网卡flannel.1。(需要注意的是flannel.1是一个tun设备，它是一种工作在三层的虚拟网络设备，而flanneld是一个proxy，它会监听flannel.1并转发流量。)&lt;/p&gt;    &lt;p align="justify"&gt;3.当封包进入flannel.1时，flanneld就可以从flanne.1中将封包读出，由于flanne.1是三层设备，所以读出的封包仅仅包含IP层的报头及其负载。&lt;/p&gt;    &lt;p align="justify"&gt;4.最后flanneld会将获取的封包作为负载数据，通过udp socket发往目的主机。&lt;/p&gt;    &lt;p align="justify"&gt;5.在目的主机的flanneld会监听Public IP所在的设备，从中读取udp封包的负载，并将其放入flannel.1设备内。&lt;/p&gt;    &lt;p align="justify"&gt;6.容器网络封包到达目的主机，之后就可以通过网桥转发到目的容器了。&lt;/p&gt;    &lt;p align="justify"&gt;优点：Pod能够跨网段访问&lt;/p&gt;    &lt;p align="justify"&gt;缺点：隔离性不够，udp不能隔离两个网段。&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;Vxlan        &lt;br /&gt;&lt;/strong&gt;&lt;/h2&gt;    &lt;p align="justify"&gt;vxlan和上文提到的udp backend的封包结构是非常类似的，不同之处是多了一个vxlan header，以及原始报文中多了个二层的报头。&lt;/p&gt;    &lt;p align="justify"&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/1060878/201904/1060878-20190420145758804-1550036759.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p align="justify"&gt;当初始化集群里，vxlan网络的初始化工作：&lt;/p&gt;    &lt;p align="justify"&gt;主机B加入flannel网络时,它会将自己的三个信息写入etcd中，分别是：subnet 10.1.16.0/24、Public IP 192.168.0.101、vtep设备flannel.1的mac地址MAC B。之后，主机A会得到EventAdded事件，并从中获取上文中B添加至etcd的各种信息。这个时候，它会在本机上添加三条信息：&lt;/p&gt;    &lt;p align="justify"&gt;1)路由信息：所有通往目的地址10.1.16.0/24的封包都通过vtep设备flannel.1设备发出，发往的网关地址为10.1.16.0，即主机B中的flannel.1设备。&lt;/p&gt;    &lt;p align="justify"&gt;2) fdb信息：MAC地址为MAC B的封包，都将通过vxlan发往目的地址192.168.0.101，即主机B&lt;/p&gt;    &lt;p align="justify"&gt;3）arp信息：网关地址10.1.16.0的地址为MAC B&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p align="justify"&gt;事实上，flannel只使用了vxlan的部分功能，由于VNI被固定为1，本质上工作方式和udp backend是类似的，区别无非是将udp的proxy换成了内核中的vxlan处理模块。而原始负载由三层扩展到了二层，但是这对三层网络方案flannel是没有意义的，这么做也仅仅只是为了适配vxlan的模型。vxlan详细的原理参见文后的参考文献，其中的分析更为具体，也更易理解。&lt;/p&gt;    &lt;p align="justify"&gt; &lt;/p&gt;    &lt;p align="justify"&gt;总的来说，flannel更像是经典的桥接模式的扩展。我们知道，在桥接模式中，每台主机的容器都将使用一个默认的网段，容器与容器之间，主机与容器之间都能互相通信。要是，我们能手动配置每台主机的网段，使它们互不冲突。接着再想点办法，将目的地址为非本机容器的流量送到相应主机：如果集群的主机都在一个子网内，就搞一条路由转发过去；若是不在一个子网内，就搞一条隧道转发过去。这样以来，容器的跨网络通信问题就解决了。而flannel做的，其实就是将这些工作自动化了而已。&lt;/p&gt;    &lt;h1&gt;      &lt;strong&gt;存在问题&lt;/strong&gt;&lt;/h1&gt;    &lt;p&gt;1.不支持pod之间的网络隔离。Flannel设计思想是将所有的pod都放在一个大的二层网络中，所以pod之间没有隔离策略。&lt;/p&gt;    &lt;p&gt;2.设备复杂，效率不高。Flannel模型下有三种设备，数量经过多种设备的封装、解析，势必会造成传输效率的下降。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;对于flannel网络介绍的文章也很多，其中有一个点有明显的分歧，就是对于flanned的作用。分歧点在于：使用UDP作为后端网络时，flanned会将flanne.1设备的流量经过自己的处理发送给对端的flanned。但是在分析vxlan作为后端网络时明显不是这么做的，在vxlan中flanned作用是获取必要的mac地址，ip地址信息，没有直接处理数据流。这里要存疑，如果有读者能告知，欢迎留言。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61631-k8s-%E7%BD%91%E7%BB%9C-flannel</guid>
      <pubDate>Fri, 23 Jul 2021 20:53:52 CST</pubDate>
    </item>
    <item>
      <title>k8s网络原理之flannel - 渡边彻 - 博客园</title>
      <link>https://itindex.net/detail/61630-k8s-%E7%BD%91%E7%BB%9C-%E5%8E%9F%E7%90%86</link>
      <description>&lt;div&gt;    &lt;p&gt;      &lt;strong&gt;首先当你创建一个k8s集群后一般会存在三种IP分别是,Pod IP,Node IP,Cluster IP&lt;/strong&gt;&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;其中一个Cluster IP之下包含多个Node IP,而一个Node IP之下又包含多个Pod IP,同一个Pod包含多个容器，这些容器的网络都在同一个命名空间,因此它们可以自由的通信,同一个Node包含多个Pod,这些Pod又通过veth pair技术与同一个cni网桥进行连接,通常这个cni网桥就是我们熟知的docker0网卡,这个是在你安装docker后就会创建在宿主机上的一个虚拟网卡,因此相同Node节点下的Pod又可以通过cni网桥进行通信。（这部分的知识我们在docker网络当中有详细的讲解，不了解的同学可以查看之前的微博。）&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;那么不同Node节点下的Pod又是如何进行通信的呢？本文重点要讲的flannel网络插件就是用来解决这个问题的。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;一.在这里有必要先介绍一下flannel&lt;/strong&gt;&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务，他的作用就是实现Pod资源跨主机进行网络通信。        &lt;br /&gt;我们知道在默认的Docker配置中，每个节点上的Docker服务会分别负责所在节点容器的IP分配。这样导致的一个问题是，不同节点上容器可能获得相同的内外IP地址。        &lt;br /&gt;那么flannel可以让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址,使得不同节点上的容器能够获得“同属一个内网”且”不重复的”IP地址，并让属于不同节点上的容器能够直接通过内网IP通信。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;      &lt;strong&gt;二.那么简单总结下flannel的作用有以下几点:&lt;/strong&gt;&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;1.使集群中的不同Node主机创建的Docker容器都具有全集群唯一的虚拟IP地址。        &lt;br /&gt;2.建立一个覆盖网络（overlay network），通过这个覆盖网络，将数据包原封不动的传递到目标容器。覆盖网络是建立在另一个网络之上并由其基础设施支持的虚拟网络。覆盖网络通过将一个分组封装在另一个分组内来将网络服务与底层基础设施分离。在将封装的数据包转发到端点后，将其解封装。        &lt;br /&gt;3.创建一个新的虚拟网卡flannel0接收docker网桥的数据，通过维护路由表，对接收到的数据进行封包和转发（vxlan）。        &lt;br /&gt;4.etcd保证了所有node上flanned所看到的配置是一致的。同时每个node上的flanned监听etcd上的数据变化，实时感知集群中node的变化。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;      &lt;strong&gt;三.flannel网络架构的IP地址规划&lt;/strong&gt;&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;flannel在每个主机中运行flanneld作为agent，它会为所在主机从集群的网络地址空间中，获取一个小的网段subnet，本主机内所有容器的IP地址都将从中分配。        &lt;br /&gt;如测试环境中ip分配：        &lt;br /&gt;1.master节点        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105004245206-1420092906.png"&gt;&lt;/img&gt;        &lt;br /&gt;2.node1        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105004509006-303600776.png"&gt;&lt;/img&gt;        &lt;br /&gt;3.node2        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105004548095-1126115106.png"&gt;&lt;/img&gt;        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105004608484-1912803603.png"&gt;&lt;/img&gt;        &lt;br /&gt;在flannel network中，因为每个K8s node节点的subnet各不重叠，没有交集，因此各节点下的每个pod也都会被分配唯一的ip地址。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;      &lt;strong&gt;四.flannel网络架构原理图&lt;/strong&gt;      &lt;br /&gt;      &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105005418090-1845945052.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;这里借用官网的原理图讲解下各组件的功能：        &lt;br /&gt;1.Cni0:网桥设备，每创建一个pod都会创建一对 veth pair。其中一端是pod中的eth0，另一端是Cni0网桥中的端口（网卡）。Pod中从网卡eth0发出的流量都会发送到Cni0网桥设备的端口（网卡）上。        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105005542900-1718816939.png"&gt;&lt;/img&gt;        &lt;br /&gt;Cni0 设备获得的ip地址是该节点分配到的网段的第一个地址。&lt;/p&gt;&lt;/blockquote&gt;    &lt;blockquote&gt;      &lt;p&gt;2.Flannel.1: overlay网络的设备，用来进行 vxlan 报文的处理（封包和解包）。不同node之间的pod数据流量都从overlay设备以隧道的形式发送到对端。        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105005717727-1007052659.png"&gt;&lt;/img&gt;&lt;/p&gt;&lt;/blockquote&gt;    &lt;blockquote&gt;      &lt;p&gt;3.Flanneld：flannel在每个主机中运行flanneld作为agent，它会为所在主机从集群的网络地址空间中，获取一个小的网段subnet，本主机内所有容器的IP地址都将从中分配。同时Flanneld监听K8s集群数据库，为flannel.1设备提供封装数据时必要的mac，ip等网络数据信息。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;      &lt;strong&gt;不同node上的pod的通信流程：&lt;/strong&gt;&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;pod中产生数据，根据pod的路由信息，将数据发送到Cni0虚拟网桥设备（docker0）        &lt;br /&gt;Cni0虚拟网桥设备根据node节点的路由表，将数据发送到隧道设备flannel.1        &lt;br /&gt;Flannel.1查看数据包的目的ip，从flanneld获得对端隧道设备的必要信息（node节点对应的Mac地址），并对数据包进行封装。        &lt;br /&gt;Flannel.1将数据包发送到对端设备。对端节点的网卡接收到数据包，发现数据包为overlay数据包，解开外层封装，并发送内层封装到flannel.1设备。        &lt;br /&gt;Flannel.1设备查看数据包，根据目的node节点的路由表匹配规则，将数据发送给Cni0虚拟网桥设备。        &lt;br /&gt;Cni0虚拟网桥匹配Node节点路由表，将数据发送给网桥上对应的端口从而将数据传输给对应的目的pod。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;      &lt;strong&gt;不同node节点的pod的通信流程详解：&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;以不同node节点的Pod1 ping Pod3为例      &lt;br /&gt;      &lt;strong&gt;1.pod1到cni0&lt;/strong&gt;      &lt;br /&gt;首先Pod1与Pod3能够互相ping通      &lt;br /&gt;      &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105103623475-2130658808.png"&gt;&lt;/img&gt;      &lt;br /&gt;Ping包的dst ip 为192.20.1.43，根据路由匹配到最后一条路由表项，去往192.20.0.0/12的包都转发给192.20.0.1      &lt;br /&gt;      &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105103654216-63257298.png"&gt;&lt;/img&gt;      &lt;br /&gt;192.20.0.1为cni0的ip地址      &lt;br /&gt;      &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105103743833-2076535503.png"&gt;&lt;/img&gt;      &lt;br /&gt;      &lt;strong&gt;2.cni0到flannel1&lt;/strong&gt;      &lt;br /&gt;      &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105104051545-297908342.png"&gt;&lt;/img&gt;      &lt;br /&gt;根据最长匹配原则，匹配到图上的一条路由表项。去往192.20.1.0/24 网段的包，发送192.20.1.0网关，网关设备是flannel.1      &lt;br /&gt;      &lt;strong&gt;3.源node节点flannel1对数据包进行封装处理并发到远端node节点的flannel1网络接口&lt;/strong&gt;&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;flannel.1为vxlan设备，当数据包来到flannel.1时，需要将数据包封装起来。此时的dst ip 为192.20.1.43，src ip为192.20.0.51。数据包继续封装需要知道192.20.1.43 ip地址对应的mac地址。此时，flannel.1不会发送arp请求去获得192.20.1.42的mac地址，而是由Linux kernel将一个“L3 Miss”事件请求发送给用户空间的flanned程序。Flanned程序收到内核的请求事件之后，从etcd查找能够匹配该目的地址的子网的flannel.1设备的mac地址，即发往的pod所在host中flannel.1设备的mac地址。Flannel在为Node节点分配ip网段时记录了所有的网段和mac等信息，所以能够知道。交互流程如下图所示：        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201105104527465-50022426.png"&gt;&lt;/img&gt;        &lt;br /&gt;flanned将查询到的信息放入master node host的arp cache表中:        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201106095203952-326164846.png"&gt;&lt;/img&gt;        &lt;br /&gt;到这里，vxlan的内层数据包就完成了封装。格式是这样的：        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201106095311927-1402081556.png"&gt;&lt;/img&gt;        &lt;br /&gt;        &lt;strong&gt;4.目的node节点flannel1接收到数据包之后&lt;/strong&gt;        &lt;br /&gt;Node节点的eth0网卡接收到vxlan设备包，kernal将识别出这是一个vxlan包，将包拆开之后转给节点上的flannel.1设备。这样数据包就从发送节点到达目的节点，flannel.1设备将接收到一个如下的数据包：        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201106095633498-1899135220.png"&gt;&lt;/img&gt;        &lt;br /&gt;目的地址为192.20.1.43，flannel.1查找自己的路由表，根据路由表完成转发。        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201106095702415-614756095.png"&gt;&lt;/img&gt;        &lt;br /&gt;根据最长匹配原则，flannel.1将去往192.20.1.0/24的流量转发到cni0上去。        &lt;br /&gt;5.cni0到pod        &lt;br /&gt;cni0是一个虚拟网桥设备。当cni0拿到数据包之后，通过veth pair，将数据包发送给pod。        &lt;br /&gt;在node节点上通过arp解析可以开出，192.20.1.43的mac地址为 66:57:8e:3d:00:85        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201106102240670-560661424.png"&gt;&lt;/img&gt;        &lt;br /&gt;该地址为pod的网卡eth0的地址        &lt;br /&gt;        &lt;img alt="" src="https://img2020.cnblogs.com/blog/1985817/202011/1985817-20201106102255659-2124811665.png"&gt;&lt;/img&gt;        &lt;br /&gt;在获知目的pod mac地址后，cni0会通过veth pair将数据包发到pod eth0网卡veth pair接口，至此不同node 节点的通信圆满结束。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;      &lt;strong&gt;总结：本文详细介绍了K8s如何通过cni网络插件flannel完成了不同node节点也就是跨主机pod的通信，这部分的知识对于k8s集群来说十分重要，希望可以方便大家的理解，并在今后的使用和运维当中游刃有余。&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61630-k8s-%E7%BD%91%E7%BB%9C-%E5%8E%9F%E7%90%86</guid>
      <pubDate>Fri, 23 Jul 2021 17:03:10 CST</pubDate>
    </item>
    <item>
      <title>工信部发布网络产品安全漏洞管理规定</title>
      <link>https://itindex.net/detail/61607-%E5%B7%A5%E4%BF%A1%E9%83%A8-%E7%BD%91%E7%BB%9C-%E4%BA%A7%E5%93%81%E5%AE%89%E5%85%A8</link>
      <description>工信部发布了《 &lt;a href="https://www.miit.gov.cn/jgsj/waj/wjfb/art/2021/art_96c2d3de7a6f400ea1d8522b7893db7a.html" target="_blank"&gt;网络产品安全漏洞管理规定&lt;/a&gt;》，从 9 月 1 日起开始实施。《规定》旨在规范网络产品安全漏洞发现、报告、修补和发布等行为。 &lt;em&gt;
《规定》第四条：任何组织或者个人不得利用网络产品安全漏洞从事危害网络安全的活动，不得非法收集、出售、发布网络产品安全漏洞信息；明知他人利用网络产品安全漏洞从事危害网络安全的活动的，不得为其提供技术支持、广告推广、支付结算等帮助。第五条：网络产品提供者、网络运营者和网络产品安全漏洞收集平台应当建立健全网络产品安全漏洞信息接收渠道并保持畅通，留存网络产品安全漏洞信息接收日志不少于 6 个月。第七条：工业和信息化部网络安全威胁和漏洞信息共享平台同步向国家网络与信息安全信息通报中心、国家计算机网络应急技术处理协调中心通报相关漏洞信息。鼓励网络产品提供者建立所提供网络产品安全漏洞奖励机制，对发现并通报所提供网络产品安全漏洞的组织或者个人给予奖励。第十条：任何组织或者个人设立的网络产品安全漏洞收集平台，应当向工业和信息化部备案。工业和信息化部及时向公安部、国家互联网信息办公室通报相关漏洞收集平台，并对通过备案的漏洞收集平台予以公布。&lt;/em&gt; &lt;p&gt;  &lt;img height="120" src="https://img.solidot.org//0/446/liiLIZF8Uh6yM.jpg"&gt;&lt;/img&gt;&lt;/p&gt; &lt;div&gt;
  &lt;a href="http://feeds.feedburner.com/~ff/solidot?a=64zkhJ-Rb2w:ujeWeJXE8zk:yIl2AUoC8zA"&gt;   &lt;img border="0" src="http://feeds.feedburner.com/~ff/solidot?d=yIl2AUoC8zA"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;a href="http://feeds.feedburner.com/~ff/solidot?a=64zkhJ-Rb2w:ujeWeJXE8zk:7Q72WNTAKBA"&gt;   &lt;img border="0" src="http://feeds.feedburner.com/~ff/solidot?d=7Q72WNTAKBA"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61607-%E5%B7%A5%E4%BF%A1%E9%83%A8-%E7%BD%91%E7%BB%9C-%E4%BA%A7%E5%93%81%E5%AE%89%E5%85%A8</guid>
      <pubDate>Tue, 13 Jul 2021 19:25:37 CST</pubDate>
    </item>
    <item>
      <title>网信办发布《网络安全审查办法》修订草案</title>
      <link>https://itindex.net/detail/61604-%E7%BD%91%E4%BF%A1%E5%8A%9E-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8-%E5%AE%A1%E6%9F%A5</link>
      <description>&lt;p&gt;　　国家互联网信息办公室发布关于《网络安全审查办法（修订草案征求意见稿）》公开征求意见的通知。《办法》提出，掌握超过100万用户个人信息的运营者赴国外上市，必须向网络安全审查办公室申报网络安全审查。承诺不利用提供产品和服务的便利条件非法获取用户数据、非法控制和操纵用户设备，无正当理由不中断产品供应或必要的技术支持服务等。网络安全审查重点评估采购活动、数据处理活动以及国外上市可能带来的国家安全风险。&lt;/p&gt;

 &lt;p&gt;　　  &lt;strong&gt;网络安全审查办法&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;　　（修订草案征求意见稿）&lt;/p&gt;

 &lt;p&gt;　　第一条 为了确保关键信息基础设施供应链安全，维护国家安全，依据《中华人民共和国国家安全法》《中华人民共和国网络安全法》《中华人民共和国数据安全法》，制定本办法。&lt;/p&gt;

 &lt;p&gt;　　第二条 关键信息基础设施运营者（以下简称运营者）采购网络产品和服务，数据处理者（以下称运营者）开展数据处理活动，影响或可能影响国家安全的，应当按照本办法进行网络安全审查。&lt;/p&gt;

 &lt;p&gt;　　第三条 网络安全审查坚持防范网络安全风险与促进先进技术应用相结合、过程公正透明与知识产权保护相结合、事前审查与持续监管相结合、企业承诺与社会监督相结合，从产品和服务安全性、可能带来的国家安全风险等方面进行审查。&lt;/p&gt;

 &lt;p&gt;　　第四条 在中央网络安全和信息化委员会领导下，国家互联网信息办公室会同中华人民共和国国家发展和改革委员会、中华人民共和国工业和信息化部、中华人民共和国公安部、中华人民共和国国家安全部、中华人民共和国财政部、中华人民共和国商务部、中国人民银行、国家市场监督管理总局、国家广播电视总局、中国证券监督管理委员会、国家保密局、国家密码管理局建立国家网络安全审查工作机制。&lt;/p&gt;

 &lt;p&gt;　　网络安全审查办公室设在国家互联网信息办公室，负责制定网络安全审查相关制度规范，组织网络安全审查。&lt;/p&gt;

 &lt;p&gt;　　第五条 运营者采购网络产品和服务的，应当预判该产品和服务投入使用后可能带来的国家安全风险。影响或者可能影响国家安全的，应当向网络安全审查办公室申报网络安全审查。&lt;/p&gt;

 &lt;p&gt;　　关键信息基础设施保护工作部门可以制定本行业、本领域预判指南。&lt;/p&gt;

 &lt;p&gt;　　第六条 掌握超过100万用户个人信息的运营者赴国外上市，必须向网络安全审查办公室申报网络安全审查。&lt;/p&gt;

 &lt;p&gt;　　第七条 对于申报网络安全审查的采购活动，运营者应通过采购文件、协议等要求产品和服务提供者配合网络安全审查，包括承诺不利用提供产品和服务的便利条件非法获取用户数据、非法控制和操纵用户设备，无正当理由不中断产品供应或必要的技术支持服务等。&lt;/p&gt;

 &lt;p&gt;　　第八条 运营者申报网络安全审查，应当提交以下材料：&lt;/p&gt;

 &lt;p&gt;　　（一）申报书；&lt;/p&gt;

 &lt;p&gt;　　（二）关于影响或可能影响国家安全的分析报告；&lt;/p&gt;

 &lt;p&gt;　　（三）采购文件、协议、拟签订的合同或拟提交的IPO材料等；&lt;/p&gt;

 &lt;p&gt;　　（四）网络安全审查工作需要的其他材料。&lt;/p&gt;

 &lt;p&gt;　　第九条 网络安全审查办公室应当自收到审查申报材料起，10个工作日内确定是否需要审查并书面通知运营者。&lt;/p&gt;

 &lt;p&gt;　　第十条 网络安全审查重点评估采购活动、数据处理活动以及国外上市可能带来的国家安全风险，主要考虑以下因素：&lt;/p&gt;

 &lt;p&gt;　　（一）产品和服务使用后带来的关键信息基础设施被非法控制、遭受干扰或破坏的风险；&lt;/p&gt;

 &lt;p&gt;　　（二）产品和服务供应中断对关键信息基础设施业务连续性的危害；&lt;/p&gt;

 &lt;p&gt;　　（三）产品和服务的安全性、开放性、透明性、来源的多样性，供应渠道的可靠性以及因为政治、外交、贸易等因素导致供应中断的风险；&lt;/p&gt;

 &lt;p&gt;　　（四）产品和服务提供者遵守中国法律、行政法规、部门规章情况；&lt;/p&gt;

 &lt;p&gt;　　（五）核心数据、重要数据或大量个人信息被窃取、泄露、毁损以及非法利用或出境的风险；&lt;/p&gt;

 &lt;p&gt;　　（六）国外上市后关键信息基础设施，核心数据、重要数据或大量个人信息被国外政府影响、控制、恶意利用的风险；&lt;/p&gt;

 &lt;p&gt;　　（七）其他可能危害关键信息基础设施安全和国家数据安全的因素。&lt;/p&gt;

 &lt;p&gt;　　第十一条 网络安全审查办公室认为需要开展网络安全审查的，应当自向运营者发出书面通知之日起30个工作日内完成初步审查，包括形成审查结论建议和将审查结论建议发送网络安全审查工作机制成员单位、相关关键信息基础设施保护工作部门征求意见；情况复杂的，可以延长15个工作日。&lt;/p&gt;

 &lt;p&gt;　　第十二条 网络安全审查工作机制成员单位和相关关键信息基础设施保护工作部门应当自收到审查结论建议之日起15个工作日内书面回复意见。&lt;/p&gt;

 &lt;p&gt;　　网络安全审查工作机制成员单位、相关关键信息基础设施保护工作部门意见一致的，网络安全审查办公室以书面形式将审查结论通知运营者；意见不一致的，按照特别审查程序处理，并通知运营者。&lt;/p&gt;

 &lt;p&gt;　　第十三条 按照特别审查程序处理的，网络安全审查办公室应当听取相关部门和单位意见，进行深入分析评估，再次形成审查结论建议，并征求网络安全审查工作机制成员单位和相关部门意见，按程序报中央网络安全和信息化委员会批准后，形成审查结论并书面通知运营者。&lt;/p&gt;

 &lt;p&gt;　　第十四条 特别审查程序一般应当在3个月内完成，情况复杂的可以延长。&lt;/p&gt;

 &lt;p&gt;　　第十五条 网络安全审查办公室要求提供补充材料的，运营者、产品和服务提供者应当予以配合。提交补充材料的时间不计入审查时间。&lt;/p&gt;

 &lt;p&gt;　　第十六条 网络安全审查工作机制成员单位认为影响或可能影响国家安全的网络产品和服务、数据处理活动以及国外上市行为，由网络安全审查办公室按程序报中央网络安全和信息化委员会批准后，依照本办法的规定进行审查。&lt;/p&gt;

 &lt;p&gt;　　第十七条 参与网络安全审查的相关机构和人员应严格保护企业商业秘密和知识产权，对运营者、产品和服务提供者提交的未公开材料，以及审查工作中获悉的其他未公开信息承担保密义务；未经信息提供方同意，不得向无关方披露或用于审查以外的目的。&lt;/p&gt;

 &lt;p&gt;　　第十八条 运营者或网络产品和服务提供者认为审查人员有失客观公正，或未能对审查工作中获悉的信息承担保密义务的，可以向网络安全审查办公室或者有关部门举报。&lt;/p&gt;

 &lt;p&gt;　　第十九条 运营者应当督促产品和服务提供者履行网络安全审查中作出的承诺。&lt;/p&gt;

 &lt;p&gt;　　网络安全审查办公室通过接受举报等形式加强事前事中事后监督。&lt;/p&gt;

 &lt;p&gt;　　第二十条 运营者违反本办法规定的，依照《中华人民共和国网络安全法》《中华人民共和国数据安全法》的规定处理。&lt;/p&gt;

 &lt;p&gt;　　第二十一条 本办法中关键信息基础设施运营者是指经关键信息基础设施保护工作部门认定的运营者。&lt;/p&gt;

 &lt;p&gt;　　本办法所称网络产品和服务主要指核心网络设备、重要通信产品、高性能计算机和服务器、大容量存储设备、大型数据库和应用软件、网络安全设备、云计算服务，以及其他对关键信息基础设施安全有重要影响的网络产品和服务。&lt;/p&gt;

 &lt;p&gt;　　第二十二条 涉及国家秘密信息的，依照国家有关保密规定执行。&lt;/p&gt;

 &lt;p&gt;　　第二十三条 本办法自2021年 月 日起实施，《网络产品和服务安全审查办法（试行）》同时废止。&lt;/p&gt;

 &lt;p&gt;　　来源：“网信中国”微信公众号&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>业界动态</category>
      <guid isPermaLink="true">https://itindex.net/detail/61604-%E7%BD%91%E4%BF%A1%E5%8A%9E-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8-%E5%AE%A1%E6%9F%A5</guid>
      <pubDate>Sun, 11 Jul 2021 00:15:34 CST</pubDate>
    </item>
    <item>
      <title>K8s网络插件flannel与calico - 小雨淅淅o0 - 博客园</title>
      <link>https://itindex.net/detail/61547-k8s-%E7%BD%91%E7%BB%9C-%E6%8F%92%E4%BB%B6</link>
      <description>&lt;div&gt;    &lt;p&gt;       &lt;strong&gt;Kubernetes的网络通信问题:&lt;/strong&gt;      &lt;br /&gt;　　1. 容器间通信： 即同一个Pod内多个容器间通信，通常使用loopback来实现。      &lt;br /&gt;　　2. Pod间通信： K8s要求,Pod和Pod之间通信必须使用Pod-IP 直接访问另一个Pod-IP      &lt;br /&gt;　　3. Pod与Service通信： 即PodIP去访问ClusterIP，当然，clusterIP实际上是IPVS 或 iptables规则的虚拟IP，是没有TCP/IP协议栈支持的。但不影响Pod访问它.      &lt;br /&gt;　　4. Service与集群外部Client的通信，即K8s中Pod提供的服务必须能被互联网上的用户所访问到。      &lt;br /&gt;      &lt;br /&gt;需要注意的是，k8s集群初始化时的service网段，pod网段，网络插件的网段，以及真实服务器的网段，都不能相同，如果相同就会出各种各样奇怪的问题，而且这些问题在集群做好之后是不方便改的，改会导致更多的问题，所以，就在搭建前将其规划好。      &lt;br /&gt;      &lt;br /&gt;CNI(容器网络接口)：      &lt;br /&gt;　　这是K8s中提供的一种通用网络标准规范，因为k8s本身不提供网络解决方案。      &lt;br /&gt;　　目前比较知名的网络解决方案有:      &lt;br /&gt;　　　　flannel      &lt;br /&gt;　　　　calico      &lt;br /&gt;　　　　canel      &lt;br /&gt;　　　　kube-router      &lt;br /&gt;　　　　.......      &lt;br /&gt;等等，目前比较常用的时flannel和calico，flannel的功能比较简单，不具备复杂网络的配置能力，calico是比较出色的网络管理插件，单具备复杂网络配置能力的同时，往往意味着本身的配置比较复杂，所以相对而言，比较小而简单的集群使用flannel，考虑到日后扩容，未来网络可能需要加入更多设备，配置更多策略，则使用calico更好      &lt;br /&gt;所有的网络解决方案，它们的共通性：      &lt;br /&gt;　　1. 虚拟网桥      &lt;br /&gt;　　2. 多路复用：MacVLAN      &lt;br /&gt;　　3. 硬件交换：SR-IOV（单根-I/O虚拟网络）：它是一种物理网卡的硬件虚拟化技术，它通过输出VF(虚拟功能)来将网卡虚拟为多个虚拟子接口，每个VF绑定给一个VM后，该VM就可以直接操纵该物理网卡。      &lt;br /&gt;      &lt;br /&gt;kubelet来调CNI插件时，会到 /etc/cni/net.d/目录下去找插件的配置文件，并读取它，来加载该插件,并让该网络插件来为Pod提供网络服务。      &lt;br /&gt;      &lt;br /&gt;flannel网络插件要怎么部署？      &lt;br /&gt;　1. flannel部署到那个节点上？      &lt;br /&gt;　　因为kubelet是用来管理Pod的，而Pod运行需要网络，因此凡是部署kubelet的节点，都需要部署flannel来提供网络，因为kubelet正是通过调用flannel来实现为Pod配置网络的(如:添加网络，配置网络，激活网络等)。      &lt;br /&gt;      &lt;br /&gt;　2. flannel自身要如何部署？      &lt;br /&gt;　　1》它支持直接运行为宿主机上的一个守护进程。      &lt;br /&gt;　　2》它也支持运行为一个Pod      &lt;br /&gt;　　对于运行为一个Pod这种方式：就必须将flannel配置为共享当前宿主机的网络名称空间的Pod，若flannel作为控制器控制的Pod来运行的话，它的控制器必须是DaemonSet，在每一个节点上都控制它仅能运行一个Pod副本，而且该副本必须直接共享宿主机的网络名称空间，因为只有这样，此Pod才能设置宿主机的网络名称空间，因为flannel要在当前宿主机的网络名称空间中创建CNI虚拟接口，还要将其他Pod的另一半veth桥接到虚拟网桥上，若不共享宿主机的网络名称空间，这是没法做到的。      &lt;br /&gt;      &lt;br /&gt;3. flannel的工作方式有3种:      &lt;br /&gt;　　1) VxLAN:      &lt;br /&gt;　　　而VxLAN有两种工作方式:      &lt;br /&gt;　　　　a.  VxLAN:　这是原生的VxLAN，即直接封装VxLAN首部，UDP首部，IP，MAC首部这种的。      &lt;br /&gt;　　　　b.  DirectRouting: 这种是混合自适应的方式, 即它会自动判断，若当前是相同二层网络      &lt;br /&gt;　　　　   (即：不垮路由器,二层广播可直达)，则直接使用Host-GW方式工作，若发现目标是需要跨网段      &lt;br /&gt;　　　　   (即：跨路由器)则自动转变为使用VxLAN的方式。      &lt;br /&gt;　　2)  host-GW:  这种方式是宿主机内Pod通过虚拟网桥互联，然后将宿主机的物理网卡作为网关，当需要访问其它Node上的Pod时，只需要将报文发给宿主机的物理网卡，由宿主机通过查询本地路由表，来做路由转发，实现跨主机的Pod通信，这种模式带来的问题时，当k8s集群非常大时，会导致宿主机上的路由表变得非常巨大，而且这种方式，要求所有Node必须在同一个二层网络中，否则将无法转发路由，这也很容易理解，因为如果Node之间是跨路由的，那中间的路由器就必须知道Pod网络的存在，它才能实现路由转发，但实际上，宿主机是无法将Pod网络通告给中间的路由器，因此它也就无法转发理由。      &lt;br /&gt;　　3) UDP: 这种方式性能最差的方式，这源于早期flannel刚出现时，Linux内核还不支持VxLAN，即没有VxLAN核心模块，因此flannel采用了这种方式，来实现隧道封装，其效率可想而知，因此也给很多人一种印象，flannel的性能很差，其实说的是这种工作模式，若flannel工作在host-GW模式下，其效率是非常高的，因为几乎没有网络开销。      &lt;br /&gt;      &lt;br /&gt;4. flannel的网络配置参数：      &lt;br /&gt;　　1) Network: flannel使用的CIDR格式的网络地址，主要用于为Pod配置网络功能。      &lt;br /&gt;　　　如:  10.10.0.0/16  ---&amp;gt;      &lt;br /&gt;　　　　master:  10.10.0.0/24      &lt;br /&gt;　　　　node01: 10.10.1.0/24      &lt;br /&gt;　　　　.....      &lt;br /&gt;　　　　node255: 10.10.255.0/24      &lt;br /&gt;      &lt;br /&gt;　　2) SubnetLen: 把Network切分为子网供各节点使用时，使用多长的掩码来切分子网，默认是24位.      &lt;br /&gt;　　3) SubnetMin: 若需要预留一部分IP时，可设置最小从那里开始分配IP，如：10.10.0.10/24 ，这样就预留出了10个IP      &lt;br /&gt;　　4) SubnetMax: 这是控制最多分配多个IP，如: 10.10.0.100/24  这样在给Pod分配IP时，最大分配到10.10.0.100了。      &lt;br /&gt;　　5) Backend: 指定后端使用的协议类型，就是上面提到的：vxlan( 原始vxlan，directrouter)，host-gw, udp&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;flannel的配置：&lt;/strong&gt;      &lt;br /&gt;　　.....      &lt;br /&gt;　　net-conf.json: |      &lt;br /&gt;　　　　{      &lt;br /&gt;　　　　　&amp;quot;Network&amp;quot;:  &amp;quot;10.10.0.0/16&amp;quot;,      &lt;br /&gt;　　　　　&amp;quot;Backend&amp;quot;:  {      &lt;br /&gt;　　　　　&amp;quot;Type&amp;quot;:   &amp;quot;vxlan&amp;quot;, 　　            #当然，若你很确定自己的集群以后也不可能跨网段，你完全可以直接设置为 host-gw.      &lt;br /&gt;　　　　　&amp;quot;Directrouting&amp;quot;:  true  #默认是false，修改为true就是可以让VxLAN自适应是使用VxLAN还是使用host-gw了。      &lt;br /&gt;　　　　　}      &lt;br /&gt;　　　　}      &lt;br /&gt;      &lt;br /&gt;#在配置flannel时，一定要注意，不要在半道上，去修改，也就是说要在你部署k8s集群后，就直接规划好，而不要在k8s集群已经运行起来了，你再去修改，虽然可能也不会出问题，但一旦出问题，你就！！&lt;/p&gt;    &lt;p&gt;　　      &lt;img alt="" src="https://img2018.cnblogs.com/blog/922925/201908/922925-20190802172545350-1788912835.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;  #在配置好，flannel后，一定要测试，创建新Pod，看看新Pod是否能从flannel哪里获得IP地址，是否能通信。&lt;/p&gt;    &lt;p&gt; &lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Calico：&lt;/strong&gt;      &lt;br /&gt;　　Calico是一种非常复杂的网络组件，它需要自己的etcd数据库集群来存储自己通过BGP协议获取的路由等各种所需要持久保存的网络数据信息，因此在部署Calico时，早期是需要单独为Calico部署etcd集群的，因为在k8s中，访问etcd集群只有APIServer可以对etcd进行读写，其它所有组件都必须通过APIServer作为入口，将请求发给APIServer，由APIServer来从etcd获取必要信息来返回给请求者，但Caclico需要自己写，因此就有两种部署Calico网络插件的方式，一种是部署两套etcd，另一种就是Calico不直接写，而是通过APIServer做为代理，来存储自己需要存储的数据。通常第二种使用的较多，这样可降低系统复杂度。      &lt;br /&gt;　　当然由于Calico本身很复杂，但由于很多k8s系统可能存在的问题是，早期由于各种原因使用了flannel来作为网络插件，但后期发现需要使用网络策略的需求，怎么办？      &lt;br /&gt;　　目前比较成熟的解决方案是：flannel + Calico, 即使用flannel来提供简单的网络管理功能，而使用Calico提供的网络策略功能。      &lt;br /&gt;      &lt;br /&gt;      &lt;br /&gt;Calico网络策略：&lt;/p&gt;    &lt;p&gt;　　      &lt;img alt="" src="https://img2018.cnblogs.com/blog/922925/201908/922925-20190802174641622-981307379.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;  Egress：是出站的流量，即自己是源，远端为服务端，因此我自己的源IP可确定，但端口不可预知， 目标的端口和IP都是确定的，因此to 和 ports都是指目标的IP和端口。      &lt;br /&gt;  Ingress：是入站的流量，即自己为目标，而远端是客户端，因此要做控制，就只能对自己的端口 和 客户端的地址 做控制。      &lt;br /&gt;我们通过Ingress 和 Egress定义的网络策略是对一个Pod生效 还是 对一组Pod生效？      &lt;br /&gt;这个就要通过podSelector来实现了。      &lt;br /&gt;而且在定义网络策略时，可以很灵活，如：入站都拒绝，仅允许出站的； 或 仅允许指定入站的，出站都允许等等。      &lt;br /&gt;另外，在定义网络策略时，也可定义 在同一名称空间中的Pod都可以自由通信，但跨名称空间就都拒绝。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;网络策略的生效顺序：&lt;/strong&gt;      &lt;br /&gt;　　越具体的规则越靠前，越靠前，越优先匹配&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;网络策略的定义：&lt;/strong&gt;      &lt;br /&gt;　　kubectl  explain  networkpolicy      &lt;br /&gt;　　spec:      &lt;br /&gt;　　　egress:  &amp;lt;[]Object&amp;gt;  :定义出站规则      &lt;br /&gt;　　　ingress: &amp;lt;[]Object&amp;gt;: 定义入站规则      &lt;br /&gt;　　　podSelector： 如论是入站还是出站，这些规则要应用到那些Pod上。      &lt;br /&gt;　　　policyType：[Ingress|Egress| Ingress,Egress]   :      &lt;br /&gt;　　　  它用于定义若同时定义了egress和ingress，到底那个生效？若仅给了ingress，则仅ingress生效，若设置为Ingress,Egress则两个都生效。      &lt;br /&gt;　　      注意：policyType在使用时,若不指定，则当前你定义了egress就egress生效，若egress,ingress都定义了,则两个都生效！！      &lt;br /&gt;　　　　还有，若你定义了egress， 但policyType: ingress, egress  ； egress定义了，但ingress没有定义,这种要会怎样？      &lt;br /&gt;　　　　其实，这时ingress的默认规则会生效，即：若ingress的默认规则为拒绝，则会拒绝所有入站请求，若为允许，则会允许所有入站请求，      &lt;br /&gt;　　　　所以，若你只想定义egress规则，就明确写egress ！！      &lt;br /&gt;      &lt;br /&gt;　　egress：&amp;lt;[]Object&amp;gt;      &lt;br /&gt;　　    ports: &amp;lt;[]Object&amp;gt;  :因为ports是有端口号 和 协议类型的，因此它也是对象列表      &lt;br /&gt;　　    　port :      &lt;br /&gt;　　　　protocol: 这两个就是用来定义目标端口和协议的。      &lt;br /&gt;　　　to :&amp;lt;[]Object&amp;gt;      &lt;br /&gt;　　　    podSelector: &amp;lt;Object&amp;gt; : 在控制Pod通信时，可控制源和目标都是一组Pod，然后控制这两组Pod之间的访问。      &lt;br /&gt;　　　   ipBlock：&amp;lt;[]Object&amp;gt; : 指定一个Ip地址块，只要在这个IP范围内的，都受到策略的控制，而不区分是Pod还是Service。      &lt;br /&gt;　　　   namespaceSelector： 这是控制对指定名称空间内的全部Pod 或 部分Pod做访问控制。      &lt;br /&gt;      &lt;br /&gt;　　Ingress：      &lt;br /&gt;　　    from： 这个from指访问者访问的IP      &lt;br /&gt;　　    ports:  也是访问者访问的Port&lt;/p&gt;    &lt;div&gt;      &lt;div&gt;        &lt;a title=""&gt;          &lt;img alt="&amp;#22797;&amp;#21046;&amp;#20195;&amp;#30721;" src="https://common.cnblogs.com/images/copycode.gif"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/div&gt;      &lt;pre&gt;#定义网络策略：
vim   networkpolicy-demo.yaml
apiVersion:  networking.k8s.io/v1  
    #注意：虽然kubectl  explain networkpolicy中显示为 extensions/v1beta1 ，但你要注意看说明部分.
kind:  NetworkPolicy
metadata:
     name:  deny-all-ingressnamespace:  dev
spec:
     podSelector:  {}  #这里写空的含义是，选择指定名称空间中所有Pod
     policyTypes:-Ingress        #这里指定要控制Ingress(进来的流量)，但又没有指定规则，就表示全部拒绝，只有明确定义的,才是允许的。
                       #egress: 出去的流量不控制，其默认规则就是允许，因为不关心，所以爱咋咋地的意思。
    
#写一个简单的自主式Pod的定义:
vim  pod1.yaml
    apiVersion:  v1
    kind: Pod
    metadata: 
      name:  pod1
    spec:
      containers:-name:  myapp
        image:  harbor.zcf.com/k8s/myapp:v1

#创建dev名称空间，并应用规则
kubectl apply-f networkpolicy-demo.yaml -n dev

# kubectl describe-n dev networkpolicies
    Name:         deny-all-ingress
    Namespace:    dev
   ........................
    Spec:
      PodSelector:&amp;lt;none&amp;gt; (Allowing the specific traffic to all podsinthisnamespace)
      Allowing ingress traffic:&amp;lt;none&amp;gt; (Selected pods are isolatedforingress connectivity)
      Allowing egress traffic:&amp;lt;none&amp;gt; (Selected pods are isolatedforegress connectivity)


#查看dev名称空间中的网络规则:
kubectlgetnetworkpolicy -n dev     
 或   
 kubectlgetnetpol  -n  dev

#然后在dev 和 prod 两个名称空间中分别创建pod
kubectl  apply-f  pod1.yaml   -n   dev
kubectl  apply-f  pod1.yaml   -n   prod

#接着测试访问这两个名称空间中的pod
kubectlgetpod  -n  dev   -o   wide
    
    #测试访问:
        curl   http://POD_IPkubectlgetpod  -n  prod   -o   wide

    #测试访问:
        curl   http://POD_IP#通过以上测试，可以看到，dev名称空间中的pod无法被访问，而prod名称空间中的pod则可被访问。&lt;/pre&gt;      &lt;div&gt;        &lt;a title=""&gt;          &lt;img alt="&amp;#22797;&amp;#21046;&amp;#20195;&amp;#30721;" src="https://common.cnblogs.com/images/copycode.gif"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;    &lt;div&gt;      &lt;div&gt;        &lt;a title=""&gt;          &lt;img alt="&amp;#22797;&amp;#21046;&amp;#20195;&amp;#30721;" src="https://common.cnblogs.com/images/copycode.gif"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/div&gt;      &lt;pre&gt;#测试放行所有dev的ingress入站请求。
# vim  networkpolicy-demo.yaml
    apiVersion:  networking.k8s.io/v1   
    kind:  NetworkPolicy
    metadata:
       name: allow-all-ingressnamespace:  dev
    spec:
       podSelector:  {}
       ingress:-{}      #这就表示允许所有，因为定义了规则，但规则是空的，即允许所有。
       policyTypes:-Ingress

#接着测试，和上面测试一样，也是访问dev 和 prod两个名称空间中的pod，若能访问，则成功。
# kubectl describe-n dev netpol
    Name:         deny-all-ingress
    Namespace:    dev
    .....................
    Spec:
      PodSelector:&amp;lt;none&amp;gt; (Allowing the specific traffic to all podsinthisnamespace)
      Allowing ingress traffic:
        To Port:&amp;lt;any&amp;gt;(traffic allowed to all ports)
        From:&amp;lt;any&amp;gt;(traffic not restricted by source)
      Allowing egress traffic:&amp;lt;none&amp;gt; (Selected pods are isolatedforegress connectivity)
      Policy Types: Ingress&lt;/pre&gt;      &lt;div&gt;        &lt;a title=""&gt;          &lt;img alt="&amp;#22797;&amp;#21046;&amp;#20195;&amp;#30721;" src="https://common.cnblogs.com/images/copycode.gif"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;    &lt;p&gt;  #测试定义一个仅允许访问dev名称空间中，pod标签 app=myapp 的一组pod的80端口&lt;/p&gt;    &lt;p&gt;　　      &lt;img alt="" src="https://img2018.cnblogs.com/blog/922925/201908/922925-20190802175542541-907033446.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;div&gt;      &lt;div&gt;        &lt;a title=""&gt;          &lt;img alt="&amp;#22797;&amp;#21046;&amp;#20195;&amp;#30721;" src="https://common.cnblogs.com/images/copycode.gif"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/div&gt;      &lt;pre&gt;#先给pod1打上app=myapp的标签
#kubectl label pod pod1 app=myapp -n dev
    
vim  allow-dev-80.yaml
 apiVersion: networking.k8s.io/v1
 kind: NetworkPolicy
 metadata:
    name: allow-myapp-ingress
 spec:
   podSelector:
      matchLabels:
        app: myapp
     ingress:-from:-ipBlock:
            cidr:10.10.0.0/16except:-10.10.1.2/32ports:-protocol:  TCP
         port:88-protocol:  TCP
         port:443#查看定义的ingress规则
kubectlgetnetpol  -n  dev

#然后测试访问 dev 名称空间中的pod
curl  http://Pod_IPcurl  http://Pod_IP:443curl   http://Pod_IP:88&lt;/pre&gt;      &lt;div&gt;        &lt;a title=""&gt;          &lt;img alt="&amp;#22797;&amp;#21046;&amp;#20195;&amp;#30721;" src="https://common.cnblogs.com/images/copycode.gif"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/922925/201908/922925-20190802175810651-579552423.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2018.cnblogs.com/blog/922925/201908/922925-20190802175826689-478710017.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;div&gt;      &lt;div&gt;        &lt;a title=""&gt;          &lt;img alt="&amp;#22797;&amp;#21046;&amp;#20195;&amp;#30721;" src="https://common.cnblogs.com/images/copycode.gif"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/div&gt;      &lt;pre&gt;上图测试：1. 先给dev名称空间打上标签
  kubectl   labelnamespacedev   ns=dev2. 编写网络策略配置清单
  vim  allow-ns-dev.yaml
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-ns-dev
    spec:
      podSelector: {}
      ingress:-from:-namespaceSelector:
              matchLabels:
                ns: dev
      egress:-to:-namespaceSelector:
             matchLabels:
               ns: dev



#要控制egress，也是如此，只是将ingress替换为egress即可，然后在做测试。
另外，关于网络策略，建议：
 名称空间内：
     拒绝所有出站，入站流量
     仅放行出站目标为当前名称空间内各Pod间通信，因为网络策略控制的颗粒度是Pod级别的，不是名称空间级别。
     具体的网络策略，要根据实际需求，来定义ingress 和 egress规则。&lt;/pre&gt;      &lt;div&gt;        &lt;a title=""&gt;          &lt;img alt="&amp;#22797;&amp;#21046;&amp;#20195;&amp;#30721;" src="https://common.cnblogs.com/images/copycode.gif"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;    &lt;p&gt; &lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61547-k8s-%E7%BD%91%E7%BB%9C-%E6%8F%92%E4%BB%B6</guid>
      <pubDate>Fri, 18 Jun 2021 17:13:32 CST</pubDate>
    </item>
    <item>
      <title>TCP之网络优化</title>
      <link>https://itindex.net/detail/61530-tcp-%E7%BD%91%E7%BB%9C-%E4%BC%98%E5%8C%96</link>
      <description>&lt;div&gt;  &lt;p&gt;   &lt;a href="https://juejin.cn/post/6971710168413241375" target="_blank"&gt;上一篇文章我提到了Nagle算法&lt;/a&gt;，是为了解决报头大数据小从而导致网络利用率低的问题，这其实会带来新的问题。除此之外我们一起来看看tcp还会有什么优化策略呢！本文纯属学习记录，不完善或错误之处若指正将不胜感激。如有被误导的朋友，望海涵。&lt;/p&gt;
  &lt;hr&gt;&lt;/hr&gt;
  &lt;p&gt;首先我们先康康Nagle算法&lt;/p&gt;
  &lt;h3&gt;Nagle算法规则&lt;/h3&gt;
  &lt;ul&gt;
   &lt;li&gt;（1）如果包长度达到MSS，则允许发送；&lt;/li&gt;
   &lt;li&gt;（2）如果该包含有FIN，则允许发送；&lt;/li&gt;
   &lt;li&gt;（3）设置了TCP_NODELAY选项，则允许发送；&lt;/li&gt;
   &lt;li&gt;（4）未设置TCP_CORK选项时，若所有发出去的小数据包（包长度小于MSS）均被确认，则允许发送；&lt;/li&gt;
   &lt;li&gt;（5）上述条件都未满足，但发生了超时（一般为200ms），则立即发送。&lt;/li&gt;
&lt;/ul&gt;
  &lt;h3&gt;延迟ACK&lt;/h3&gt;
  &lt;p&gt;ACK机制中，在接收方收到一个包之后会先检查是否需要立即回应ACK，否则进入延迟ACK逻辑。   &lt;a href="https://blog.csdn.net/sinat_20184565/article/details/90181191" rel="nofollow noopener noreferrer" target="_blank"&gt;参考&lt;/a&gt;，   &lt;br /&gt;
优点显而易见，提高了网络信道的利用率&lt;/p&gt;
  &lt;h3&gt;当Nagle遇见延迟ACK&lt;/h3&gt;
  &lt;p&gt;假想一个场景  MSS为8个中文字（最大报文长度）   &lt;br /&gt;
甲需要发送两个应用层报文给乙——“你好”！“我是甲”。显然这两个报文都是不足8的，但是由于“你好”满足Nagel的第4条规则所以会第一时间发送出去，由于ACK延迟，甲迟迟收不到乙的确认。于是等到超时发送。   &lt;br /&gt;
这会产生一个明显的延迟   &lt;br /&gt;
   &lt;strong&gt;解决&lt;/strong&gt;&lt;/p&gt;
  &lt;ul&gt;
   &lt;li&gt;关闭Nagle算法，使用TCP套接字选项TCP_NODELAY可以关闭套接字选项（不推荐，有更多的优化策略）&lt;/li&gt;
   &lt;li&gt;使用writev，而不是两次调用write，单个writev调用会使tcp输出一次而不是两次，只产生一个tcp分节，这是首选方法&lt;/li&gt;
&lt;/ul&gt;
  &lt;h3&gt;流量控制之滑动窗口&lt;/h3&gt;
  &lt;p&gt;滑动窗口是为了平衡发送方和接收方速率不匹配，发送窗口在连接建立时由双方商定。但在通信的过程中，一般由接收方反馈本身的缓冲区大小从而动态调节发送窗口（缓冲区）大小&lt;/p&gt;
  &lt;h3&gt;拥塞控制&lt;/h3&gt;
  &lt;p&gt;为了方便，我们假设主机A给主机B传输数据   &lt;br /&gt;
我们知道，两台主机在传输数据包的时候，如果发送方迟迟没有收到接收方反馈的ACK，那么发送方就会认为它发送的数据包丢失了，进而会重新传输这个丢失的数据包。
然而实际情况有可能此时有太多主机正在使用信道资源，导致网络拥塞了，而A发送的数据包被堵在了半路，迟迟没有到达B。这个时候A误认为是发生了丢包情况，会重新传输这个数据包。   &lt;br /&gt;
结果就是不仅浪费了信道资源，还会使网络更加拥塞。因此，我们需要进行拥塞控制&lt;/p&gt;
  &lt;h4&gt;慢开始和拥塞避免&lt;/h4&gt;
  &lt;ul&gt;
   &lt;li&gt;在建立连接之后是如何确定拥塞窗口的大小？(拥塞窗口和滑动窗口注意区别)
    &lt;ul&gt;
     &lt;li&gt;第一种策略，第一次发送一个包，如果没有丢失就+1，以此类推&lt;/li&gt;
     &lt;li&gt;第二种策略，第一次发送一个包，如果没有丢失就乘以2，以此类推&lt;/li&gt;
&lt;/ul&gt;
实际上第一种方式增长过于缓慢，难以快速适应网络拥塞情况，而第二种方式指数型增长，很容易到达拥塞阈值。    &lt;br /&gt;
所以二者取其长，在前期使用指数增长，当到达某一个数值之后进行线性增长    &lt;br /&gt;
但是无论是指数增长还是线性增长最终都会到达一个MAX值，此时会重新以1开始启动并把阈值设置为MAX/2    &lt;br /&gt;
我们把确定拥塞窗口大小的过程中指数增长阶段称之为    &lt;strong&gt;慢开始&lt;/strong&gt;，线性增长阶段称之为    &lt;strong&gt;拥塞避免&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
  &lt;h4&gt;快速重传与快速恢复&lt;/h4&gt;
  &lt;p&gt;前面说过了，当出现网络拥塞时会重启慢开始过程&lt;/p&gt;
  &lt;ul&gt;
   &lt;li&gt;怎么判断网络拥塞？
    &lt;ul&gt;
     &lt;li&gt;当网络拥塞时，会出现大量的丢包&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
   &lt;li&gt;超时重发（丢包）一定是网络拥塞吗？
    &lt;ul&gt;
     &lt;li&gt;网络拥塞会导致大量的包触发超时重发事件。而当一个单独的包出现损坏或者丢包时，也会导致超时重发，所以超时重发不一定是网络拥塞&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
   &lt;li&gt;如何判断超时重发的原因
    &lt;ul&gt;
     &lt;li&gt;网络拥塞会导致大量的丢包&lt;/li&gt;
     &lt;li&gt;单个的丢包，由于延迟ACK规则，后序到达的每到达一个包，接收端都会回复相同的ACK。故当发送方接收到三个相同的ACK时，表明发生了单个的丢包&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
  &lt;p&gt;单个丢包事件，当发送方接收到三个相同的ACK时，此时发送方不必等待序号为ACK-1包的超时，会立即重发。并把当前的阈值设置为MAX，新的阈值为MAX/2，以 拥塞窗口 = MAX/2 进行增长   &lt;br /&gt;
重发阶段我们称之为   &lt;strong&gt;快速重传&lt;/strong&gt; ，窗口参数的调整阶段称之为   &lt;strong&gt;快速恢复&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61530-tcp-%E7%BD%91%E7%BB%9C-%E4%BC%98%E5%8C%96</guid>
      <pubDate>Thu, 10 Jun 2021 08:12:49 CST</pubDate>
    </item>
  </channel>
</rss>

