Безопасность Coreos

Я играю с coreos и digitalocean и хочу разрешить внутреннюю связь между моими контейнерами.

Я настроил частную сеть для всех хостов, и теперь я хотел бы убедиться, что некоторые контейнеры открывают порты только для локального хоста и внутреннего интерфейса.

Я изучил множество вариантов для этого, но ни один из них не кажется удовлетворительным:

  • Using the '-p', I can ensure docker binds to the local interface, but this has two downsides:
    • I can't easily test services by SSHing in, because that traffic originates from localhost
    • Мне нужно написать несколько хакерских сценариев оболочки, чтобы запустить мои службы, чтобы ввести адрес машины, на которой работает контейнер.
  • Я пытался использовать фланель, но это не делает трафик приватным (или я не правильно настроил)
  • Я рассматривал возможность использования iptables в контейнерах для предотвращения внешнего доступа, но это не кажется безопасным.
  • I tried using iptables on the coreos hosts, but ... it's tricky, and I couldn't get it working.

Итак, каков наилучший подход, и я потрачу время на то, чтобы заставить его работать.

В целом, я думаю, мне нужно найти что-то, что я могу:

  • Надежное развертывание на всех хостах
  • Что-то достаточно гибкое в будущем
  • Что-то, что позволяет использовать «пограничные машины», доступные из более широкого Интернета.

Решение

Я расскажу, как я решил это. Спасибо larsks за помощь. В конце концов, их подход был правильным. Это сложно на coreos, потому что не существует действительно стабильных адресов, как предполагает larsks. Весь смысл coreos в том, чтобы можно было забыть об IP-адресах.

Я решил эту проблему, найдя неплохой способ ввести IP-адрес в команду в служебном файле. Сложность в том, что он не поддерживает многие функции оболочки, которые я ожидал. Что я хотел сделать, так это присвоить IP-адрес машины переменной, а затем внедрить ее в команду:

ip=$(ifconfig eth1 | grep -o 'inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*');
/usr/bin/docker run -p $ip:7000:7000 ...

Но, как уже упоминалось, это не работает. Так что делать? Получите оболочку!

ExecStart=/usr/bin/sh -c "\
     export ip=$(ifconfig eth1 | grep -o 'inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*');\
     echo $ip;\
     /usr/bin/docker run -p $ip:7000:7000"

По пути я столкнулся с несколькими проблемами.

  1. Я почти уверен, что в этой команде нет новых строк, поэтому мне пришлось добавить ';' персонажи
  2. когда вы тестируете приведенную выше команду bash -c в оболочке, она будет иметь совсем другие эффекты, чем когда это делает systemd. В оболочке вам нужно экранировать символы '$', а в конфигурационных файлах systemd этого делать не нужно.
  3. Я включил эхо, чтобы увидеть, что команда думает об ip.
  4. Когда я все это делал, я фактически вставил небольшой веб-сервер в образ докера, чтобы я мог просто протестировать его с помощью curl.

Недостатком этого подхода является то, что он привязан к тому, как работает ifconfig, и ipv4. На самом деле этот подход не работает на моем ноутбуке с Linux Mint, где ifconfig выдает вывод в другом формате. Важным уроком здесь является вывод данных в yaml или json, чтобы инструменты оболочки json могли получить к ним более легкий доступ.


person riri    schedule 21.03.2015    source источник


Ответы (2)


Я настроил частную сеть для всех хостов, и теперь я хотел бы убедиться, что некоторые контейнеры открывают порты только для локального хоста и внутреннего интерфейса.

Это именно то поведение, которое вы получаете с опцией -p при указании IP-адреса. Допустим, у меня есть хост с двумя внешними интерфейсами, eth0 (с адресом 10.0.0.10) и eth1 (с адресом 192.168.0.10), и мост docker0 по адресу 172.17.42.1/16.

Если я запускаю контейнер следующим образом:

docker run -p 192.168.0.10:80:80 -d larsks/mini-httpd

Это запустит контейнер, доступный через интерфейс eth1 по адресу 192.168.0.10, порт 80. Эта служба также доступна -- с хоста, на котором расположен контейнер -- по адресу, назначенному контейнер в сети docker0. Это будет что-то вроде 172.17.0.39, порт 80.

Кажется, это соответствует вашим целям:

  • Порт контейнера предоставляется через «частный» интерфейс eth1.
  • Порт контейнера доступен с хоста.

Я не могу легко протестировать службы с помощью SSH, потому что этот трафик исходит от локального хоста.

Если бы вы запускали ssh внутри контейнера, вы бы подключились к нему по ssh по «внутреннему» адресу, назначенному Docker. Но если вы используете ssh внутри своих контейнеров, вы можете рассмотреть возможность не делать этого и вместо этого полагаться на такие инструменты, как docker exec.

Мне нужно написать несколько хакерских сценариев оболочки, чтобы запустить мои службы, чтобы ввести адрес машины, на которой работает контейнер.

С этим решением нет необходимости вводить IP-адрес машины в контейнер.

person larsks    schedule 21.03.2015

Вместо grep-ping IP-адреса вы можете использовать файлы среды для получения IP-адреса (как общедоступного, так и частного) хоста, на который запланирована служба. Это позволяет простым способом привязать порты контейнера к общедоступным или частным портам.

Вот так:

[Service]
EnvironmentFile=/etc/environment
ExecStart=/usr/bin/docker run --name myservice -p \
    ${COREOS_PUBLIC_IPV4}:80:80 \
    ${COREOS_PRIVATE_IPV4}:3306:3306 \
    ubuntu /bin/bash
person yp28    schedule 11.08.2015
comment
Это хорошая функция, спасибо, что показали ее мне :). - person riri; 14.08.2015