GRE/VXLAN 过nat的一些尝试

支持nat-t的tunnel要么是标准的C/S模型,能够从墙内发起建立tunnel隧道,且有保活机制使防火墙上的ct持久生效。要么像IPSec一样,能够在协议层面支持,知道tunnel是经过nat的。

linux gre 和 vxlan 作为常用的tunnel口是无法过nat的,但其性能和复杂度比ssl,ipsec这些能够过nat的tunnel要好很多。

做了些gre/vxlan过nat的测试,做了些记录:


GRE过nat

如果网关设备为ovs,直接通过流表学习到nat过的gre头即可,如果网关设备为linux bridge需要改动内核gre模块,修改量不多。

网关设备为ovs:

1. ovs上的操作

* 创建br0

ovs-vsctl add-br br0

ip link set up dev br0

ip addr add 211.1.1.1/24 dev br0

* 创建gre口

ovs-vsctl add-port br0 gre1 -- set interface gre1 type=gre options:local_ip=192.168.121.177 options:remote_ip=flow options:key=flow

* 创建流表,in_port=1是gre1的端口编号,流表主要用于学习反向nat过的流表。流表需要配置老化时间防止对端不可用后流表残留,这里只是测试没配置。

ovs-ofctl add-flow br0 "priority=1,in_port=1,actions=learn(priority=1,NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[] load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],load:NXM_NX_TUN_IPV4_SRC[]->NXM_NX_TUN_IPV4_DST[],output:NXM_OF_IN_PORT[]),NORMAL"

* 配置arp表项,可以省掉,能够自动学习,工作上组网远比试验复杂,所有节点mac和ip都是分配的,arp也是静态配置的,所以这里用静态配置。

#ip neigh

211.1.1.2 dev br0 lladdr de:22:5f:f3:71:a6 PERMANENT

2. bridge上操作

* 创建bridge

brctl addbr br0

ip link set up dev br0

ip addr add 211.1.1.2/24 dev br0

* 创建gre口,加入bridge

key一定要加上,即使是0

ip link add gretap0 type gretap local 15.1.1.2 remote 192.168.121.177 key 0

brctl addif br0 gretap0

ip link set up dev gretap0

* 配置arp表项

211.1.1.1 dev br0 lladdr f2:f9:24:d1:a1:40 PERMANENT

3. nat 设备上操作

* 配置出口nat

iptables -t nat -A POSTROUTING -i eth0 -o eth1 -j MASQUERADE

* 安装gre的nat支持

modprobe nf_conntrack_pptp

modprobe nf_nat_pptp

modprobe nf_conntrack_proto_gre

modprobe nf_nat_proto_gre

4. 测试

bridge上 ping 211.1.1.1

#ping 211.1.1.1

PING 211.1.1.1 (211.1.1.1) 56(84) bytes of data.

64 bytes from 211.1.1.1: icmp_seq=1 ttl=64 time=1.10 ms

64 bytes from 211.1.1.1: icmp_seq=2 ttl=64 time=0.634 ms

64 bytes from 211.1.1.1: icmp_seq=3 ttl=64 time=0.661 ms


ovs上可以看到学习到一个流表,NXM_NX_TUN_IPV4_DST 是经过nat的nat设备的出口ip地址,而不是bridge上ip地址,这样即使nat过,回程流量的gre头也能正确封装,当然有个前提,nat内部的bridge设备需要做gre的keepalive,定时发些报文到ovs上,使nat设备能够保持连接跟踪表,ovs上能刷新回程流表:

cookie=0x0, duration=2449.653s, table=0, n_packets=635, n_bytes=62230, idle_age=0, hard_age=0, priority=1,dl_dst=de:22:5f:f3:71:a6 actions=load:0->NXM_NX_TUN_ID[],load:0xc0a87945->NXM_NX_TUN_IPV4_DST[],output:6

网关设备为bridge

正在测试中。。。。

二. vxlan过nat

