Отказ от подключения от хоста

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

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

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

 BerggreenDK12 июл. 2009 г., 17:25
Не могли бы вы добавить теги для какого языка вы используете? Я не эксперт по сокетам, но у меня есть некоторый опыт в ActionScript и C # /. NET
 Chris Arguin12 июл. 2009 г., 18:12
И ОС также ... Windows против Unix может иметь большое значение здесь. Я не думаю, что есть портативное решение, но я могу ошибаться.

Ответы на вопрос(4)

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

TCP Wrapper стал очень распространенным на UNIX-подобных платформах. Да, соединение проверено толькоafter 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 совсем.

Решение Вопроса

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

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

 Calmarius13 июл. 2009 г., 13:05
Так что, если я слушаю через порт, соединение будет установлено в фоновом режиме, независимо от того, хочу я или нет?
 13 июл. 2009 г., 15:44
Вызов listen () сообщает ОС, что вы хотите любое соединение, которое может быть успешно установлено на вашем порту. Поэтому, если вы не отфильтруете пакет на более низком уровне (правило брандмауэра), он будет отвечать на любой запрос на подключение к этому порту. Если вы решите, что вам не нужно определенное соединение, вы всегда можете закрыть () его, что будут делать некоторые другие ответы здесь.

НаwindowsПосмотрите на WSAAccept, может быть, это то, что вам нужно:

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

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

Заlinux решение взглянуть на: GNU Common C ++ - класс TCPSocket, он имеет методы onAccept () и reject ().

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

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

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

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

 12 июл. 2009 г., 21:19
То, что вы хотите, более элегантно, однако при разработке нам нужен баланс между характеристиками благодарности и затраченным на это временем и деньгами. Как в XP сказано - делайте это проще всего, позже вы можете прийти и рефакторинг.
 Calmarius12 июл. 2009 г., 21:04
Если другого решения не существует, я немедленно приму и закрою розетку, как, например, открыв дверь, чтобы спросить, кто вы, и закрою ее, если вас забанят ... Но я вообще не хочу открывать эту дверь. Я хочу, чтобы забаненные пользователи думали, что сервер просто выключен.

Ваш ответ на вопрос