之所以用笔记本做路由是因为笔记本有两个网卡:无线网卡和有线网卡

 

  本文要解决的问题是,在笔记本连上了无线网的情况下,如何让旁边的台式机也能上网?

  一种方法是将台式机与运营商提供宽带的猫或路由器用网线连接,但如果没有这种条件就不行,比如笔记本连的WIFI是公共场所的。

  另一种方法是让台式机与笔记本的网口相连,变笔记本为路由器,从而上网。

 

我的笔记本与台式机都是Ubuntu 16.04。

 

笔记本的ifconfig:

xiangzi@xiangzi-meiming:~$ ifconfig
ens4      Link encap:以太网  硬件地址 b0:25:aa:18:37:d1  
          inet 地址:192.168.56.200  广播:192.168.56.255  掩码:255.255.255.0
          inet6 地址: fe80::b225:aaff:fe18:37d1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
          接收数据包:136 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:195 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000
          接收字节:15749 (15.7 KB)  发送字节:20429 (20.4 KB)

lo        Link encap:本地环回  
          inet 地址:127.0.0.1  掩码:255.0.0.0
          inet6 地址: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  跃点数:1
          接收数据包:7431 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:7431 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000
          接收字节:602072 (602.0 KB)  发送字节:602072 (602.0 KB)

wls3      Link encap:以太网  硬件地址 2c:6e:85:c4:1a:ad  
          inet 地址:192.168.1.105  广播:192.168.1.255  掩码:255.255.255.0
          inet6 地址: fe80::8602:7c6:b7a0:721c/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  跃点数:1
          接收数据包:117939 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:56555 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000
          接收字节:143118550 (143.1 MB)  发送字节:7030929 (7.0 MB)

标红的地方是重点。

 

笔记本的路由表:

xiangzi@xiangzi-meiming:~$ netstat -rn
内核 IP 路由表
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG        0 0          0 wls3
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 ens4
192.168.1.0     0.0.0.0         255.255.255.0   U         0 0          0 wls3
192.168.56.0    0.0.0.0         255.255.255.0   U         0 0          0 ens4

笔记本连接的无线网接口名是wls3,它的IP是192.168.1.105,是路由器DHCP自动分配的,通过这个IP可以访问外网,与外网通讯数据通过的网关是默认网关192.168.1.1。

wls3网络接口所处的子网IP是192.168.1.0/24。

另外还需注意另外一个网络接口ens4,它有IP地址192.168.56.200,子网掩码255.255.255.0。这个接口本来是没有IP的,但要给它配置上一个静态IP:

xiangzi@xiangzi-meiming:~$ cat /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

#set ens4 as static ip
auto ens4
allow-hotplug ens4
iface ens4 inet manual
iface ens4 inet static
address 192.168.56.200
netmask 255.255.255.0
#gateway 192.168.0.1
#network 192.168.0.1

 

它的IP配置成192.168.56.200。

 

接下来还要配置下台式机的IP:

台式机的ifconfig:

zhang@zhang-honglian:~$ ifconfig
enp1s4    Link encap:以太网  硬件地址 00:1e:8c:c3:c5:88  
          inet 地址:192.168.56.201  广播:192.168.56.255  掩码:255.255.255.0
          inet6 地址: fe80::21e:8cff:fec3:c588/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
          接收数据包:5419 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:31431 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000
          接收字节:475257 (475.2 KB)  发送字节:11842976 (11.8 MB)

lo        Link encap:本地环回  
          inet 地址:127.0.0.1  掩码:255.0.0.0
          inet6 地址: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  跃点数:1
          接收数据包:273 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:273 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000
          接收字节:21772 (21.7 KB)  发送字节:21772 (21.7 KB)

台式机路由表:

zhang@zhang-honglian:~$ netstat -rn
内核 IP 路由表
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.56.200  0.0.0.0         UG        0 0          0 enp1s4
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 enp1s4
192.168.56.0    0.0.0.0         255.255.255.0   U         0 0          0 enp1s4

台式机只有enp1s4这么一个网口,它的IP也需被配置成静态IP,配成192.168.56.201。

需要注意的是,台式机网口的IP所处的子网IP要与笔记本的有线网卡子网IP相同。都是192.168.56.0/24。用一根网线把这两个网口相连,即构成了一个局域网。两个网口可以通过链路层协议直接通讯。

除了静态IP外,还需要为台式主机添加一条与外网通讯的默认路由,即:

Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface

0.0.0.0         192.168.56.200  0.0.0.0         UG        0 0          0 enp1s4

将网关地址设置成笔记本有线网口的IP地址192.168.56.200。

 

我们要关心数据包往返的过程:

台式机192.168.56.201发往Internet的数据包先通过默认路由表项传给(笔记本)网关192.168.56.200,再由路由器(笔记本)使用默认路由通过网口wls3转发到下一个网关192.168.1.1,就这样一直传送到目的主机所处网络和子网,目的主机接收到为止。

