Прослушивание сокетов в IP-подсети в C/Unix

Я пытаюсь написать программу сокета сервер-клиент на C. Цель состоит в том, чтобы сервер прослушивал определенный порт, но через диапазон IP-адресов, принадлежащих в одну и ту же IP-подсеть. Эта IP-подсеть является частью диапазона 127.x.x.x (конечно, не 127.0.0.1).

Пара замечаний:

  • Это сокет на основе потока, а не сокет дейтаграммы.
  • Это не широковещательный адрес.
  • Реализация на C/C++ только на платформе Unix/Linux

Я не хочу открывать несколько сокетов на сервере для каждого IP-адреса в диапазоне. Это не масштабируется.

Любая помощь будет идеально оценена. Это вообще осуществимо?


person viv    schedule 25.06.2012    source источник
comment
AFAIK в Windows это невозможно.   -  person Kirill Kobelev    schedule 25.06.2012
comment
Это для Unix/Linux. Надо было упомянуть об этом в моем списке, но я думал, что это уже есть в заголовке.   -  person viv    schedule 25.06.2012


Ответы (3)


Вы можете привязываться только к одному адресу на одном сокете. Почему вы не можете привязаться к INADDR_ANY и просто отклонить любые пакеты, не привязанные к вашим целевым IP-адресам? В качестве альтернативы вы можете привязаться к произвольному порту и использовать магию уровня ОС (например, iptables, bpf) для перенаправления пакетов, предназначенных для этих комбинаций IP/порта, в ваш сокет.

person Andy Ross    schedule 25.06.2012
comment
Спасибо за это предложение. Не могли бы вы подробнее рассказать об отклонении любых пакетов, не связанных с вашими целевыми IP-адресами? Нужно ли это делать в моем коде, проверяя заголовки каждого входящего пакета? - person viv; 25.06.2012
comment
@Vivek: Нет, потому что это сокет на основе потока - вам просто нужно вызвать getpeername() для сокета, возвращенного accept(), и убедиться, что это один из адресов, которые вы хотите использовать. - person caf; 25.06.2012
comment
Извините, я неправильно понял и подумал, что вы используете UDP. caf предлагает правильный API для TCP-сокета. - person Andy Ross; 25.06.2012

API сокетов не позволяет привязываться к подсети — вы можете привязываться к одному IP-адресу или к любому IP-адресу. Вы можете прослушивать все входящие подключения и отклонять те, которые неприменимы. Если вам нужно разделить соединения между процессами на одном сервере, используйте один прослушивающий сокет и передавайте входящие соединения рабочим процессам.

person tylerl    schedule 25.06.2012
comment
Спасибо. В этом случае нет задействованных рабочих процессов. Требование вытекает из наложенного ограничения безопасности, согласно которому сокет должен открываться только на определенных IP-адресах. Фактический IP-адрес является динамическим по своей природе. Поэтому вместо того, чтобы динамически пытаться определить, на каком IP-адресе открывать сокет, я проверял, будет ли работать подход на основе подсети. - person viv; 25.06.2012
comment
Если это действительно ограничение безопасности, то, возможно, вашей команде следует пересмотреть это решение и попытаться выяснить, какой именно вид безопасности, по их мнению, он покупает. - person tylerl; 26.06.2012

Вы можете использовать брандмауэр, чтобы предотвратить подключение кого-либо из-за пределов нужной подсети (это на уровне операционной системы). Вы можете перевести сокет в неразборчивый режим и принимать все соединения на данном интерфейсе. Я не знаю, можете ли вы сделать и то, и другое (иметь сокет в неразборчивом режиме и запускать на нем iptables). По сути, это похоже на создание анализатора пакетов, который прослушивает только один порт.

person ipaul    schedule 08.07.2012