本周在协助验证一套虚拟网络的方案,该方案包含一个bridge,向上对接容器的veth,并接管真实NIC作为tx口,方案中需要在bridge中做SNAT,具体hook点位于POST_ROUTING,命令如下:iptables -t nat -A POSTROUTING -d 192.168.0.0/24 -j SNAT --to-source 192.168.0.5

为了验证该方案,我创建了一对veth,其中一端划分到独立的netns中,命令如下:ip link add br-veth type veth peer name veth

ip link set br-veth up

ip link set veth up

brctl addif br0 br-veth

ip netns add test-zone

ip link set veth netns test-zone

ip netns exec test-zone ip addr add 192.168.0.100/24 dev veth

为了避免方案过于复杂,规避gw带来的影响,这里假设对端和本端在同一子网,在test-zone中ping对端,我发现对端抓包看到的源IP并未变为192.168.0.5,换句话说SNAT未生效。

在veth的tx方向,这里仅需做二层转发即可,阅读bridge的源码可以发现如下路径(kernel 3.10/4.9无显著区别):br_forward -> BR_FORWARD -> br_nf_forward -> BR_POST_FORWARD -> br_nf_post_routing -> INET_POST_ROUTING

然而挂载POST_ROUTING的SNAT竟然未生效,真的令人匪夷所思。一番google之后,发现需要enable一个标志:echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables

纵观bridge实现,该sysctl的值最终设置到了变量nf_call_iptables,而该变量仅在br_nf_pre_routing中使用。显然,这是不符合预期的。

惯性思维使然,总认为既然有代表特性是否开启的变量,那么在代码相关的分支处一定会用到该变量,而bridge的实现则正好不是这样。

可以看到,只有开启了nf_call_iptables,才会进入网络层的netfilter hook点:static unsigned int br_nf_pre_routing(void *priv,

struct sk_buff *skb,

const struct nf_hook_state *state)

{

struct nf_bridge_info *nf_bridge;

struct net_bridge_port *p;

struct net_bridge *br;

__u32 len = nf_bridge_encap_header_len(skb);

if (unlikely(!pskb_may_pull(skb, len)))

return NF_DROP;

p = br_port_get_rcu(state->in);

if (p == NULL)

return NF_DROP;

br = p->br;

...

if (!brnf_call_iptables && !br->nf_call_iptables)

return NF_ACCEPT;

...

nf_bridge_put(skb->nf_bridge);

if (!nf_bridge_alloc(skb)) // 注意这里!

return NF_DROP;

...

NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->net, state->sk, skb,

skb->dev, NULL, br_nf_pre_routing_finish);

return NF_STOLEN;

}

很容易忽略标着注释的那一行,而恰是那一行,直接决定了是否进入NF_INET_FORWARD和NF_INET_POST_ROUTING的HOOK点。static unsigned int br_nf_forward_ip(void *priv,

struct sk_buff *skb,

const struct nf_hook_state *state)

{

struct nf_bridge_info *nf_bridge;

struct net_device *parent;

u_int8_t pf;

if (!skb->nf_bridge) // 看这里!

return NF_ACCEPT;

...

NF_HOOK(pf, NF_INET_FORWARD, state->net, NULL, skb,

brnf_get_logical_dev(skb, state->in),

parent, br_nf_forward_finish);

return NF_STOLEN;

}static unsigned int br_nf_post_routing(void *priv,

struct sk_buff *skb,

const struct nf_hook_state *state)

{

struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

struct net_device *realoutdev = bridge_parent(skb->dev);

u_int8_t pf;

if (!nf_bridge || !nf_bridge->physoutdev) // 看这里!

return NF_ACCEPT;

...

NF_HOOK(pf, NF_INET_POST_ROUTING, state->net, state->sk, skb,

NULL, realoutdev,

br_nf_dev_queue_xmit);

return NF_STOLEN;

}

参加工作后,见识了很多相当“野”的解决方案,一言不合就得改kernel,为了避免遇到问题时一脸懵逼,平时还是要多花时间熟悉内部实现!