而从目的主机返回的数据包,也是通过使用相同的路由策略,一直将数据包转发到192.168.1.1所在路由器的某个网口,然后根据此路由器内部的选路策略,它决定从网关192.168.1.1转发到(笔记本)网关192.168.1.105(要注意此时笔记本是一台路由器,它的每个网络接口都可以称为用来转发数据包的网关)。然后笔记本搜索它自己的路由表,决定将此数据包通过网关ens4(192.168.56.200)转发到处于同一子网的目的主机192.168.56.201。

 

上面提到台式机两项任务:配置静态IP,添加默认路由。可以一步完成:

zhang@zhang-honglian:~$ cat /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

#set enp1s4 static ip address
auto enp1s4
iface enp1s4 inet static
address 192.168.56.201
gateway 192.168.56.200
netmask 255.255.255.0
dns-nameservers 114.114.114.114 114.114.115.115
#network 192.168.26.0
#broadcast 192.168.26.255

可以看到里面还配置了DNS服务器地址,因为静态IP不会自动获取对应的DNS服务器。笔记本不用为ens4接口(静态IP)配置DNS服务器,因为笔记本上网是通过wls3接口(DHCP),自动获取DNS服务器。

 

最后,开启笔记本linux的数据包转发功能,变成路由器:

  将文件/etc/sysctl.conf里面的net.ipv4.ip_forward=1的注释去除,然后重启。

  linux默认是不开启数据转发的,net.ipv4.ip_forward项默认为0。将它置1才表示开启,摇身一变路由器。

 

通过上面的介绍,看似这样就可实现台式机与Internet通讯,但实际上还忘记了一个很重要的问题:网关192.168.1.1所在的路由器的路由选择问题。

  我称这个路由器为A,假如外网主机给台式机返回一个数据包,这个包先被A所接收,然后A凭什么决定将此数据包(目的IP为192.168.56.201)通过接口192.168.1.1转发给笔记本的192.168.1.105?虽然这种转发路径是我期望的,但A不知道这么做,因为它的路由表里面并没有这种转发条件:将目的地址为192.168.56.201的数据包从接口192.168.1.1转发出去 或者 将目的IP所在子网为192.168.56.0/24的数据包从接口192.168.1.1转发出去。于是它将使用路由表的默认表项进行转发,在网络中迷路,如果没有默认表项则丢弃。如果路由器A和笔记本都使用动态选路协议,那笔记本可以将自己所处的网络信息(192.168.56.0/24)告诉给A,自动让A实现正确的选路。但它们两的路由表都是静态的,没那么高级。

  要解决这个问题,需要手动去为路由器A添加一条路由表项,但实际当中一般是不可行的。即使可行也有可能引起其他的选路问题。

 

  解决这个问题的一种有效方法是NAT。

 

  192.168.1.1所在路由器(路由器A)虽然不知道如何转发目的IP为192.168.56.201的数据报,但是它知道如何转发目的IP所在子网为192.168.1.0/24的数据报:就是通过网关192.168.1.1转发出去的。

  因此我们可以在作为路由器的笔记本上使用NAT技术,将台式机的IP(192.168.56.201)转换成处于192.168.1.0/24网段的某个IP地址,进而与外网通讯。这样,台式机与外网的通讯对于A来说就像笔记本(192.168.1.105)与外网通讯一样简单,台式机的IP对于A来说就像是处于192.168.1.0/24内的一台机器。

 

  在笔记本上实现这种NAT,只需要root下执行下面这条命令:

  # iptables -t nat -A POSTROUTING -s 192.168.56.201 -j MASQUERADE

   执行后立即生效,重启后会被清除。

对这条命令的解释:

  -t nat : 对NAT映射表的操作

  -A POSTROUTING : 路由后进行转换

  -s 192.168.56.201 : 指定要转换的源主机IP

  -j MASQUERADE : 动态伪装转换后的IP地址而不是静态写死

 

iptables参考资料:http://blog.chinaunix.net/uid-26495963-id-3279216.html

SNAT和DNAT的实现

 
由于我们现在IP地址十分紧俏,已经分配完了,这就导致我们必须要进行地址转换,来节约我们仅剩的一点IP资源。那么通过iptables如何实现NAT的地址转换呢?
 
1.SNAT基于原地址的转换
基于原地址的转换一般用在我们的许多内网用户通过一个外网的口上网的时候,这时我们将我们内网的地址转换为一个外网的IP,我们就可以实现连接其他外网IP的功能
所以我们在iptables中就要定义到底如何转换:
定义的样式:
比如我们现在要将所有192.168.10.0网段的IP在经过的时候全都转换成172.16.100.1这个假设出来的外网地址:
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j SNAT --to-source 172.16.100.1
这样,只要是来自本地网络的试图通过网卡访问网络的,都会被统统转换成172.16.100.1这个IP.
那么,如果172.16.100.1不是固定的怎么办?
我们都知道当我们使用联通或者电信上网的时候,一般它都会在每次你开机的时候随机生成一个外网的IP,意思就是外网地址是动态变换的。这时我们就要将外网地址换成 MASQUERADE(动态伪装):它可以实现自动寻找到外网地址,而自动将其改为正确的外网地址。所以,我们就需要这样设置:
         iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j MASQUERADE
         这里要注意:地址伪装并不适用于所有的地方。