vxlan封装在udp中,但是两端是独立建socket的,而不是c/s模型,需要做些修改支持nat。vxlan在bridge实现较为简单,linux原生的vxlan实现直接使用vxlan接口上配置的dstport作为udp的目的端口号,实际上如果过nat-t,nat内部的设备需要先主动从vxlan上发一些数据包,在nat设备上建立连接跟踪表,nat外部的设备用转换过的src ip和src port作为返向流量的dst ip和dst port,linux的fdb表项学习已基本支持这个功能,唯一需要修改的地方是src port的学习,修改量10行之内就有很好的效果;

     ovs类似,基本原理也是nat外部设备通过入方向的报文学习到出方向的vxlan的封装信息,通过流表的learn功能实现添加流表,同样缺少tun_port的支持,修改量稍大,过了一下ovs的源码,感觉修改量在可控范围内,300行左右的修改;

大概看了一下vxlan的协议栈,感觉可以通过修改vxlan模块达成目的,特别如果在dpdk上实现更简单一点。今天在原生的linux上试了一下,只修改了vxlan.ko 模块不到10行代码,搞定了,效果非常好。

bridge协议栈,每次收到报文的时候都会学习 fdb表项,就是mac---ip地址映射,回来的报文走这个表项封装vxlan报文以及转发,vxlan的表项特殊之处全在下面这个结构里了,有remote_ip,remoteport,remote_vni,内核只根据接收报文对remote_ip做了赋值,其它两个都取的接口上的配置,所以只需要对这两个成员赋下值就ok了,这样即使nat过的ip和port,也能学到fdb表中,回程报文使用这两个值封装vxlan,到了防火墙也能通过。

注意需要在cpe设备上做保活,防止防火墙的连接跟踪表项老化。

struct vxlan_rdst {

union vxlan_addr remote_ip;

__be16 remote_port;

__be32 remote_vni;

u32 remote_ifindex;

struct list_head list;

struct rcu_head rcu;

struct dst_cache dst_cache;

};

vxlan_xmit_one:

。。。。

if (rdst) {

dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;

vni = rdst->remote_vni;

dst = &rdst->remote_ip;

local_ip = vxlan->cfg.saddr;

dst_cache = &rdst->dst_cache;

}

。。。。

udp_tunnel_xmit_skb(rt, sk, skb, local_ip.sin.sin_addr.s_addr,

    dst->sin.sin_addr.s_addr, tos, ttl, df,

    src_port, dst_port, xnet, !udp_sum);

。。。。

修改点:

static bool vxlan_snoop(struct net_device *dev,

union vxlan_addr *src_ip, __be16 src_port, __be32 vni,const u8 *src_mac)  // 增加port和vni赋值

{

struct vxlan_dev *vxlan = netdev_priv(dev);

struct vxlan_fdb *f;

f = vxlan_find_mac(vxlan, src_mac);

if (likely(f)) {

struct vxlan_rdst *rdst = first_remote_rcu(f);

if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip)))

return false;

/* Don't migrate static entries, drop packets */

if (f->state & NUD_NOARP)

return true;

if (net_ratelimit())

netdev_info(dev,

    "%pM migrated from %pIS to %pIS\n",

    src_mac, &rdst->remote_ip, &src_ip);

rdst->remote_ip = *src_ip;

rdst->remote_port = src_port;    // 增加port和vni赋值

rdst->remote_vni = vni;

f->updated = jiffies;

vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH);

} else {

/* learned new entry */

spin_lock(&vxlan->hash_lock);

/* close off race between vxlan_flush and incoming packets */

if (netif_running(dev))

vxlan_fdb_create(vxlan, src_mac, src_ip,

NUD_REACHABLE,

NLM_F_EXCL|NLM_F_CREATE,

//vxlan->dst_port,

//vxlan->default_dst.remote_vni,

src_port, vni,    // 增加port和vni赋值

0, NTF_SELF);

spin_unlock(&vxlan->hash_lock);

}

return false;

}

调用这个函数的地方赋下值即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容