之前我们说了,在一个局域网内打游戏,但是不能真正的上网仍然让人感觉到不爽,于是希望可以真正的上网,而终于有了一个校园网的IP,这个IP是一个更大的局域网内得IP,覆盖了整个校园,而我们宿舍内是更小的网络,校园网的ip假设是10.10.X.X;宿舍网的IP假设是 192.168.1.X

我们如何在宿舍连上校园网进行上网呢?

第一个办法,再买一个网卡,插在宿舍长的电脑上,这样宿舍长的电脑就有两个网卡,一个网卡连宿舍内得交换机,另一个连着是校园网的网口,如果这张新的网卡的IP地址要按照校园网的IP去配置,这种情况下,我们需要一直开着宿舍长的电脑

或者第二种方法,买个路由器,路由器当时会有内网网口和外网网口,将外网网口的线插到校园网口上,然后将这个外网的网口配置和网管部的一样,内网的随便连宿舍的电脑,这种情况下,上网只需要开着路由器就可以了

其实两种方法的内在都是一样的,第一个方法只不过是将路由器的功能换成了宿舍长电脑罢了

在宿舍长能够上网后,就是其他人的电脑怎么上网了,需要配置自己的网卡,当然Ip可以使用DHCP设置,但是除了IP,还需要设置一个Gateway的东西,就是网关

配置完成网关的设置之后,就能够跨网关访问了,但是这其中会涉及到MAC和IP的变化

所以我们需要将MAC和IP的细节详细的说下

图片

mac头里面,先是mac地址,然后是源mac地址,然后有一个协议地址,这里面说明了是IP协议,IP里面有版本号,说明是IPV4.然后服务类型TOS说了,表明权重的,TTL说了,每过一次中转就减一的

然后还有IP层的协议,说明了下一层是TCP还是UDP,最重要的就是源ip和目标ip,先是源ip,后是目标ip

任何一个机器,访问另一个ip的时候,都先判断,这个目标ip地址,和当前的ip地址,是否是一个网段内,这需要用到CIDR和子网掩码,这个第三节讲到了

如果是同一个网段,比如旁边的兄弟的电脑,这就没网关什么事情了,将源地址和目的地址放在IP头内,查找对应的MAC地址,如果找不到,ARP协议吼一嗓子,获取了MAC地址,发送出去

如果不是一个网段,就需要发送到默认的网关上,然后Gateway的往往和源IP地址是一个网段,往往是该网段的第一个或者第二个地址

那么这个发往网关的过程,和发往其他机器的过程一直,就是讲源地址和目标地址放进去,然后获取到MAC地址,然后发送出去,网关怎么做,就是网关的事情了

那么我们就说说网关,其实往往是一个路由器,是一个三层转发的设备,其可以取出MAC层和IP层的数据,然后看里面的内容,要转发到哪里去

在这个场景下,网关就是宿舍长的电脑,一个路由器往往有多个网口,一个服务器做转发的事情,就是会有多个网卡,其中一个网卡和源ip同网段

路由器从本质上来说,是一个设备,有五个网口或者网卡,分别连着5个局域网,每个网口的ip和局域网的ip地址有着相同的网段,每个网口也是对应的局域网的网关

任何一个想要发给别的局域网的包,都会先到一个网口,然后获取到对应的MAC和IP,然后进行计算后,选择别的网口,发送出去

那选择哪一个网口,对于IP头和MAC头怎么处理,这就是一个新的问题,对于这个问题,我们可以分为两类来看其是如何处理的,一类是静态路由,一类是动态路由,我们先说下静态路由

静态路由,主要是在路由器上,配置了一条条的规则,就是想要访问BBS站,要从2口出去,然后下一跳是ip2,想要访问视频中心,从3口出去,下一跳是ip3

每当来了个新包并选择从那个口出去的时候,就要一条条的选择规则,找到合适的,然后从某个口抛出去,到下一跳

对于IP和MAC的转换关系

可以分为了两个类型,一种是IP不变”欧洲十国行” ,一种是IP改变,”玄奘西行”

因为在整体的过程中,IP很少变化,但是每过一个关卡,MAC都会改变,对于IP不变的网关,我们称呼为转发网关,对于IP改变的网关,我们称为NAT网关

首先是欧洲十国游型

图片

服务器A去访问B,那么A会思考,因为不是本网段的,所以会先发给网关,那么网关收到了这个包,这个包的格式如下

图片

然后收到了包之后,发现MAC一致,收进来,思考如何转发

因为路由器中定义了静态路由,访问 192.168.4.0/24,需要从192.168.56.1这个口出去,下一跳是192.168.56.2

路由器会从192.168.56.1这个口发出去,发往192.168.56.2,那么56.2的MAC地址是多少呢?

