Linux 网络与 iptables 设置

模拟环境

虚拟机上模拟运行一台 Server 和一台 Client,操作系统都为 Ubuntu 18.04

配置主要在 Server 上进行,并且 Server 上部署有 Apache。

Server 拥有两个 Host-only 接口:enp0s3enp0s8,一个 NAT 接口:enp0s9

Server 和 Client 通过局域网进行连接,Server 的 IP 地址为 192.168.60.100 ,Client 的 IP 地址为 192.168.60.111

Interfaces 接口

  1. ip link : 列出 Linux 系统中可用的接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ ip link
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:6e:d4:13 brd ff:ff:ff:ff:ff:ff
    3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:86:21:8d brd ff:ff:ff:ff:ff:ff
    4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 08:00:27:28:41:e0 brd ff:ff:ff:ff:ff:ff
  2. ip address show : 列出可用接口以及相关 IP 地址

    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
    $ ip address show
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
    valid_lft forever preferred_lft forever
    2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:6e:d4:13 brd ff:ff:ff:ff:ff:ff
    inet 192.168.60.100/24 brd 192.168.60.255 scope global enp0s3
    valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe6e:d413/64 scope link
    valid_lft forever preferred_lft forever
    3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:86:21:8d brd ff:ff:ff:ff:ff:ff
    inet 192.168.70.5/24 brd 192.168.70.255 scope global enp0s8
    valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe86:218d/64 scope link
    valid_lft forever preferred_lft forever
    4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:28:41:e0 brd ff:ff:ff:ff:ff:ff
    inet 10.0.98.100/24 brd 10.0.98.255 scope global enp0s9
    valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe28:41e0/64 scope link
    valid_lft forever preferred_lft forever
  3. ip -4 address / ip -6 address : 精简版

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ ip -4 address
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
    2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.60.100/24 brd 192.168.60.255 scope global enp0s3
    valid_lft forever preferred_lft forever
    3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.70.5/24 brd 192.168.70.255 scope global enp0s8
    valid_lft forever preferred_lft forever
    4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.0.98.100/24 brd 10.0.98.255 scope global enp0s9
    valid_lft forever preferred_lft forever
  4. 查看 interfaces 相关配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    $ cat /etc/network/interfaces
    # interfaces(5) file used by ifup(8) and ifdown(8)
    auto lo
    iface lo inet loopback

    # NAT interface
    auto enp0s9
    iface enp0s9 inet static
    address 10.0.98.100
    netmask 255.255.255.0
    gateway 10.0.98.2

    # Connection to subnet A (host-only interface)
    auto enp0s3
    iface enp0s3 inet static
    address 192.168.60.100
    netmask 255.255.255.0

    # IPsec VPN connection to subnet B (host-only interface)
    auto enp0s8
    iface enp0s8 inet static
    address 192.168.70.5
    netmask 255.255.255.0

