NAT网关设计

目的

本文的目的是将Linux配置成NAT网关,具备NAT、DHCP、DNS功能,实现内网访问外网的通信、实现外网对特定主机的访问、实现内网主机的IP地址动态分配以及域名解析的功能。

环境

实验环境介绍:

  • 一台搭建了KVM环境的物理服务器,命名为Server,并在该服务器上创建两台虚拟机VM

  • 第一台虚拟机用作NAT网关,命名为Gateway,分配两张网卡,eth0连接内网,eth1连接外网;

  • 第二台虚拟机作为内网主机,命名为Host,分配一张网卡eth0连接内网。

  • 内网网段为:10.0.0.0/24

  • 外网网段为:192.168.1.0/24

    注:本实验其实也可以在VMware workstation或者virtualBox环境下进行,但是由于博主的电脑配置不高,不想在个人电脑上搭建该环境,且身边的服务器刚好有空闲的资源,所以就在服务器上搭建了该环境,至于如何在服务器上搭建KVM环境可以参照我的另一篇博客的部分内容 快速链接

搭建实验环境:

  • 创建内部网桥:服务器Server上创建一个虚拟网桥br-int,作为连接内网的交换机。

    1
    2
    3
    4
    5
    6
    7
    $ sudo brctl addbr br-int

    $ brctl show
    bridge name bridge id STP enabled interfaces
    br-int 8000.000000000000 no

    $ sudo ifconfig br-int up

    注:VMware workstation中搭建环境时需要在虚拟网络编辑器中将使用本地DHCP服务将IP分配给虚拟机选项取消勾选,因为我们需要实现NAT网关来给虚拟机分配IP。另外在创建虚拟网桥后一定要开启该网桥。

  • 创建NAT网关虚拟机

    其网络配置信息如下:

    • eth0

      Gateway_NIC0

    • eth1

      Gateway_NIC1通过ifconfig查看网络信息:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      $ ifconfig
      eth0 Link encap:Ethernet HWaddr 52:54:00:1c:83:53
      inet6 addr: fe80::5054:ff:fe1c:8353/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
      ...

      eth1 Link encap:Ethernet HWaddr 52:54:00:de:e8:51
      inet addr:192.168.1.123 Bcast:192.168.1.255 Mask:255.255.255.0
      inet6 addr: fe80::5054:ff:fede:e851/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
      ...

      lo Link encap:Local Loopback
      inet addr:127.0.0.1 Mask:255.0.0.0
      inet6 addr: ::1/128 Scope:Host
      UP LOOPBACK RUNNING MTU:65536 Metric:1
      ...

      可见NAT网关的eth0网卡因为没有DHCP服务器所以没有分配到IP,但外网网卡eth1已经有一个外网IP。

  • 创建内部主机虚拟机

    其网络配置信息如下:

    • eth0

      Host_NIC0通过ifconfig查看网络信息:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      $ ifconfig
      eth0 Link encap:Ethernet HWaddr 52:54:00:1a:a1:78
      inet6 addr: fe80::5054:ff:fe1a:a178/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
      ...

      lo Link encap:Local Loopback
      inet addr:127.0.0.1 Mask:255.0.0.0
      inet6 addr: ::1/128 Scope:Host
      UP LOOPBACK RUNNING MTU:65536 Metric:1
      ...

      可见其内网网卡eth0没有分配IP。

      其实,在启动这两个虚拟机时,因为内部网络没有DHCP服务器,他们的内网网卡会一直等待DHCP服务器给它们分配IP,等待的时间大概是5分钟,最终还是没有获得IP。

  • 修改两个虚拟机的网络配置文件

    • NAT网关$ sudo vi /etc/network/interfaces

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      source /etc/network/interfaces.d/*

      # The loopback network interface
      auto lo
      iface lo inet loopback

      # The primary network interface
      auto eth0
      iface eth0 inet static
      address 10.0.0.1
      netmask 255.255.255.0
      gateway 10.0.0.1

      auto eth1
      iface eth1 inet dhcp

      因为NAT网关的eth0将做内网的网关,故将其IP设置为静态IP:10.0.0.1,这样更容易识别,且不会因为重启而改变。

    • 内部主机$ sudo vi /etc/network/interfaces

      1
      2
      3
      4
      5
      6
      7
      8
      9
      source /etc/network/interfaces.d/*

      # The loopback network interface
      auto lo
      iface lo inet loopback

      # The primary network interface
      auto eth0
      iface eth0 inet dhcp
  • 在服务器Server上查看虚拟网桥的信息:

    1
    2
    3
    4
    $ brctl show br-int
    bridge name bridge id STP enabled interfaces
    br-int 8000.fe54001aa178 no vnet1
    vnet3

    可以看到虚拟网桥br-int上面已经有两个网络接口,对应两个虚拟机的内部网卡。

NAT 功能实现

NAT网关的功能是通过Linux中自带的iptables来实现,NAT功能包括SNAT和DNAT。SNAT是源地址转换,在内网主机访问外网时发挥作用,可以将内网主机的ip地址转换为网关的ip地址。DNAT是目的地址转换,在外网的主机通过NAT网关的ip和端口对内网主机发起访问时发挥作用,可以将NAT网关的ip地址与端口转换为对应内网主机的ip,从而实现从外网对内网中某一特定主机的访问。当然要将Linux虚拟机配置成NAT网关,首先得要开启Linux虚拟机的网络转发功能。下面将介绍NAT功能的实现过程:

  1. 开启网络转发功能

    • 临时开启网络转发功能,需要切换到root用户,命令如下:

      # echo 1 > /proc/sys/net/ipv4/ip_forward

      这样在下次虚拟机重启后该功能会自动关闭,因此可以修改配置文件的方式来开启该功能并永久生效。

    • 永久开启网络转发功能:

      # vi /etc/sysctl.conf

      在文件里面添加一行net.ipv4.ip_foward=1,在下次重启之后就不会还原了。

  2. SNAT的实现

    iptablesnat表POSTROUTING规则链中添加规则,使得从10.0.0.0/24网络发到NAT网关的数据包,从eth1转发出去,并将数据包的源ip地址修改为NAT网关的外网地址,命令如下 :

    sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth1 -j SNAT --to-source 192.168.1.123

    192.168.1.123是NAT网关的外网网卡eth1的IP。

  3. DNAT的实现

    iptablesnat表PREROUTING规则链中添加规则,使得从外网发往NAT网关固定端口(如:8080)的TCP(这里也可以添加其他网络协议)数据包转发到内网的某固定主机上,命令如下:

    sudo iptables -t nat -A PREROUTING -i eth1 -d 192.168.1.67 -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.107:22

    10.0.0.107是内网某主机的IP,这里说明一下:实际实现的过程中,最好先实现DHCP与DNS的功能。

  4. 保存iptables规则

    sudo iptables-save | sudo tee /etc/iptables.sav

  5. 编辑/etc/rc.local文件,将下面的一行添加到"exit 0"之前:

    iptables-restore < /etc/iptables.sav

    这样每次重启机器时都会自动加载NAT相关的iptables规则。

DHCP与DNS功能实现

实现DHCP服务器可以使用isc-dhcp-server工具包,实现DNS服务器可以使用bind9工具包,但是本实验考虑使用DNSmasq工具来同时实现DHCP服务器与DNS服务器的功能。DNSmasq是一个小巧且方便地用于配置DHCP和DNS的工具,适用于小型网络。作为域名解析服务器(DNS),DNSmasq可以通过缓存DNS请求来提高对访问过的网址的连接速度。作为DHCP服务器,DNSmasq可以用于为局域网电脑分配内网ip地址和提供路由。

  • 安装DNSmasq工具:

    $ sudo apt-get install dnsmasq

  • 编辑DNSmasq的配置文件/etc/dnsmasq.conf,添加下面两行:

    1
    2
    interface=eth0
    dhcp-range=10.0.0.100,10.0.0.200,72h

    其中interface是用作内网网关的网卡,也就是NAT网关的eth0网卡;dhcp-range是动态分配的IP地址池;72h表示分配的IP的有效时间是72个小时,到时间后需要重新分配IP。

  • 重启DNSmasq服务:

    1
    2
    $ sudo /etc/init.d/dnsmasq restart
    [ ok ] Restarting dnsmasq (via systemctl): dnsmasq.service.

    到这里就配置内容就完成了。然后需要重启这两个虚拟机。

测试结果

  • DHCP服务

    在完成DHCP服务器配置重启虚拟机后,会发现在启动过程中不再需要等待5分钟来获取IP了,进入内部主机查看网络信息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $ ifconfig
    eth0 Link encap:Ethernet HWaddr 52:54:00:1a:a1:78
    inet addr:10.0.0.176 Bcast:10.0.0.255 Mask:255.255.255.0
    inet6 addr: fe80::5054:ff:fe1a:a178/64 Scope:Link
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
    RX packets:17 errors:0 dropped:0 overruns:0 frame:0
    TX packets:21 errors:0 dropped:0 overruns:0 carrier:0
    collisions:36 txqueuelen:1000
    RX bytes:1642 (1.6 KB) TX bytes:2182 (2.1 KB)

    lo Link encap:Local Loopback
    inet addr:127.0.0.1 Mask:255.0.0.0
    inet6 addr: ::1/128 Scope:Host
    UP LOOPBACK RUNNING MTU:65536 Metric:1
    RX packets:164 errors:0 dropped:0 overruns:0 frame:0
    TX packets:164 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1
    RX bytes:12200 (12.2 KB) TX bytes:12200 (12.2 KB)

    可以看到eth0分配到了一个在DHCP地址池内的一个IP:10.0.0.176

  • DNS与NAT服务

    这里将同时对DNS服务与NAT服务进行测试

    • 内网到外网

      由于我所在的网络所有的ping外网的报文都会被拦截,所以没有办法通过ping来测试网络的连通性,这里采用wget命令在内部主机测试:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      $ wget http://www.baidu.com
      --2018-07-08 16:30:37-- http://www.baidu.com/
      Resolving www.baidu.com (www.baidu.com)... 180.97.33.108, 180.97.33.107
      Connecting to www.baidu.com (www.baidu.com)|180.97.33.108|:80... connected.
      HTTP request sent, awaiting response... 200 OK
      Length: 2381 (2.3K) [text/html]
      Saving to: ‘index.html’

      index.html 100%[================================>] 2.33K --.-KB/s in 0s

      2018-07-08 16:30:37 (61.1 MB/s) - ‘index.html’ saved [2381/2381]

      上面的测试说明内网主机到外网的连通性,并且也实现了域名解析的功能。

    • 外网到内网

      在博主的个人Windows电脑上去访问内网主机,以此来测试外网到内网的连通性:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      [c:\~]$ ssh openstack-image@192.168.1.152 8080

      Connecting to 192.168.1.152:8080...
      Connection established.
      To escape to local shell, press 'Ctrl+Alt+]'.

      Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-87-generic x86_64)

      * Documentation: https://help.ubuntu.com
      * Management: https://landscape.canonical.com
      * Support: https://ubuntu.com/advantage

      134 packages can be updated.
      55 updates are security updates.

      Last login: Sun Jul 8 16:13:54 2018
      openstack-image@ubuntu:~$ ifconfig
      eth0 Link encap:Ethernet HWaddr 52:54:00:d0:51:38
      inet addr:10.0.0.176 Bcast:10.0.0.255 Mask:255.255.255.0
      inet6 addr: fe80::5054:ff:fed0:5138/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
      RX packets:96 errors:0 dropped:0 overruns:0 frame:0
      TX packets:125 errors:0 dropped:0 overruns:0 carrier:0
      collisions:516 txqueuelen:1000
      RX bytes:17842 (17.8 KB) TX bytes:15515 (15.5 KB)

      lo Link encap:Local Loopback
      inet addr:127.0.0.1 Mask:255.0.0.0
      inet6 addr: ::1/128 Scope:Host
      UP LOOPBACK RUNNING MTU:65536 Metric:1
      RX packets:176 errors:0 dropped:0 overruns:0 frame:0
      TX packets:176 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1
      RX bytes:13392 (13.3 KB) TX bytes:13392 (13.3 KB)

      可以访问,外网到内网也是连通的。到此,需要实现的功能都已经实现了。