路由器A发送ARP获取192.168.56.2的MAC地址,然后发送包

图片

然后路由器B就收到了这个路由,发现MAC一致,收了进来,同时思考往哪里发送,在路由表B中配置了静态路由,要访问192.168.4.0/24,需要从我的192.168.4.1这个口出去,而且因为是同一个网段,所以没有下一跳了,于是发送了出去,整个包如下

图片

服务器B收到了这个包,匹配了MAC地址,收了进来

这个过程中可以看出,每到一个新的局域网,Mac都是要变的,但是IP不变,而下一跳就是,将下一个发送的网段IP,获取出来,然后转换为MAC地址,放到MAC头里面

这就好比欧洲十国游,整个过程中,IP的地址不会改变,签证也不会变

IP会变 玄奘西行

在发送包的时候,可能出现的问题是,IP段冲突了,本网段的地址是192.168.1.101,其他的网段的地址也是192.168.1.101,直接看起来,就好比自己访问自己

但是目标服务器会有一个国际身份,我就利用这个国际身份来发送,假设,国际身份是192.168.56.2,这个国际身份对应着一个国内身份 192.168.1.101,所有访问192.168.56.2,转为192.168.1.101

这样,源服务器会发送一个带有国际身份的包去请求服务器B,但是一开始,因为国际身份的包不是本网段的,所以先发给网关,这个网关假设是192.168.1.1,于是发送出去包带着网关的MAC

一开始发送的包如下

图片

然后到了网关,收了进来,思考如何转发

路由器A中配置了静态路由,告诉路由器A,想要访问192.168.56.2/24,就要从192.168.56.1这个口出去,到了同一个网段了,

但是在发送出去的时候,服务器A需要一个国际身份,所以不能拿着192.168.1.101这个源IP发送,需要改写,改写为192.168.56.1,发送了出去

图片

服务器B收到了这个请求,发现MAC一只,收了进来,这是一个NAT网关,配置了访问国际身份192.168.56.2对应国内身份192.168.1.101

然后进行发送给了服务器B

图片

中间经过了ip的转换,源ip为服务器A的国际身份,返回包的时候,也是返回的国际身份,这时候路由器A是NAT网关,进行了身份转变

NAT网关:Network Address Translation 简称NAT

本章小结

如果需要离开局域网,需要一个网关

路由器是一个三层设备,可以获取到下一跳

经过路由器后MAC头要变,但是IP变不变,是看网关是NAT吗?

课后思考

1.在访问163网站的时候,自己的ip,肯定经过了NAT网关变成了公网ip,返回的时候如何返回回来的

2.对于路由规则,我们说了静态设置,如何动态设置呢?

1.其实在真正的转发的时候,Nat路由会借助端口来进行自己专有局域网内得对应的私有IP主机,将一个公网的IP+NAT端口映射称多个内网主机+主机端口,提高了IP利用率,详细点说就是

对于NAT这种直接的映射,很少使用,一般使用的是,NAPT,进行了IP地址和传输层端口改写

对于传出 NAT 路由器的数据包,NAT 根据源 IP 地址和传输层端口号在尽可能保留源端口号的情况下将其转写为 NAT 可用 IP 地址池里的 IP 地址和可用的 NAT 端口,并用 Session(TCP)或者活跃计时器(UDP)的方法来记忆”源IP地址+传输层端口号 <=> NAT IP 地址 + NAT 端口号“的映射。这样,当相应的回复数据包返回 NAT 路由器时,我们可以根据记录信息将 IP 地址和端口号转写回去。

更加具体点的可以解释为

我们说了iptables的时候,说了conntrack功能,记录了SNAT一去一回的关系

如果编译内核的时候开启了连接追踪的选项,Linux系统会为其收到的每一个数据包维持一个连接状态,用于记录这个连接的状态

图片

对于网络包,会存在着三条路径

发给我的,从PREROUTING到INPUT

发给别人,从OUTPUT到POSTROUTING,发送出去

经过的,PREROUTING到FORWARD到POSTROUTING

跟踪一个网络包,对每一个路径,设置两个记录点,打两次卡,内核知道这个包的状态

这三种路径

发给我的,我会在PREROUTING时候调用ipv4_conntrack_in,创建连接跟踪记录,在INPUT中调用ipv4_confim,将这个连接记录挂在内核的连接跟踪表,只有确定接收的,才会记录连接

对于我发出的,会在OUTPUT掉用 ipv4_conntrack_local,创建连接跟踪记录,在POSTROUTING里调用ipv4_confirm,将这个记录跟踪挂在内核的连接跟踪表里

对于从我这里经过的,在PRETOURING调用ipv4_conntrack_in,创建连接跟踪记录,在POSTROUTING中调用ipv4_confirm,将这个连接追踪放在内核的追踪表里

