Протокол socks5. Универсальный прокси-сервер. Прием входящих соединений

При работе с прокси очень важно выбрать правильный тип прокси под ваши задачи, чтобы избежать возможных проблем и достигнуть поставленных целей. Чаще всего используются HTTP прокси и Socks5 прокси. Отличия между ними заключаются в степени анонимности, используемому протоколу, способу передачи данных, используемых при работе прокси, а также в некоторых дополнительных функциях. Давайте разберём каждый тип прокси отдельно.

Особенности HTTP прокси

Начнём с HTTP прокси. При своей работе они используют HTTP протокол, который предназначен для посещения сайтов, загрузки и передачи файлов, и при работе с некоторыми программами, которые используют этот протокол для соединения через прокси. Запросы, выполняемые при работе с HTTP прокси серверами, не отправляются напрямую, а используют прокси сервер как посредника, отправляя запросы от его имени.

Также в HTTP протоколе прокси доступно кэширование, что ускоряет загрузку страниц за счёт использования сохранённых файлов, а ещё контроль и фильтрация сетевого трафика, установка ограничения скорости, блокирование нежелательных ресурсов, сбор статистики путём сохранения логов и.т.д.

Прокси этого протокола отличаются по степени анонимности. Выделяются следующие типы HTTP прокси по анонимности:

Прозрачные прокси, которые не маскируют настоящий IP адрес, а также не скрывают факт использование прокси сервера для доступа к ресурсу. Такие прокси используются редко, в основном, чтобы перенаправить пользователя на другой прокси сервер,

Анонимные Прокси. Передают информацию о том, что используются прокси, однако, ваш IP адрес маскируется и подменяется другим IP адресом, предоставляя надёжный уровень безопасности.

Элитные прокси. Скрывают использование прокси, а также надёжно маскируют IP адрес, что делает их самыми безопасными среди HTTP прокси. Сервер, к которому вы попытаетесь получить доступ будет считать, что ваше подключение осуществляется напрямую, без использования прокси сервера.

Отдельно стоит выделить HTTPS прокси, которые используют протокол SSL. Они представляют собой подвид HTTP протокола, который использует защищённое соединение. Сетевой трафик, передаваемый этими прокси надёжно зашифрован, что гарантирует высочайший уровень анонимности. Как правило, такие прокси используются для обеспечения безопасности банковских сетей, в коммерческих организациях для создания безопасных корпоративных сетей и в прочих подключениях, требующих безопасности. Остальные особенности такие же, как и у HTTP протокола.

Особенности Socks5 прокси

Другой протокол, который пользуются популярностью у пользователей - Socks5. Прокси сервера, работающие с этим протоколом изначально анонимны, поскольку они пропускают сетевой трафик в чистом виде, не раскрывая HTTP заголовков. Поэтому сервер, к которому вы пытаетесь получить доступ, не узнает о использовании прокси сервера, а также не получит ваш IP адрес.

Socks5 прокси, поддерживают следующие сетевые протоколы: HTTP, HTTPS, FTP и их особенности: кеширование, SSL соединение, аутентификация. Помимо этого, прокси протокола Socks5 используют UDP и TPC соединения, что расширяет сферу их применения и делает их наиболее функциональными из современных прокси серверов. Изначально Socks5 протокол предназначался для работы с программным обеспечением. По этой причине, большинство программ поддерживает этот протокол для подключения через прокси. А ещё прокси сервера Socks5 имеют приятную особенность, которая позволяет выстраивать цепочки из прокси серверов, что полезно для решения некоторых задач при работе в интернете.

Если сравнивать прокси HTTP и Socks5, то предпочтительней использовать вторые. Так как они анонимней, поддерживают больше функций, а также работают с любыми сайтами и программами, поддерживающие соединение через прокси. вы можете у нас на сайте, оформив заказ в личном кабинете.

Доброго времени суток, дорогие друзья, знакомые, читатели, почитатели и прочие личности. В этой статье, как Вы поняли из заголовка, речь пойдет о том, что такое SOCKS сервер и зачем он вообще нужен.

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

Общее и подробное описание SOCKS

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

Он передает данные, полученные от первого клиента второму и обратно. В отличии от , через SOCKS прокси можно пустить любой трафик (скажем, ). Кроме того SOCKS передает "чистые" данные, не добавляя от себя ничего лишнего, поэтому его сложнее выявить.

В повседневной жизни SOCKS прокси чаще всего используется для доступа к сайтам, запрещенным . При таком раскладе получается, что Вы обращаетесь к серверу, а не к запрещенному интернет-адресу, поэтому соединение не блокируется.

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

Послесловие

