Отказ от подключения от хоста - PullRequest
5 голосов
/ 12 июля 2009

Я пишу простое приложение tcp server, используя сокеты. Насколько я знаю, я могу получить IP-адрес и порт клиента после вызова accept ().

Теперь давайте предположим, что у меня есть банлист и я хочу забанить некоторые ip-адреса с моего сервера. Есть ли лучший способ, чем принять соединение и затем сбросить его?

Есть ли способ получить IP-адрес и порт клиента перед тем, как принимать соединение? Если у нас есть accept (), почему у нас нет чего-то вроде отказаться ()? Есть ли способ отклонить соединение или просто проигнорировать попытку соединения с хоста?

Ответы [ 4 ]

13 голосов
/ 13 июля 2009

Реализация TCP обычно завершает трехстороннее рукопожатие TCP, прежде чем пользовательский процесс даже получит доступ к соединению, а функция accept() просто удаляет следующее соединение из очереди. Так что уже слишком поздно делать вид, что сервер не работает. Это работает так же для обычных данных TCP; реализация TCP не ожидает, пока приложение фактически recv() данных, прежде чем отправляется TCP ACK. Это удерживает другую сторону от ненужной повторной передачи пакетов, которые были приняты правильно, и позволяет пропускной способности оставаться высокой, даже если приложение перегружено другими вещами. В случае новых соединений (SYN-пакетов) это также позволяет ядру защитить себя (и приложение) от атак SYN-флуд.

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

4 голосов
/ 12 июля 2009

Вкл. windows : посмотрите на WSAAccept, возможно, это то, что вам нужно:

SOCKET WSAAccept(
  __in     SOCKET s,
  __out    struct sockaddr *addr,
  __inout  LPINT addrlen,
  __in     LPCONDITIONPROC lpfnCondition,
  __in     DWORD dwCallbackData
);

lpfnCondition - адрес необязательной, заданной приложением условной функции, которая примет решение принять / отклонить на основе информации о вызывающем абоненте, переданной в качестве параметров, и при необходимости создаст или присоединит группу сокетов, назначив соответствующее значение параметр результата g этой функции. Если этот параметр равен NULL, то функция условия не вызывается.

Для решения linux посмотрите: GNU Common C ++ - класс TCPSocket, он имеет методы onAccept () и reject ().

virtual bool TCPSocket::onAccept    (       const InetHostAddress &      ia,
        tpport_t    port
    )   [inline, protected, virtual]

Метод для вызова производного класса TCPSocket, который действует как сервер, когда принимается запрос на соединение.

Сервер может реализовать специальные правила протокола, чтобы исключить принятие удаленного сокета путем возврата false. Для этой цели также можно использовать метод Peek.


Однако, вы можете просто закрыть сокет после принятия, если предварительное условие ложно:)

1 голос
/ 13 июля 2009

TCP Wrapper стал очень распространенным на UNIX-подобных платформах. Да, соединение проверяется только после accept; однако, если вы все равно это делаете, вы можете использовать ту же конфигурацию, что и все остальные.

По сути, ваша программа либо запускается с tcpd, либо изменена для непосредственного использования libwrap, например:

#include <tcpd.h>
connfd = accept(listenfd, (struct sockaddr *)&addr, &addrlen);
if (!hosts_ctl("my_program", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), STRING_UNKNOWN)) {
    fprintf(stderr, "Client %s connection disallowed\n", inet_ntoa(addr.sin_addr));
    close(connfd);
}

Затем вы настраиваете /etc/hosts.allow и /etc/hosts.deny в соответствии с вашими желаниями, например,

# /etc/hosts.allow
my_program: 127.0.0.1 10. 192.168.

# /etc/hosts.deny
my_program: ALL

Это приведет к тому, что my_program будет отклонять все попытки подключения с нелокальных адресов, но его можно изменить, не касаясь my_program вообще.

0 голосов
/ 15 июля 2009

Концепция неприятия соединения на основе IP-адреса не будет работать, если вы используете NAT.

...