В предыдущей статье я расписал, как можно узнать IP клиента. Но в некоторых случаях Apache Tomcat находится за nginx и способ, описанный в той статье, будет возвращать локальный IP сервера nginx. Чтобы можно было узнать реальный IP клиента, необходимо немного поправить способ получения этого IP и конфигурационный файл nginx.
В файле настроек nginx /etc/nginx/sites-available/default при описании перенаправления на Apache Tomcat нужно добавить следующие строчки:
1 2 3 4 5 6 7 8 |
location / { ... proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; ... } |
Директива proxy_set_header здесь позволяет добавить/изменить заголовки HTTP-запроса для прокси-соединения (соединения, которое будет между nginx и Apache Tomcat).
Описание используемых HTTP-заголовков:
Host — доменное имя для сервера.
X-Real-IP — IP клиента. На сколько я знаю, в стандарте такого заголовка нет.
X-Forwarded-For — IP клиента и список IP всех прокси-серверов, через которых прошёл запрос, разделённые запятыми. IP последнего прокси-сервера не включается в этот список, так как с него отправляется последний запрос. На сколько я знаю, этот заголовок тоже не описан в стандартах, но является стандартом де-факто.
X-Forwarded-Proto — Для определения исходного протокола (например HTTPS или HTTP). В стандартах не описан, но является стандартом де-факто.
Теперь в нашем Java-коде мы можем определить реальный IP клиента посмотрев сперва заголовок X-Forwarded-For и затем сам getRemoteAddr:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * @param request * @return IP-адрес клиента. */ public static String getClientIp(HttpServletRequest request) { String clientIp = request.getHeader("X-FORWARDED-FOR"); if (clientIp == null) { clientIp = request.getRemoteAddr(); } else { clientIp = clientIp.split(",")[0].trim(); } return clientIp; } |