Вот такие дела. Надеюсь теперь Вам хотя бы примерно понятно, что это такое вообще и зачем оно в общем и целом может быть необходим.

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

Как и всегда, если остались какие-то вопросы, мысли, дополнения и всё такое прочее, то добро пожаловать в комментарии к этому материалу.

SOCKS сокращение от «SOCKetS» (сокеты, гнёзда) разработан для того, чтобы дать возможность приложениям клиент/сервер в доменах TCP и UDP удобно и безопасно пользоваться услугами межсетевого экрана. Он дает пользователям возможность преодолевать межсетевой экран организации и получать доступ к ресурсам, расположенным в сети Интернет. SOCKS является “посредником уровня приложений”: он взаимодействует с общими сетевыми средствами (например, Telnet и браузер Netscape) и с помощью центрального сервера (прокси-сервера) от имени вашего компьютера устанавливает связь с другими центральными компьютерами.


SOCKS был разработан много лет назад Дейвом Кобласом из компании SGI, и сегодня этот код можно бесплатно получить через Интернет. С момента первого выпуска этот код пережил несколько крупных модификаций, но каждая из них распространялась совершенно бесплатно. SOCKS версия 4 решает вопрос незащищенного пересечения межсетевых экранов приложениями клиент/сервер, основанными на протоколе TCP, включая Telnet, FTP и популярные информационные протоколы, такие как HTTP, Wide Area Information Server (WAIS) и GOPHER. SOCKS версия 5, RFC 1928, является дальнейшим расширением четвертой версии SOCKS. Он включает в себя UDP, расширяет общую рамочную структуру, придавая ей возможность использования мощных обобщенных схем аутентификации, и расширяет систему адресации, включая в нее имя домена и адреса IP v6.

В настоящее время предлагается создать механизм управления входящими и исходящими многоадресными сообщениями IP, которые проходят через межсетевой экран. Это достигается определением расширений для существующего протокола SOCKS V.5, что создает основу для аутентифицированного перехода межсетевого экрана одноадресным пользовательским графиком TCP и UDP. Однако ввиду того, что поддержка UDP в текущей версии SOCKS V.5 имеет проблемы с масштабируемостью и другие недостатки (и их обязательно нужно разрешить, прежде чем переходить к многоадресной передаче), расширения определяются двояко: как базовые расширения UDP и как многоадресные расширения UDP.


Функционирование SOCKS заключается в замене стандартных сетевых системных вызовов в приложении их специальными версиями. Эти новые системные вызовы устанавливают связь с прокси-сервером SOCKS (который конфигурируется самим пользователем в приложении или системным файлом конфигурации), подключаясь к хорошо известному порту (обычно это порт 1080/ТСР). После установления связи с сервером SOCKS приложение отправляет серверу имя машины и номер порта, к которому хочет подключиться пользователь. Сервер SOCKS реально устанавливает связь с удаленным центральным компьютером, а затем прозрачно передает данные между приложением и удаленной машиной. При этом пользователь даже не подозревает, что в канале связи присутствует сервер SOCKS.


Трудность с использованием SOCKS состоит в том, что кто-то должен проводить работу по замене сетевых системных вызовов версиями SOCKS (этот процесс обычно называется “SOCKS-ификацией” приложения). К счастью, большинство обычных сетевых приложений (Telnet, FTP, finger, whois) уже SOCKS-ифицированы, и многие производители включают поддержку SOCKS в свои коммерческие приложения. Кроме того, SOCKS V.5 включает эти процедуры в свою общую библиотеку: на некоторых системах (например, на машинах Solaris) можно автоматически SOCKS-ифицировать приложение, поставив общую библиотеку SOCKS перед “shared libc” в вашей строке поиска библиотек (переменная среды LD__LIBRARY_PATH в системах Solaris).

Какое то время тому назад захотелось мне попробовать реализовать прокси сервер для собственных нужд, да такой, который можно было бы в дальнейшем использовать, а также, чтобы размер его был минимален. Естественным вариантом для меня стала реализация с использованием ассемблера. Программка получилась небольшая, удобная и в дальнейшем я очень часто ей пользовался. А вот теперь, по прошествии лет, хотелось бы показать простейшую реализацию одного протокола, SOCKS4. Данный протокол был создан для того, чтобы клиенты, находящиеся в локальной сети за межсетевым экраном могли обращаться во внешнюю сеть. В то же время запросы клиентов в таком случае есть возможность контролировать:) Самым первым, что нужно, при реализации – прочитать документацию с описанием данного протокола, так как мы хотим, чтобы наш протокол понимался стандартными программами, без “подтачивания напильником”. Итак, документация:

