之所以用笔记本做路由是因为笔记本有两个网卡:无线网卡和有线网卡
本文要解决的问题是,在笔记本连上了无线网的情况下,如何让旁边的台式机也能上网?
一种方法是将台式机与运营商提供宽带的猫或路由器用网线连接,但如果没有这种条件就不行,比如笔记本连的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的实现