Есть две проблемы (и на самом деле не -задал 3-й вопрос, который я рассмотрю простым, если не лучшим решением, на всякий случай, чтобы быть тщательным):
Локально инициированные пакеты не пересылаются (не маршрутизируются ). Таким образом, эти пакеты никогда не видят цепочку nat/PREROUTING
. Взгляните на Поток пакетов в Netfilter и General Networking , чтобы получить представление о том, что происходит во время жизни пакета в ядре. Локальные пакеты приходят из "локального процесса".
Таким образом, в дополнение к правилу nat/PREROUTING
выполняется DNAT
для пакетов, прибывающих "извне", что должно выглядеть как:
iptables -t nat -I PREROUTING -i eno1 -p tcp --dport 8443 -j DNAT --to-destination 172.17.0.2:8443
Вы также должны использовать цепочку nat/OUTPUT
. На выходе его синтаксис допускает только исходящие интерфейсы, поэтому он изменен следующим образом:
iptables -t nat -I OUTPUT -o lo -p tcp --dport 8443 -j DNAT --to-destination 172.17.0.2:8443
Исходный пакет, а затем поток будут фактически перенаправлены на другой интерфейс (Я подозреваю, что "проверка перенаправления" на схеме предыдущей ссылки может быть размещена неправильно ).
Это будет работать с любым IP-адресом, принадлежащим хосту (, т.е. :172.16.214.45 и 172.17.0.1 ), кроме...
lo
Ядро Linux имеет специальные настройки, запрещающие маршрутизацию любого IP-адреса в диапазоне 127.0.0.0/8 куда-либо, кроме интерфейса lo
, и отбрасывает любой такой пакет как марсианский источник при «попытке» использовать другой интерфейс, и правильно :удаленная система (даже если это контейнер )не примет входящий пакет с источником 127.0.0.1 и пунктом назначения 172.17.0.2 хотя бы потому, что не будет знать, куда на него ответить.
Таким образом,SNAT
(или простойMASQUERADE
)к пакету в дополнение к DNAT
также необходимо сделать, на этот раз в цепочке nat/POSTROUTING
, которая проходится (см. предыдущую схему):
iptables -t nat -I POSTROUTING -s 127.0.0.1 -d 172.17.0.2 -j MASQUERADE
Этого еще недостаточно :как следует из названия, nat/POSTROUTING
происходит после маршрутизации (на самом деле проверка перемаршрутизации происходит после DNAT
), и пакет уже был отброшен как марсианский источник.
В особых случаях, таких как этот, можно переопределить ограничение локальной сети с помощью переключателя интерфейса -route_localnet
:
echo 1 > /proc/sys/net/ipv4/conf/docker0/route_localnet
Теперь стек маршрутизации пропускает пакеты с источником 127.0.0.1, а их источник корректируется на 172.17.0.1 по предыдущему правилу перед выходом по виртуальному проводу в контейнер :это работает.
Вам действительно следует избегать всего, что требует этого второго случая, потому что это ненужная сложность :использование IP-адреса, принадлежащего хосту, а не 127.0.0.1, должно быть достаточно для любого теста. Кроме того, если интерфейс docker0
будет удален и создан заново, настройка route_localnet
будет потеряна, и было бы неразумно устанавливать ее по умолчанию.
Не задано, но если вы добавите сюда вторую систему (контейнер )в той же локальной сети, возникнут проблемы с локальной сетью -на -хост -на -тот же -перенаправления локальной сети (, если только Docker уже не обрабатывает это на сетевом уровне ).
Правило nat/PREROUTING
, которое я написал в начале ответа, обрабатывает только интерфейс eno1
. Была причина, по которой я добавил это -i eno1
ограничение :без него, если другой контейнер в сети 172.17.0.0/16 попытается подключиться, например, к 172.16.214.45 :8443 (или к 172.17.0.1 :8443 ), пакет будет перенаправлен на 172.17.0.2. Затем 172.17.0.2 ответит напрямую источнику :другому контейнеру и полностью обойдет хост и его правила NAT.Этот контейнер увидит ответный пакет, пришедший из источника, о котором он не знает, и отклонит его (с помощьюTCP RST
). Так что лучше не справляться с этим вообще, чем справляться плохо. Docker, вероятно, предоставляет определенные способы прямого разрешения службы на IP/порт другого контейнера без участия хоста.
В любом случае, если это необходимо, существует несколько способов преодолеть это, часто с компромиссом, от простого NAT (, который теряет исходный IP-адрес или должен транслировать его в фиктивную сеть, для целей регистрации )до сложного моста и /или настройки маршрутизатора, способные перехватывать связь по локальной сети.
Вот простое решение, где источником является SNAT -ed, использующий NETMAP
, для фиктивной сети 10.17.0.0/16. Простое предварительное условие :10.17.0.0/16, вероятно, должно быть направлено на хост (, даже если он на самом деле не используется ), либо по маршруту по умолчанию (, вероятно, в случае ), определенному маршруту, либо с помощью хост, имеющий IP-адрес в этой фиктивной сети для этой цели. Пакеты с этим IP-адресом будут существовать только внутри сети docker0
.
После удаления -i eno1
из правила PREROUTING
выше добавьте это новое правило:
iptables -t nat -I POSTROUTING -s 172.17.0.0/16 -d 172.17.0.0/16 -j NETMAP --to 10.17.0.0/16
Теперь перенаправление из локальной сети в ту же локальную сеть будет работать, а журналы контейнера назначения будут показывать исходные IP-адреса в диапазоне 10.17.0.0/16.
Конечно, следует также избегать ситуаций, связанных со шпильками.
Вы просто пытаетесь переименовать файлы, чтобы сжать все цепочки пробелов в их именах до 1? Это было бы (непроверенным):
#!/usr/bin/env bash
shopt -s extglob
while IFS= read -rd '' old; do
new="${old// *( )/ }"
mv -- "$old" "$new"
done < <(find "$1" -name '* *.*' -print0)
Нет причин использовать awk или другие команды.
Я нашел :здесь
awk -v FS=' ' 'NR==FNR{ s[$1]=$0; next } {print "mv "s[$1]" " $0}' l1 l2