Теперь, вооружившись описанием, приступим. Работа прокси сервера состоит в том, чтобы принять от клиента запрос в определенном формате, сформировать сокет и подключить его по адресу запрошенному клиентом, после чего обеспечить обмен данными между двумя сокетами, до их закрытия со стороны сервера, либо клиента. Приступим к реализации.

Макросы и структуры данных, используемые в программе

Сформируем включаемый файл, includes.inc. В данный файл поместим стандартные, при написании Windows программ макросы + структуры для работы с SOCKS4. Здесь я не буду приводить все макросы, я приведу лишь описание и функционал, необходимый для решения основной задачи, все остальное вы найдете в приложенном файле с исходными кодами.
; SOCKS4 – Структура, используемая клиентом, при запросе соединения; на указанный сервер(DSTIP)/порт(DSTPORT) CONNECT_SOCK4 Struc VN Db ? CD Db ? DSTPORT Dw ? DSTIP Dd ? NULL Db ? CONNECT_SOCK4 Ends ; SOCKS4 - ответ прокси-сервера о соединении. RESPONSE_SOCK4 Struc VN Db ? CD Db ? DSTPORT Dw ? DSTIP Dd ? RESPONSE_SOCK4 Ends

По большому счету, структуры CONNECT_SOCK4 и RESPONSE_SOCK4 ничем не отличаются, так как мы реализуем протокол без авторизации. Но я решил все таки оставить их отдельно, чтобы в дальнейшем можно было легко изменить их, для доработки. В самих структурах, в переменной VN – указывается версия протокола, в нашем случае, здесь всегда должно быть 4, в случае с SOCKS5 в данной переменной находится 5 (протокол в принципе похож). Переменная CD используется для возврата клиенту результата запроса прокси сервера к запрошенному клиентом адресу (90 – соединение успешно / 91 – соединение не удалось).
У нас в программе по факту три этапа.
* Первый, инициализируем сокет, слушаем сокет на предмет наличия клиентских запросов, создаем поток обработки.
* Второй этап – анализ запроса клиента, попытка создания и соединения сокета с запрошенным клиентом сервером.
* И окончательный, третий этап – пересылка данных между сокетом клиента и сокетом созданным и соединенным нами с запрошенным адресом.

Реализация первого этапа, инициализация программы:

; Основная процедура, является стартовой для программы WinMain Proc LOCAL ThreadId, hServSock:DWORD LOCAL hostname :BYTE LOCAL _wsa:WSADATA LOCAL _our:sockaddr_in ; Запуск библиотеки работы с сокетами, мы используем функционал версии 1.1, ; запросим его как минимальный invoke WSAStartup, 0101h, ADDR _wsa .if eax == 0 ; Берем свой адрес, подготавливаем структуру, для инициализации серверного сокета invoke gethostname, ADDR hostname, 256 invoke gethostbyname, ADDR hostname .if eax == 0 invoke inet_addr, ADDR hostname .else mov eax, mov eax, mov eax, .endif mov _our.sin_addr, eax invoke inet_ntoa, eax mov _our.sin_family, AF_INET mov _our.sin_addr.S_un.S_addr, INADDR_ANY xor eax, eax ; Вносим порт, на котором хотим слушать входящие сообщения mov ax, SOCKS_PORT invoke htons, eax mov _our.sin_port, ax invoke socket, AF_INET, SOCK_STREAM, 0 .if eax != INVALID_SOCKET ; Сохраняем созданный серверный сокет mov hServSock, eax ; Привязываем серверный сокет к нашему адресу и необходимому порту invoke bind, hServSock, ADDR _our, SIZEOF sockaddr_in .if eax != SOCKET_ERROR @@: ; Инициируем сокет на ожидание invoke listen, hServSock, SOMAXCONN .repeat ; Пришел клиент, получаем сокет с пришедшим клиентом invoke accept, hServSock, NULL, NULL .until eax != INVALID_SOCKET ; Создаем поток, в котором будет обрабатываться текущий клиент xchg eax, ebx invoke CreateThread, NULL, NULL, ADDR socketThread, ebx, NULL, ADDR ThreadId ; Уходим на ожидание клиентов jmp @B .endif .endif invoke closesocket, hServSock .endif invoke ExitProcess, 0 WinMain Endp
Это первая наша процедура, я постарался максимально прокомментировать код, чтобы вы могли разобраться, но если все же что-то не понятно – обращайтесь либо ко мне, либо к MSDN. В принципе весь код написан с использованием синтаксиса MASM и WinAPI. Итогом работы приведенной функции должен быть работающий сокет на одном из сетевых адресов вашей машины (локальный адрес, либо внешний адрес если у вас реальный IP) + по соединению клиента функция создает отдельный поток, используемый для работы с пришедшим клиентом. Теперь пойдем дальше...