网关的主要工作是转发,主要就好比NAT网关,从我这里经过的,再加上NAT,因而将NAT的过程融入连接追踪的过程中

如果是PREROUTING的话,先调用ipv4_conntrack_in,创建连接跟踪记录

如果是PREROUTING时候,有NAT规则,则调用nf_nat_ipv4_in进行地址转换

如果是POSTROUTING,有NAT规则,调用nf_nat_ipv4_out进行地址转换

涉及跟踪记录,连接跟踪表这两个数据结构

在前面说网络包处理的时候,我们说了每个网络包struct_sk_buff,有一个成员变量 _nfct指向一个连接跟踪记录 struct_nf_conn,当然当一个网络包刚进来的时候,不会指向一个结构的,但是这个网络包必然属于某个连接,会先去连接追踪表中查找,之后赋值给sk_buff这个成员变量,没找到的话,说明是一个新的连接,在连接追踪表里面新创建一个

在nf_conntrack是_nfct变量指向的地址

tuplehash是数组,但是里面只有两个变量,一个是IP_CT_DIR_OPIGINAL为下标0,表示连接发起的方向,IP_CT_DIR_REPLY是下标1,表示连接回复的方向

每当有一个网络包来了,就会将网络包里面的sk_buff中数据提取出来,形成nf_conntrack_tuple,利用里面的内容记算哈希值,然后在哈希表中查找,如果找到了,说明这个连接出现过,没找到则生成一个插入哈希表

通过nf_conntrack_tuple里面的内容,唯一标识一个连接

src:标识源IP,如果是TCP或者UDP,包含源端口,如果是ICMP,包含的是ID

dst:标识目标IP,如果是tcp或者udp,包含目标端口,如果是ICMP,包含type,code

当一个包发出去,到达了这个NAT网关的时候,先经过PREROUTING,调用ipv4_conntack_in,进来的包sk_buff为

{源ip:客户端ip,源端口:客户端port,目标ip:服务端ip,目标端口:服务端port} 将这个转换为nf_conntrack_tuple,然后进行哈希运算,然后查找是否有记录,如果没有就是一个新的连接

于是,创建一个新的连接记录,里面有两个nf_conntrack_tuple_hash

一去:{

源IP:客户端IP,客户端port, 目标IP:服务器IP,服务器port

}

一回{

源IP:服务端IP,服务端port, 目标IP:客户端IP,目标端口:客户端port

}

在进入POSTROUTING的过程,有NAT规则,调用nf_nat_ipv4_out地址,转换,这时候,源地址要变成NAT网关的IP地址,对于masquerade来说,会自动选择一个公网IP和随机端口

为了让包回来的时候,能够找到追踪连接,需要修改两个nf_conntrack_tuple_hash中回来的一项,

{

源IP:服务端IP,源端口:服务端port,目标IP:NAT网关IP,目标端口:随机端口

}

将这个转换为了nf_conntrack_tuple,进行哈希运算,在连接跟踪表里面查找,能找到相对应的记录,找到nf_conntrack_hash之后,可以获取到外面的连接追踪记录,nf_conn,通过这个找到来的方向的那个nf_conntrack_tuple_hash,找到对应的客户端的IP和端口,NAT回去

NAT能建立多少的连接

如果将端口号和IP都转换为公网IP和运算后的端口,端口最多65535个,会有这个上限吗?

SNAT多用于内网访问外网的场景

如果内网机器多,访问的外网不同,导致可以承载的内网数量不止65535个

如果所有的内网都访问同一个目标IP和端口,源IP只有一个,导致受到65535端口数目限制,一种方法就是多种源IP,利用多个NAT网关来分摊内网机器的访问

如果是公有云,65535个机器,放在一个VPC里面,可以做多个NAT网关的设置

nat支持一对一的转换,也支持一对多,如果是一对多的转换,需要维护一张映射的表

内网ip:port -> 外网 ip:port

只要路由器空闲ip足够多就可以了,但是,像是微信这样海量用户长连接的,路由器的port必然不够,如何处理的呢?

对于微信,服务器在数据中心内,无论多少长连接,服务器监听的都是少数的几个端口,是DNAT的场景,不需要担心端口数目,一个服务器也不会维护这么多的连接,因此NAT的网关后面会部署多个Nginx分摊

公网IP和私网IP需要进行意义绑定吗?

如果一个内网有十台机器,但是只有一个公网IP的情况,那么网络中只有一台可以连接外网,其他都连接不了

这个想法必然不对,对于需要对外提供服务的节气,接入层的Nginx需要公网IP,没有公网IP,使用SNAT也行,大家共享SNAT网关的公网IP地址

主要是区分是内网访问外网,还是外网访问内网

发表评论

邮箱地址不会被公开。 必填项已用*标注