Очередь FORWARD
используется только тогда, когда сервер является маршрутизатором, для работы с входящими/исходящими пакетами вне вашей сети; она используется для блокирования/принятия маршрутизации пакетов вне вашей сети (на уровне маршрутизатора).
Для управления соединениями на уровне хоста обычно используются очереди INPUT
или OUTPUT
, независимо от того, откуда идут соединения, поскольку они не выполняют маршрутизацию (например, не выполняют переадресацию IP).
Если вы действительно хотите, чтобы группа машин в локальной сети общалась между собой, а не с Интернетом, самый простой подход - не определять шлюз на этих машинах.
Если вы все еще используете iptables
, вы должны использовать очередь INPUT
в вашем скрипте вместо FORWARD
.
Если ваше главное беспокойство - это трафик, идущий в Интернет, хотя я предпочитаю не давать им шлюз для выхода, вы должны использовать очередь OUTPUT
в локальных машинах.
Например:
iptables -A OUTPUT -d 192.168.1.0/24 -j ACCEPT
iptables -A OUTPUT -j DROP
(192.168.1.0/24 -> все машины в сети 192.168.1)
Имейте в виду, что если вы заходите через ssh из другой сети, вы фактически заблокируете себя этими правилами.
Однако, если ваш маршрутизатор - это linux, то может быть достаточно написать правило FORWARD, чтобы заблокировать пару машин от Интернета:
iptables -A FORWARD -s 192.168.1.10 -j DROP
iptables -A FORWARD -s 192.168.1.11 -J DROP
Из man iptables
:
INPUT (для пакетов, предназначенных для локальных сокетов)
FORWARD (для пакетов, направляемых через ящик)
OUTPUT (для локально генерируемых пакетов).
Хотя ssh
обеспечивает два отдельных выходных потока (для stdout и stderr), он подает только один входной поток (stdin). Поэтому вам нужно либо передавать содержимое скрипта и входной файл через разные механизмы.
Например, один через переменную, другой через stdin:
LC_CODE=$(cat local_script.sh) ssh host 'eval "$LC_CODE"' < input
(предполагая, что и ваш ssh
клиент передает LC_*
переменную (SendEnv
в ssh_config
) и ssh_config
sshd
сервер принимает их (AcceptEnv
в sshd_config
))
Или просто передайте содержимое local_script. sh
в качестве кода удаленной оболочки, предполагая, что оболочка входа удаленного пользователя соответствует синтаксису этого скрипта:
ssh host "$(cat local_script.sh)" < input
Или скомпонуйте код и ввод, переданный в stdin ssh
, как в примере:
{
echo '{'; cat local_script.sh; echo '}; exit'
cat input
} | ssh host 'bash -s some arguments'
Здесь используется bash
, потому что bash
позаботится о чтении ввода по одному байту за раз, чтобы не читать дальше этой строки }; exit
, в то время как не все другие оболочки делают это.
Или если sed
на удаленном хосте - GNU sed
:
echo '#END-OF-SCRIPT' | cat local_script.sh - input |
ssh host 'set some arguments; eval "$(sed -u "/^#END-OF-SCRIPT/q")"'
(здесь код оценивается оболочкой входа удаленного пользователя и предполагается, что она Bourne-подобная)
Это работает хорошо и даже позволяет передавать содержимое нескольких файлов в сценарий:
ssh host "bash -s -- '$(cat local_file_1.txt)' '$(cat local_file_2.txt)'" < local_script.sh
Объяснение состоит в том, что ssh
будет выполнить bash -s
при входе в систему с аргументами сценария, являющимися всем, что находится после -
. Таким образом, $ 1
будет содержимым local_file_1.txt
, а $ 2
будет содержимым local_file_2.txt
. bash -s
читает команды из stdin, который поступает из
Вот более элегантное решение с использованием оператора BASH 'здесь -строки' ('<<<')
ssh -t host "/bin/bash <(base64 --decode <<<'$(base64 < script)' )"
ИТ-специалисты берут скрипт, преобразуют его в строку base64, в команде SSH преобразовывают обратно и отдают в bash в виде имени файла канала -.
Для сценария, запускающего интерактивную оболочку, добавьте префикс «имя файла канала» с «--rcfile»
ssh -t host "/bin/bash --rcfile <(base64 --decode <<<'$(base64 < script)' )"
Подробнее...https://antofthy.gitlab.io/info/apps/ssh_remote_commands.txt