linux snat mac 桥,关于SNAT在bridge中不生效的问题相关推荐

  1. Python编程软件的安装与使用——Windows、Linux和Mac

    Python版本:3.6.2  操作系统:Windows  作者:SmallWZQ 最近,有读者透露:Python软件如何安装?为什么自己安装的软件会有各种"奇怪"的问题?据此,本 ...

  2. Linux 修改mac 地址方法记录

    Linux 修改MAC 记录: sudo ifconfig eth0 hw ether 70B3D5106F90 转载于:https://www.cnblogs.com/chenfulin5/p/67 ...

  3. 将服务端移植到Linux和MAC OS

    文章目录 1 将服务端移植到Linux和MAC OS 1.1 概述 1.2 服务端代码实现 1 将服务端移植到Linux和MAC OS 1.1 概述 这里我们将服务端移植到Linux和MAC OS,差 ...

  4. 将客户端移植到Linux和MAC OS

    文章目录 1 将客户端移植到Linux和MAC OS 1.1 概述 1.2 客户端移植代码 1 将客户端移植到Linux和MAC OS 1.1 概述 我们这里把将客户端移植到Linux和MAC OS, ...

  5. 【Python】扫盲帖:关于在Windows、Linux和Mac上安装设置Python的问题

    来源|Analytics Vidhya 概述 在Linux.Mac或Windows机器上安装Python时遇到的问题 一步一步安装Python及流行的数据科学工具 1 介绍 在你的机器上安装Pytho ...

  6. [C] 跨平台使用Intrinsic函数范例1——使用SSE、AVX指令集 处理 单精度浮点数组求和(支持vc、gcc,兼容Windows、Linux、Mac)...

    作者:zyl910. 本文面对对SSE等SIMD指令集有一定基础的读者,以单精度浮点数组求和为例演示了如何跨平台使用SSE.AVX指令集.因使用了stdint.zintrin.ccpuid这三个模块, ...

  7. 在Linux以及Mac OS X启用F#

    随着.NET Core的推进,如今我们在Linux和Mac OS X平台上也可以和原先Windows平台之下一样运行F#程序.Microsoft的F#项目经理David Stephens先生在Buil ...

  8. 在Linux和Mac OS X系统上运行.NET

    .NET Core运行时已经看到了实现真正的跨平台的美好前景,它最终出现在Linux和Mac OS X平台上.在上周举办的Microsoft Build大会上,来自微软的项目经理Habib Heyda ...

  9. java怎么安装_Windows、Linux、Mac下安装JDK

    前言 在知乎上看到很多童鞋在学Java的时候,因为安装jdk时没有正确的配置,会遇到很多问题.所以决定今天写一下jdk在Windows.Mac.Linux下都怎么安装. 下载JDK "巧妇难 ...

最新文章

  1. jquery删除数组中的某个元素下标越界_Java数据结构和算法(二)—数组
  2. java spring配置类_spring 配置 Java配置类装配bean
  3. ValueError: No JSON object could be decoded
  4. 很好的关于机器学习入门讲解(深入浅出)
  5. mysql导出成execl
  6. 如何做好信息化和数字化建设,看这一篇就够了--童亚斋
  7. Pentaho BIServer 5.0.1 CE 免登录设置
  8. python遍历文件夹下的所有文件
  9. LightOJ 1071 Baker Vai(记忆化搜索)
  10. 利用多线程爬点dianying回家慢慢看【python爬虫入门进阶】(05)
  11. Vue图表(v-charts, e-charts)入门安装使用
  12. Unity 生成随机房间、洞穴(2D、3D地图)总结
  13. 2022最新SpringBoot2.X仿B站项目part1笔记
  14. 【20220629】【信号处理】(平稳随机信号)自相关函数性质的证明过程
  15. 线性变换和矩阵的详细解释
  16. 如何批量给照片加水印?详细图文教程
  17. 如何在线编辑你的各种文档?
  18. 武汉理工计算机研究生就业去向统计,21考研择校:武汉理工大学就业率和薪酬情况统计!...
  19. 分布式事务解决方案 - SpringCloud Alibaba Seata
  20. ps转手绘课程嘴巴绘制+之前回顾--day05学习笔记

热门文章

  1. 技术点:weekMap和Map的区别
  2. k8s创建用户账号——User Account
  3. UiBot Excel筛选
  4. 服务器虚拟打印机为什么经常打打不,打印机虚拟论文,关于制作PDF打印服务器相关参考文献资料-免费论文范文...
  5. 数字集成电路物理设计学习总结——布图规划和布局
  6. 1dp 等于多少PX
  7. 2016年美国数学建模比赛(MCM/ICM) E题环境科学 Are we heading towards a thirsty planet? 人工精准翻译。...
  8. 帝国cms忘记网站后台登录网址怎么找回?
  9. 在旧时的桃花里,喊疼
  10. 多样性强化学习:不光要赢,还要赢得精彩 | 清华吴翼