Краткая версия: как разрешить брандмауэру Yast на сервере Linux разрешить сокетам подключаться к произвольно выбранному (по ОС) порту?
Более длинная версия: у части моей более крупной java-программы есть клиент, подключающийся к серверу с помощью сокетов. Первоначальное соединение выполняется через определенный порт с помощью ConnectionManager, который дает клиенту порт и пароль для подключения. Первоначально я выбирал порт через список портов (все выше 49152), которые я разрешил в брандмауэре. Я заметил, что это новое соединение будет работать случайным образом или отказываться подключаться. Я пришел к выводу, что порты закрыты или используются чем-то другим (пытался отключить брандмауэр, не помогло).
Затем было предложено позволить ОС выбирать порт, не указывая номер порта (используя 0 в соответствии с этим конструктором: JavaDoc). Выбран свободный порт, который отлично работает, когда брандмауэр не работает. Однако брандмауэр блокирует соединение, и время ожидания клиента истекает.
Есть ли способ настроить брандмауэр Yast, чтобы разрешить сокеты, не передерживая сервер? Или я могу / должен указать диапазон номеров портов для java, чтобы выбрать открытый и разрешить эти порты?
ПРИМЕЧАНИЕ. Первоначально я спросил об этом в stackoverflow, и мне было предложено опубликовать здесь. Точно так же и там: StackQuestion.
Соединения TCP могут быть однозначно идентифицированы комбинацией IP-адреса источника, порта источника, IP-адреса назначения и порта назначения. Хорошим примером является веб-сервер - все подключаются к нему через порт 80, но он может поддерживать все эти подключения к одному и тому же порту одновременно, потому что исходный IP-адрес и порт разные для каждого из них.
Я имею в виду, что вы как бы заново изобретаете колесо, открывая отдельный порт прослушивания для каждого подключающегося клиента. Лучшим примером протокола, который ведет себя таким же образом, является FTP в пассивном режиме. Некоторые брандмауэры хорошо с этим справляются только из-за глубокой проверки пакетов - есть код для проверки протокола из-за необходимости открыть высокий порт, но это особые, одноразовые обходные пути для чего-то, что считается "устаревшим" способом решения вещи.
Я бы рекомендовал использовать один порт для всего входящего клиентского трафика, что является гораздо более удобным для брандмауэра способом разрешения клиентских подключений - как на вашей стороне, так и на стороне клиента, где политики брандмауэра на их стороне могут часто блокировать порты с высоким уровнем назначения. Если это не проблема, и вы указали диапазон портов и просто пропустили их все через брандмауэр, просто убедитесь, что никто другой их не прослушивает.
На стороне YaST - вам не нужно этого делать, вы можете напрямую использовать iptables для разрешения / запрета портов. Лучшим подходом было бы открыть правильный порт в Java - либо путем итерации по диапазону и пробовать каждый из них до успеха (привязка вызовет исключение, если кто-то другой использует порт), а затем открыть диапазон в брандмауэре.
Другой подход был бы (это вопрос программиста, лучше для SO :)) использовать пул сокетов, который будет использовать ваше приложение. Eсть хороший пример в Кодерс.