Второй этап, анализ запроса клиента

На втором этапе все, что необходимо сделать, это принять структуру CONNECT_SOCK4, создать сокет, попытаться соединить его и отправить клиенту ответ. Реализация:

SocketThread Proc sock:DWORD LOCAL lpMem, _csock, ThreadId, dAmount:DWORD LOCAL Remote:sockaddr_in LOCAL wrFds, rdFds:fd_set LOCAL hResp:RESPONSE_SOCK4 ; Готовимся к чтению данных из сокета invoke FdZero, ADDR rdFds invoke FdSet, sock, ADDR rdFds invoke select, NULL, ADDR rdFds, NULL, NULL, NULL ; Получаем размер ожидающих чтения данных invoke ioctlsocket, sock, FIONREAD, ADDR dAmount ; Резервируем память под данные mov lpMem, @Result(LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, dAmount) ; Читаем данные запроса из сокета invoke recv, sock, lpMem, dAmount, 0 ; Запрос пришел lea edi, hResp mov esi, lpMem ; В Esi лежит пользовательский запрос. Мы обрабатываем (здесь) только версию SOCKS4, ; SOCKS5 можно в принципе здесь же обработать, но это позже... Assume Esi: Ptr CONNECT_SOCK4 Assume Edi: Ptr RESPONSE_SOCK4 .if .VN == 4 ; Реализация протокола СОКС 4 .if .CD == 1 invoke socket, AF_INET, SOCK_STREAM, 0 .if eax != INVALID_SOCKET mov _csock, eax ; Берем данные удаленного хоста, с которым хочет соединиться клиент mov Remote.sin_family, AF_INET mov ax, .DSTPORT mov Remote.sin_port, ax mov eax, .DSTIP mov Remote.sin_addr, eax mov cx, .DSTPORT mov edx, .DSTIP ; В Edi лежит ответ пользователю mov .VN, 0 mov .DSTPORT, cx mov .DSTIP, edx ; Пытаемся соединиться с удаленным сервером invoke connect, _csock, ADDR Remote, SIZEOF Remote .if !eax ; Готовим ответ, что мы соединились mov .CD, 90 ; Отправляем клиенту ответ, содержащий результат попытки соединения invoke send, sock, ADDR hResp, SIZEOF RESPONSE_SOCK4, 0 ; Формируем структуру с информацией о серверном и; соединенном клиентском сокетах; - под серверным здесь подразумеваю сокет соединенный с клиентом, ; приславшим запрос; - под клиентским подразумеваю сокет соединенный с сервером, ; данные которого запросил клиент mov ebx, @Result(LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, SIZEOF THREAD_DATA) Assume Ebx: Ptr THREAD_DATA mov eax, _csock mov .Server, eax mov eax, sock mov .Client, eax Assume Ebx: Nothing ; Запускаем поток обработки сокетов (читающий из клиентского и; передающий в серверный сокет) invoke CreateThread, NULL, NULL, ADDR ClientSock, ebx, NULL, ADDR ThreadId .else ; Если соединение не получилось - закрываем клиентский сокет invoke closesocket, _csock ; Говорим, что произошла ошибка соединения mov , 91 ; Отправляем клиенту ответ, содержащий результат попытки соединения invoke send, sock, ADDR hResp, SIZEOF RESPONSE_SOCK4, 0 .endif .endif .endif .endif Assume Edi: Nothing Assume Esi: Nothing ; Высвобождаем память, выделенную под запрос invoke LocalFree, lpMem ret socketThread Endp
Результат выполнения данной процедуры – соединенный сокет, а также созданный поток, реализующий обмен данными между двумя сокетами. Все просто. Стоит только уточнить, здесь используется несколько моментов по адресации внутри структур, которые введены в MASM для облегчения жизни программиста. Первый момент, макрос “Assume”.
Строчка Assume Esi: Ptr CONNECT_SOCK4 говорит компилятору о том, что в данном регистре(Esi) находится адрес структуры CONNECT_SOCK4, что в дальнейшем упрощает обращение к переменным внутри данной структуры. Assume Esi:Nothing отменяет привязку. Чтобы лучше понять, возможно будет проще, если я укажу несколько вариантов адресации:
Assume Esi:Ptr CONNECT_SOCK4 mov al, .VN ; Помещаем в AL значение байта из переменной VN структуры mov al, .CD ; Помещение в AL переменной CD mov ax. .DSTPORT ; Помещение в AX переменной DSTPORT Assume Esi:Nothing
либо
mov al, ; Помещаем в AL значение байта из переменной VN mov al, ; Помещение в AL переменной CD mov ax, ; Помещение в AX переменной DSTPORT
либо
mov al, byte ptr ; Помещение в AL переменной VN mov al, byte ptr ; Помещение в AL переменной CD mov ax, word ptr ; Помещение в AX переменной DSTPORT

