1. Введение
Прокси-серверы действуют как посредники между клиентскими приложениями и другими серверами. В корпоративных условиях мы часто используем их, чтобы помочь обеспечить контроль над контентом, который потребляют пользователи, обычно за пределами сети.
В этом уроке мы рассмотрим, как подключаться через прокси-серверы в Java .
Во-первых, мы рассмотрим более старый, более глобальный подход, который распространяется на всю JVM и настраивается с помощью системных свойств. После этого мы познакомимся с классом Proxy
, который дает нам больше контроля, позволяя настраивать конфигурацию для каждого соединения.
2. Настройка
Для запуска примеров в этой статье нам потребуется доступ к прокси-серверу. Squid — популярная реализация, доступная для большинства операционных систем. Конфигурации Squid по умолчанию будет достаточно для большинства наших примеров.
3. Использование глобальной настройки
Java предоставляет набор системных свойств, которые можно использовать для настройки поведения всей JVM. Такой подход «один размер подходит всем» зачастую проще всего реализовать, если он подходит для конкретного случая использования.
Мы можем установить необходимые свойства из командной строки при вызове JVM . В качестве альтернативы мы также можем установить их, вызвав System.setProperty()
во время выполнения .
3.1. Доступные свойства системы
Java предоставляет обработчики прокси для протоколов HTTP, HTTPS, FTP и SOCKS. Прокси может быть определен для каждого обработчика как имя хоста и номер порта:
http.proxyHost
— имя хоста прокси-сервера HTTP.http.proxyPort
— номер порта прокси-сервера HTTP — свойство является необязательным и по умолчанию равно 80, если не указаноhttp.nonProxyHosts
— разделенный вертикальной чертой («|») список шаблонов хостов, для которых следует обходить прокси-сервер — применяется как для обработчиков HTTP, так и для HTTPS, если установленоsocksProxyHost
— имя хоста прокси-сервера SOCKS.socksProxyPort
— номер порта прокси-сервера SOCKS.
При указании nonProxyHosts
шаблоны узлов могут начинаться или заканчиваться подстановочным знаком («*»). Может быть необходимо экранировать «|» разделитель на платформах Windows. Исчерпывающий список всех доступных системных свойств, связанных с прокси, можно найти в официальной документации Oracle по Java по сетевым свойствам .
3.2. Установить через аргументы командной строки
Мы можем определить прокси в командной строке, передав настройки как системные свойства:
java -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=3128 com.foreach.networking.proxies.CommandLineProxyDemo
При запуске процесса таким образом мы можем просто использовать openConnection()
для URL
-адреса без какой-либо дополнительной работы:
URL url = new URL(RESOURCE_URL);
URLConnection con = url.openConnection();
3.3. Установить с помощью System.setProperty(String, String)
Если мы не можем установить свойства прокси в командной строке, мы можем установить их с помощью вызовов System.setProperty()
в нашей программе:
System.setProperty("http.proxyHost", "127.0.0.1");
System.setProperty("http.proxyPort", "3128");
URL url = new URL(RESOURCE_URL);
URLConnection con = url.openConnection();
// ...
Если позже мы отключим соответствующие системные свойства вручную, то прокси больше не будет использоваться:
System.setProperty("http.proxyHost", null);
3.4. Ограничения глобальной конфигурации
Хотя использование глобальной конфигурации с системными свойствами легко реализовать, этот подход ограничивает наши возможности, поскольку настройки применяются ко всей JVM . По этой причине настройки, определенные для конкретного протокола, активны в течение всего срока службы JVM или до тех пор, пока они не будут отменены.
Чтобы обойти это ограничение, может возникнуть соблазн включать и выключать настройки по мере необходимости. Чтобы сделать это безопасно в многопоточной программе, необходимо было бы ввести меры для защиты от проблем параллелизма.
В качестве альтернативы Proxy API обеспечивает более детальный контроль над конфигурацией прокси.
4. Использование прокси
- API
Класс Proxy
дает нам гибкий способ настройки прокси для каждого соединения. Если существуют какие-либо существующие параметры прокси-сервера для всей JVM, параметры прокси-сервера на основе подключения с использованием класса Proxy
переопределяют их.
Существует три типа прокси, которые мы можем определить с помощью Proxy.Type
:
- HTTP — прокси, использующий протокол HTTP
- SOCKS — прокси по протоколу SOCKS
- ПРЯМОЕ — явно настроенное прямое соединение без прокси
4.1. Использование HTTP-прокси
Чтобы использовать HTTP-прокси, мы сначала обертываем экземпляр SocketAddress
с помощью Proxy
и типа Proxy.Type.HTTP
. Далее мы просто передаем экземпляр Proxy в
URLConnection.openConnection():
URL weburl = new URL(URL_STRING);
Proxy webProxy
= new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 3128));
HttpURLConnection webProxyConnection
= (HttpURLConnection) weburl.openConnection(webProxy);
Проще говоря, это означает, что мы будем подключаться к URL_STRING
, но затем маршрутизировать это соединение через прокси-сервер, размещенный по адресу 127.0.0.1:3128
.
4.2. Использование ПРЯМОГО прокси
У нас может возникнуть потребность в прямом подключении к хосту. В этом случае мы можем явно обойти прокси, который может быть настроен глобально, используя статический экземпляр Proxy.NO_PROXY
. Под прикрытием API создает для нас новый экземпляр Proxy
, используя Proxy.Type.DIRECT
в качестве типа :
HttpURLConnection directConnection
= (HttpURLConnection) weburl.openConnection(Proxy.NO_PROXY);
По сути, если нет глобально настроенного прокси, то это то же самое, что и вызов openConnection()
без аргументов.
4.3. Использование SOCKS-прокси
Использование прокси-сервера SOCKS аналогично варианту HTTP при работе с URLConnection.
Мы начинаем с того, что обертываем экземпляр SocketAddress
прокси
-сервером, используя тип Proxy.Type.SOCKS
. После этого мы передаем экземпляр прокси в
URLConnection.openConnection
:
Proxy socksProxy
= new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 1080));
HttpURLConnection socksConnection
= (HttpURLConnection) weburl.openConnection(socksProxy);
Также возможно использовать прокси-сервер SOCKS при подключении к сокету TCP . Во-первых, мы используем экземпляр Proxy
для создания Socket
. После этого мы передаем целевой экземпляр SocketAddress
в Socket.connect()
:
Socket proxySocket = new Socket(socksProxy);
InetSocketAddress socketHost
= new InetSocketAddress(SOCKET_SERVER_HOST, SOCKET_SERVER_PORT);
proxySocket.connect(socketHost);
5. Вывод
В этой статье мы рассмотрели, как работать с прокси-серверами в ядре Java.
Во-первых, мы рассмотрели старый, более глобальный стиль подключения через прокси-серверы с использованием системных свойств. Затем мы увидели, как использовать класс Proxy
, который обеспечивает детальное управление при подключении через прокси-серверы.
Как всегда, весь исходный код, использованный в этой статье, можно найти на GitHub .