Как у меня есть сокет, принимающий соединения только с локального хоста (в Java)? - PullRequest
8 голосов
/ 19 сентября 2008

У меня есть Java-приложение (не работает ни в одном контейнере приложения), которое прослушивает ServerSocket для соединений. Я хотел бы, чтобы он принимал только соединения, которые приходят с localhost. В настоящее время после того, как соединение принято, оно проверяет IP-адрес однорангового узла и отклоняет его, если это не адрес обратной связи, но я знаю, что IP-адреса однорангового узла можно подделать. Поэтому, если возможно, я бы предпочел привязать сокет, который прослушивает только петлевой интерфейс; это возможно?

Я пробовал несколько разных вещей (например, указание "127.0.0.1" в качестве локального адреса при вызове bind ()), но безуспешно. Заранее спасибо.


Спасибо всем за помощь. Мне стыдно признаться, что это была моя ошибка. Наше приложение прослушивает два разных порта, и я привязывал один к интерфейсу обратной связи, но проверял другой. Когда я на самом деле пытаюсь подключиться к правильному порту через telnet, все работает нормально (то есть привязка к «127.0.0.1» делает именно то, что и должна).

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

Ответы [ 5 ]

7 голосов
/ 19 сентября 2008

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

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

3 голосов
/ 19 сентября 2008

Если адрес однорангового узла подделан, то больше ничего нельзя сделать.

Однако подделать 127.0.0.1 нелегко. Вы должны иметь достаточно тупой стек TCP / IP, чтобы принять такой пакет. Спуфер не сможет получить пакеты обратно. В хорошем стеке TCP / IP он не должен иметь возможность угадывать порядковые номера, чтобы не отставать от ожидаемого разговора.

3 голосов
/ 19 сентября 2008

Вы можете, как вы, похоже, делаете, в любом случае принять () соединение, а затем использовать getInetAddress (), чтобы убедиться, что адрес авторизован. Если нет, просто закройте () сокет прямо сейчас. 127.0.0.1 - это , а не адрес, который может быть подделан.

Кроме того, вы можете установить свой собственный менеджер безопасности, у которого будет вызываться метод checkAccept () с адресом и портом удаленного сайта. Это немного сложнее - я никогда не пробовал, так как первое решение всегда было адекватным для меня.

2 голосов
/ 14 февраля 2012
if (socket.getInetAddress().isLoopbackAddress()){
    //Your code goes here
}
1 голос
/ 19 сентября 2008

Когда вы связываете свой ServerSocket, указание localhost должно заставить стек TCP / IP отклонять соединение. Даже если это не работает в вашей системе, localhost не может (хорошо, возможно, если кто-то взломал ваш стек TCP / IP и маршрутизатор шлюза по умолчанию), так как этот адрес не маршрутизируется через физический интерфейс. *

Мне любопытно, почему ваша привязка не удалась, какая у вас ОС, версия Java и т. Д.?

...