Я думаю, вам очевидно так же как и мне, что быстрее, удобней и наглядней использовать первый вариант. Хотя если необходимо обратиться к одной переменной структуры – имеет право на существование и второй вариант. Третий же вариант думаю лучше использовать в случаях, когда данные по адресу не структурированы. Но, как известно, на вкус и цвет, каждый сам себе тамбовский волк. Пользуйтесь тем методом, который вам удобней.
Еще один момент, который стоит уточнить. Макрос Result . Данный макрос написан, чтобы можно было одной строкой вызвать функцию WinAPI и занести результат исполнения в регистр или память. Так строка:
mov lpMem, @Result(LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, dAmount)
Выполняет сначала вызов такого вида:
invoke LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, dAmount
а уже после выполнения данного вызова результат исполнения (Eax) заносит в переменную lpMem. В данном конкретном случае, будет выделена память, а в переменную будет записан адрес, по которому находится выделенный для нас участок.

Этап третий, передача данных

Итак, выполнены два самых сложных этапа. Клиент пришел, мы соединили его с удаленным сервером и настал черед простейшей “обезьяньей” работы. Передачи данных между двумя сокетами. Сделаем это просто, по-быстрому:
; Поток читающий из клиентского и передающий в серверный сокет.... ClientSock Proc Param:DWORD LOCAL sserver, sclient:DWORD LOCAL rdFds:fd_set LOCAL dAmount, lpBuf: DWORD ; В Param у нас находится информация о сокетах сервера и клиента, ; переносим в локальные переменные mov ebx, Param Assume Ebx: Ptr THREAD_DATA mov eax, .Server mov sserver, eax mov eax, .Client mov sclient, eax Assume Ebx: Nothing ; Не забудем высвободить память invoke LocalFree, Param @@: invoke FdZero, ADDR rdFds invoke FdSet, sserver, ADDR rdFds invoke FdSet, sclient, ADDR rdFds invoke select, NULL, ADDR rdFds, NULL, NULL, NULL ; Проверяем, есть ли данные для чтения.if eax == SOCKET_ERROR || eax == 0 ; Данных нет - выходим jmp @F .endif ; Есть ли данные от сервера, которые нужно передать клиенту? invoke FdIsSet, sserver, ADDR rdFds .if eax ; Получаем размер ожидающих чтения данных invoke ioctlsocket, sserver, FIONREAD, ADDR dAmount ; Резервируем память под данные mov lpBuf, @Result(LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, dAmount) invoke recv, sserver, lpBuf, dAmount, 0 .if eax == SOCKET_ERROR || eax == 0 jmp @F .endif invoke send, sclient, lpBuf, eax, 0 invoke LocalFree, lpBuf .endif ; Есть ли данные от клиента для отправки серверному сокету? invoke FdIsSet, sclient, ADDR rdFds .if eax ; Получаем размер ожидающих чтения данных invoke ioctlsocket, sclient, FIONREAD, ADDR dAmount ; Резервируем память под данные mov lpBuf, @Result(LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, dAmount) invoke recv, sclient, lpBuf, dAmount, 0 .if eax == SOCKET_ERROR || eax == 0 jmp @F .endif invoke send, sserver, lpBuf, eax, 0 invoke LocalFree, lpBuf .endif ; Идем на новый цикл jmp @B @@: ; Закрываем сокеты invoke closesocket, sserver invoke closesocket, sclient ; Выходим из потока invoke ExitThread, 0 ClientSock Endp
Первоначально в данной процедуре производится инициализация внутренних переменных из переданной в поток структуры, чтобы их было удобнее использовать. Затем, в цикле производится проверка, есть ли данные на чтение из сокетов, затем двумя кусками кода (фактически копипаст, здесь я не заморачивался выносом функции и оптимизацией ибо так наглядней) делается чтение из одного сокета и отправка во второй.
Все, ура! Компилируем и пробуем. В принципе самый хороший вариант – FireFox. В настройках подключения указываем, что нужно использовать прокси сервер SOCKS4. Указываем его адрес и порт, на котором он у нас находится. После этого, сохраняем настройки и наслаждаемся интернетом, прошедшим, через наш прокси, размером 3,5 кбайт))) Да, уточню. Для компиляции жлательно наличие установленного пакета




Top