Существует ли потребность в повторении параметров правила в iptables?

Полная история «Это зависит от того, что вы имеете в виду». Если вы хотите прослушать тот же IP-адрес и порт в качестве существующей программы, которую у вас нет контроля, то, как указывали другие, вы можете быть удачи. Однако, если вы:

  • может прослушать другой IP-адрес, или
  • есть контроль над исходным приложением

, тогда вас могут быть заинтересованы в остальной части этого поста.

Один порт, другой адрес интернет-протокола (IP)

, когда программа использует системный вызов , чтобы назначить адрес в сокет, что Adddress (в случае af_inet Разъем) Определяет как порт, так и IP-адрес. Таким образом, два адреса с одним и тем же портом, но разные IP-адреса различны и могут быть назначены отдельно без конфликтов. Например, использование SOCAT Я могу привязать к порту 9000 на IP-адресе для моего интерфейса обратной связи в одной оболочке:

 socat TCP4-LISTEN:9000,bind=127.0.0.1 STDOUT

и связываться с одним и тем же портом, но на моем внешнем IP-адресе в другом:

socat TCP4-LISTEN:9000,bind=10.0.2.15 STDOUT

Оба процесса могут принимать соединения, которые входят в IP-адрес и порт, на которых они слушают. Обратите внимание, однако, что если кто-то слушает на адрес WildCar 0.0.0.0, то вы не можете связываться с более конкретным адресом, поскольку первый процесс связан с каждым IP-адресом в системе.

Один порт, тот же IP

по умолчанию, два процесса не могут связывать два разных файловых дескриптора одинаковым адресом. В Linux, пытаясь сделать это приведет к возвращению EADDDrinuse из Bind (2) :

socat TCP4-LISTEN:9000,bind=127.0.0.1 STDOUT
2014/11/07 00:10:13 socat[21202] E bind(3, {AF=2 127.0.0.1:9000}, 16): Address already in use

Учитывая ваш вопрос и следствие, я догадаюсь, что у вас нет большого контроля над программой, использующей в настоящее время Ваш желаемый порт. Если вы это сделали, можно использовать один процесс, чтобы иметь установленное соединение на порту + iPaddress, а другой прослушивает один и тот же адрес. Например, многие серверные приложения делают следующее:

  • имеют основной процесс BING (), прослушивания () и принять () соединение
  • Вилкой новый процесс для обработки принятого соединения, с основным процессом возвращается попытаться принять () любые новые входящие соединения.

В этом случае вы увидите детский процесс с установленным соединением в порту и родительский процесс с разъемом прослушивания на одном порту.

В очень недавних ядрах Linux можно использовать два совершенно неродных процесса для оба связывания к одному и тому же адресу, используя опцию сокета SO_REUSEPORT. Если процессы устанавливают опцию SO_REUSEPORT на розетке, то другие процессы с тем же эффективным UID первого процесса также могут установить опцию SO_REUSEPORT и связываться с тем же адресом.

К сожалению, моя версия Сокат , кажется, есть ошибка, которая делает его трудно дать простой пример TCP; Тем не менее, я предоставил короткий и плохо письменный пример программы ниже. Если вы запустите эту программу в качестве одного и того же пользователя в двух разных оболочках, оба будут связываться () без проблемы:

State    Recv-Q Send-Q  Local Address:Port  Peer Address:Port
LISTEN   0      128     127.0.0.1:9000        *:*     users:(("bind_tcp_reusep",pid=21254,fd=3))
LISTEN   0    128 127.0.0.1:9000           *:*      users:(("bind_tcp_reusep",pid=21253,fd=3))

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

Следующая статья LWN имеет хороший обзор случая использования для этой опции:

http://lwn.net/articles/542629/

Просмотр трафика на установленном соединении

, как упомянул ROBBAT2, Если вы хотите шпионить на существующем трафике TCPDUMP - лучший ставка.

Пример программы SO_REUSEPORT

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


int main() {
  struct sockaddr_in bind_addr;
  struct sockaddr peer_addr;
  int optval = 1;
  int tcp_socket;
  int err;
  int addr_len = sizeof(struct sockaddr);

  memset(&bind_addr, 0, sizeof(struct sockaddr_in));
  memset(&peer_addr, 0, sizeof(struct sockaddr));
  bind_addr.sin_family = AF_INET;
  bind_addr.sin_port = htons(9000);

  if (inet_pton(AF_INET, "127.0.0.1", &(bind_addr.sin_addr)) != 1) {
    perror("inet_pton");
    exit(1);
  }

  tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
  setsockopt(tcp_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
  err = bind(tcp_socket, (const struct sockaddr *)&bind_addr, sizeof(struct sockaddr));

  if (err != 0) {
    perror("bind failed");
    exit(1);
  }

  err = listen(tcp_socket, 256);
  if (err != 0) {
    perror("listen failed");
    exit(1);
  }
  accept(tcp_socket, &peer_addr, &addr_len);
}

0
18.06.2014, 19:59
2 ответа

Если вы хотите избежать этого, то вам нужна новая цепочка:

iptables -N sshgroup1
# or reset with iptables -F sshgroup1 if it already exists
iptables -t filter -A ssh -s 10.10.10.10/32 -m mac \
  --mac-source 10:10:10:10:10:10 -j sshgroup1
iptables -t filter -A sshgroup1 ... -j ACCEPT
iptables -t filter -A sshgroup1 ... -j ACCEPT
2
28.01.2020, 02:28

Если вы хотите разрешить ssh соединения только с двух хостов в вашей локальной сети, то вы должны держать эти правила наверху, чтобы iptables работал быстрее.

iptables -I INPUT -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I INPUT -p tcp --dport 22 -s 10.10.10.10/32 -m mac --mac-source 10:10:10:10:10:10 -j ACCEPT
iptables -I INPUT -p tcp --dport 22 -s 11.11.11.11/32 -m mac --mac-source 11:11:11:11:11:11 -j ACCEPT

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

Эмпирическое правило таково: Постарайтесь избегать повторения правил и минимизируйте уровень совпадения для более быстрой работы

.
1
28.01.2020, 02:28

Теги

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