Как я могу предотвратить (почти) весь не-VPN-трафик с использованием IPtables к службе Docker?

У меня есть сервер, к которому я хочу быть доступным в общедоступном Интернете только через SSH, но я хочу, чтобы он мог подключаться к VPN, и привязываю сервисы к его интерфейсу VPN.

Я использую Linode для размещения виртуальной машины Ubuntu 16.04.2 LTS, ZeroTier для моего уровня VPN и Docker в режиме Swarm (только с одним узлом) для сервисов.

] Выполнение ifconfig -a на виртуальной машине возвращает следующее (общедоступные IP-адреса отредактированы для конфиденциальности):

docker0   Link encap:Ethernet  HWaddr 02:42:f7:e7:e6:1e
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

docker_gwbridge Link encap:Ethernet  HWaddr 02:42:ad:82:56:0f
          inet addr:172.18.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:adff:fe82:560f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6083 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16927 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:6364682 (6.3 MB)  TX bytes:49725061 (49.7 MB)

eth0      Link encap:Ethernet  HWaddr f2:3c:91:a7:c3:ac
          inet addr:<REDACTED>  Bcast:<REDACTED>  Mask:255.255.255.0
          inet6 addr: <REDACTED>/64 Scope:Global
          inet6 addr: <REDACTED>/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:94675 errors:0 dropped:0 overruns:0 frame:0
          TX packets:47778 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:59390529 (59.3 MB)  TX bytes:14765979 (14.7 MB)

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:54171 errors:0 dropped:0 overruns:0 frame:0
          TX packets:54171 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:6243573 (6.2 MB)  TX bytes:6243573 (6.2 MB)

veth8323309 Link encap:Ethernet  HWaddr 82:b3:ec:d8:8c:9b
          inet6 addr: fe80::80b3:ecff:fed8:8c9b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:15 errors:0 dropped:0 overruns:0 frame:0
          TX packets:538 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1248 (1.2 KB)  TX bytes:22932 (22.9 KB)

veth602daf7 Link encap:Ethernet  HWaddr 82:7e:cf:b3:cb:a4
          inet6 addr: fe80::807e:cfff:feb3:cba4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3065 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11154 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:6187902 (6.1 MB)  TX bytes:794193 (794.1 KB)

zt0       Link encap:Ethernet  HWaddr 42:08:c2:e8:fc:93
          inet addr:192.168.196.106  Bcast:192.168.196.255  Mask:255.255.255.0
          inet6 addr: fe80::4008:c2ff:fee8:fc93/64 Scope:Link
          inet6 addr: fc7b:7a95:194:6f84:bf9a::1/40 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:2800  Metric:1
          RX packets:442 errors:0 dropped:0 overruns:0 frame:0
          TX packets:279 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:52165 (52.1 KB)  TX bytes:46603 (46.6 KB)

Мой файл создания Docker выглядит следующим образом:

version: "3"
services:
  jenkins:
    image: jenkins/jenkins:lts
    ports:
      - "80:8080"
    volumes:
      - jenkins_home:/var/jenkins_home
    deploy:
      replicas: 1
volumes:
  jenkins_home:

Однако я не могу получить правила iptables право. Я ожидал, что смогу сделать это:

# Allow established connections, including outbound connections this server initiated, to continue to receive replies
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Allow SSH on eth0
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT

# Allow UDP 9993 on eth0 (required for ZeroTier)
iptables -A INPUT -i eth0 -p udp --dport 9993 -j ACCEPT
iptables -A OUTPUT -p udp --dport 9993 -j ACCEPT

# Reject everything that hasn't already been accepted (rules are applied in order)
iptables -A INPUT -i eth0 -j REJECT

Однако, когда я развертываю и запускаю свою службу Docker Swarm, я получаю доступ к службе через адрес на eth0 с удаленного хоста, не подключенного к VPN, из адрес VPN на zt0 от удаленного хоста, который находится в VPN, но не , а не с localhost на самой виртуальной машине.

Что я здесь делаю не так? Как я могу получить правила iptables, которые предотвратят трафик из общедоступного Интернета, но разрешат его только из ZeroTier VPN?

0
задан 21 September 2017 в 18:23
1 ответ

После дополнительных исследований я обнаружил свою проблему.

Суть в том, что Docker использует свои собственные цепочки для пересылки пакетов . Он изменит цепочки DOCKER и DOCKER-INGRESS при запуске демона Docker и при развертывании новых контейнеров, но не будет изменять цепочку с именем DOCKER-USER , который предназначен для определенных администратором правил брандмауэра того типа, который я хочу применить.

Вооружившись этими знаниями, я смог получить то, что хотел, с помощью следующих правил iptables:

#!/bin/sh

set -e
set -u

# REMINDER: DROP vs REJECT:
# a DROP operation blackholes the packet, likely causing client to wait dozens of seconds for a timeout
# a REJECT operation sends an ICMP response letting the client know the packet was rejected

# REMINDER: IPv4 vs IPv6
# `iptables` only applies IPv4 rules; `ip6tables` only lapplies IPv6 rules.

## System firewall rules

# Allow any established sessions from our container host - including replies to outbound queries - to receive traffic
iptables --append INPUT -m conntrack --ctstate ESTABLISHED,RELATED --jump ACCEPT
ip6tables --append INPUT -m conntrack --ctstate ESTABLISHED,RELATED --jump ACCEPT

# Allow SSH on eth0
iptables --append INPUT --in-interface eth0 --protocol tcp --dport 22 --jump ACCEPT
ip6tables --append INPUT --in-interface eth0 --protocol tcp --dport 22 --jump ACCEPT

# Allow UDP 9993 on eth0 (required for ZeroTier)
iptables --append INPUT --in-interface eth0 --protocol udp --dport 9993 --jump ACCEPT
ip6tables --append INPUT --in-interface eth0 --protocol udp --dport 9993 --jump ACCEPT
iptables --append OUTPUT --protocol udp --dport 9993 --jump ACCEPT
ip6tables --append OUTPUT --protocol udp --dport 9993 --jump ACCEPT

# Reject everything to eth0 that hasn't been accepted by a previous rule
iptables --append INPUT --in-interface eth0 --jump REJECT
ip6tables --append INPUT --in-interface eth0 --jump REJECT

## Docker firewall rules

# NOTE: Docker does not enable IPv6 networking by default, so there is no need for `ip6tables` here
# <https://docs.docker.com/engine/userguide/networking/default_network/ipv6/>

# NOTE: Docker promises not to modify the DOCKER-USER chain so that we can do this type of filtering

# Create the chain we need if Docker hasn't done so already
iptables --new DOCKER-USER 2>/dev/null || true

# Allow any established sessions from our containers - including replies to outbound queries - to receive traffic
iptables --append DOCKER-USER --match conntrack --ctstate ESTABLISHED,RELATED --jump ACCEPT

# Reject packets that would be forwarded to Docker when they come in over eth0 (the public interface)
iptables --append DOCKER-USER --in-interface eth0 ---jump REJECT

Обратите внимание, что некоторые из этих правил не относятся к Docker, но существуют для отклонения пакетов, предназначенных для моего сервера Docker - я хочу принимать только пакеты VPN и SSH на сам сервер.

0
ответ дан 5 December 2019 в 07:26

Теги

Похожие вопросы