Routing Tables

  1. ifconfig -a

    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
    35
    36
    $ ifconfig -a
    enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
    inet 192.168.60.100 netmask 255.255.255.0 broadcast 192.168.60.255
    inet6 fe80::a00:27ff:fe6e:d413 prefixlen 64 scopeid 0x20<link>
    ether 08:00:27:6e:d4:13 txqueuelen 1000 (Ethernet)
    RX packets 5 bytes 1169 (1.1 KB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 62 bytes 6624 (6.6 KB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

    enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
    inet 192.168.70.5 netmask 255.255.255.0 broadcast 192.168.70.255
    inet6 fe80::a00:27ff:fe86:218d prefixlen 64 scopeid 0x20<link>
    ether 08:00:27:86:21:8d txqueuelen 1000 (Ethernet)
    RX packets 5 bytes 1169 (1.1 KB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 63 bytes 6825 (6.8 KB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

    enp0s9: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
    inet 10.0.98.100 netmask 255.255.255.0 broadcast 10.0.98.255
    inet6 fe80::a00:27ff:fe28:41e0 prefixlen 64 scopeid 0x20<link>
    ether 08:00:27:28:41:e0 txqueuelen 1000 (Ethernet)
    RX packets 300925 bytes 401914103 (401.9 MB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 31878 bytes 2023292 (2.0 MB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

    lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
    inet 127.0.0.1 netmask 255.0.0.0
    inet6 ::1 prefixlen 128 scopeid 0x10<host>
    loop txqueuelen 1000 (Local Loopback)
    RX packets 31 bytes 2955 (2.9 KB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 31 bytes 2955 (2.9 KB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  2. ip -4 route : 查看 route table

    1
    2
    3
    4
    5
    6
    $ ip -4 route
    default via 10.0.98.2 dev enp0s9 onlink
    10.0.98.0/24 dev enp0s9 proto kernel scope link src 10.0.98.100
    169.254.0.0/16 dev enp0s8 scope link metric 1000
    192.168.60.0/24 dev enp0s3 proto kernel scope link src 192.168.60.100
    192.168.70.0/24 dev enp0s8 proto kernel scope link src 192.168.70.5

Firewall (iptables)

  1. 查看 iptables 的默认规则

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ sudo iptables -L -t filter
    Chain INPUT (policy ACCEPT)
    target prot opt source destination

    Chain FORWARD (policy ACCEPT)
    target prot opt source destination

    Chain OUTPUT (policy ACCEPT)
    target prot opt source destination
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $ sudo iptables -L -t mangle
    Chain PREROUTING (policy ACCEPT)
    target prot opt source destination

    Chain INPUT (policy ACCEPT)
    target prot opt source destination

    Chain FORWARD (policy ACCEPT)
    target prot opt source destination

    Chain OUTPUT (policy ACCEPT)
    target prot opt source destination

    Chain POSTROUTING (policy ACCEPT)
    target prot opt source destination
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ sudo iptables -L -t nat
    Chain PREROUTING (policy ACCEPT)
    target prot opt source destination

    Chain INPUT (policy ACCEPT)
    target prot opt source destination

    Chain OUTPUT (policy ACCEPT)
    target prot opt source destination

    Chain POSTROUTING (policy ACCEPT)
    target prot opt source destination
  2. 阻止 Server 访问外部 HTTP 网页

    1
    sudo iptables -A OUTPUT -p tcp --dport 80 -j REJECT
  3. 阻止外部访问 Server 上的 HTTP 网页

    1
    sudo iptables -A INPUT -p tcp --dport 80 -j REJECT
  4. 删除已经创建的规则

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    $ sudo iptables -L -n --line-numbers
    Chain INPUT (policy ACCEPT)
    num target prot opt source destination

    Chain FORWARD (policy ACCEPT)
    num target prot opt source destination

    Chain OUTPUT (policy ACCEPT)
    num target prot opt source destination
    1 REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 reject-with icmp-port-unreachable
    $ sudo iptables -D OUTPUT 1
    $ sudo iptables -L -n --line-numbers
    Chain INPUT (policy ACCEPT)
    num target prot opt source destination

    Chain FORWARD (policy ACCEPT)
    num target prot opt source destination

    Chain OUTPUT (policy ACCEPT)
    num target prot opt source destination
  5. 改为使用脚本,配置日志记录并修改默认规则为 DROP

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #!/bin/sh

    IPT=/sbin/iptables
    # NAT interface
    NIF=enp0s9
    # NAT IP address
    NIP='10.0.98.100'

    # Host-only interface
    HIF=enp0s3
    # Host-only IP addres
    HIP='192.168.60.100'

    # DNS nameserver
    NS='10.0.98.3'

    ## Reset the firewall to an empty, but friendly state

    # Flush all chains in FILTER table
    $IPT -t filter -F
    # Delete any user-defined chains in FILTER table
    $IPT -t filter -X
    # Flush all chains in NAT table
    $IPT -t nat -F
    # Delete any user-defined chains in NAT table
    $IPT -t nat -X
    # Flush all chains in MANGLE table
    $IPT -t mangle -F
    # Delete any user-defined chains in MANGLE table
    $IPT -t mangle -X
    # Flush all chains in RAW table
    $IPT -t raw -F
    # Delete any user-defined chains in RAW table
    $IPT -t mangle -X

    ...

    $IPT -t filter -P INPUT DROP
    $IPT -t filter -P OUTPUT DROP
    $IPT -t filter -P FORWARD DROP

    ...

    # Create logging chains
    $IPT -t filter -N input_log
    $IPT -t filter -N output_log
    $IPT -t filter -N forward_log

    # Set some logging targets for DROPPED packets
    $IPT -t filter -A input_log -j LOG --log-level notice --logprefix "input drop: "
    $IPT -t filter -A output_log -j LOG --log-level notice --logprefix "output drop: "
    $IPT -t filter -A forward_log -j LOG --log-level notice --logprefix "forward drop: " echo "Added logging"

    # Return from the logging chain to the built-in chain
    $IPT -t filter -A input_log -j RETURN
    $IPT -t filter -A output_log -j RETURN
    $IPT -t filter -A forward_log -j RETURN

    # These rules must be inserted at the end of the built-in
    # chain to log packets that will be dropped by the default
    # DROP policy
    $IPT -t filter -A INPUT -j input_log
    $IPT -t filter -A OUTPUT -j output_log
    $IPT -t filter -A FORWARD -j forward_log
  6. 查看实时日志

    1
    sudo tail -f /var/log/kern.log
  7. enable all type of traffic to and from the loopback interface

    1
    2
    3
    # loopback
    $IPT -A INPUT -i lo -j ACCEPT
    $IPT -A OUTPUT -o lo -j ACCEPT
  8. 允许本机 Ping 其他接口

    1
    2
    3
    # ping
    $IPT -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
    $IPT -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
  9. 允许 Ping 本机

    1
    2
    $IPT -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
    $IPT -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
  10. 允许 Server 在 /etc/network/interfaces 中配置的 DNS 服务器的帮助下进行域名查找

    1
    2
    3
    $ grep domain /etc/services
    domain 53/tcp # Domain Name Server
    domain 53/udp
    1
    2
    3
    # DNS
    $IPT -A INPUT -p udp --sport 53 -j ACCEPT
    $IPT -A OUTPUT -p udp --dport 53 -j ACCEPT
    1
    2
    3
    4
    5
    6
    $ host www.bing.com
    www.bing.com is an alias for a-0001.a-afdentry.net.trafficmanager.net.
    a-0001.a-afdentry.net.trafficmanager.net is an alias for cn-bing-com.cn.a-0001.a-msedge.net.
    cn-bing-com.cn.a-0001.a-msedge.net is an alias for china.bing123.com.
    china.bing123.com has address 202.89.233.100
    china.bing123.com has address 202.89.233.101
  11. 在 Server 启用 TCP 并能访问外部网站

    1
    2
    3
    # three-way handshake
    $IPT -A INPUT -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    $IPT -A OUTPUT -p tcp -m conntrack --ctstate NEW,ESTABLISHED -j ACCEP
  12. 启用 SSH

    1
    2
    3
    4
    5
    6
    7
    8
    # SSH
    # 允许 host 使用 SSH 连接 Server
    # NAT 接口为 enp0s9,IP 地址为 10.0.98.100
    $IPT -A INPUT -p tcp -s 10.0.98.0\/24 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
    # 允许 client 使用 SSH 连接 Server
    # enp0s3 为 host-only interface,IP 地址为 192.168.60.100
    $IPT -A INPUT -p tcp -s 192.168.60.0\/24 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
    $IPT -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
  13. 允许访问 Server 上的 HTTPS 网页

    1
    2
    3
    # HTTPS
    $IPT -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
    $IPT -A OUTPUT -p tcp --sport 443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
  14. 允许 Client 通过 Server 进行上网

    1
    2
    # 编辑 Client 的 /etc/network/interfaces 并增加
    gateway 192.168.60.100
    1
    2
    # 编辑 Client 的 /etc/resolv.conf 并增加 DNS 服务器
    nameserver 10.0.98.3
    1
    2
    3
    # 在 Server 上启用 IP forwarding
    $ sudo sysctl -w net.ipv4.ip_forward=1
    $ sudo sysctl -p
    1
    2
    3
    # iptables 启用 packet forwarding
    $IPT -t filter -A FORWARD -i $HIF -j ACCEPT
    $IPT -t filter -A FORWARD -i $NIF -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    1
    2
    # 在 NAT 接口上启用 SNAT
    $IPT -t nat -A POSTROUTING -j SNAT -o $NIF --to $NIP

参考