Определены две операции: Соединиться и сопоставить (CONNECT and BIND).
1) CONNECT
Клиент подключается к SOCKS4 серверу и посылает запрос на СОЕДИНЕНИЕ, когда хочет установить подключение к серверу приложений (удаленному серверу). В пакет запроса клиента включается IP адрес и номер порта удаленного хоста (сервера приложений), и пользовательский id, в следующем формате
+—-+—-+—-+—-+—-+—-+—-+—-+—-+—-+….+—-+
| VN | CD | ПОРТ | IP уд. хоста | ID польз. |NULL|
+—-+—-+—-+—-+—-+—-+—-+—-+—-+—-+….+—-+
разм полей: 1 1 2 4 variable 1
VN – это версия протокола SOCKS4, должна иметь значение 4.
CD – код команды для СОКСа, команда CONNECT должна иметь значение 1.
NULL – это завершающий байт пакета, полностью состоящий из нулевых бит.
variable – означает не фиксированную, переменную длину
Сервер SOCKS4 проверяет, разрешен ли такой запрос с заданными IP источника, IP назначения, порта назначения, ID пользователя (userid) и идентификационной информации, которую он может запросить по протоколу IDENT (*) (см. RFC 1413). Если запрос разрешен, SOCKS4 сервер создает соединение с указанным портом удаленного хоста. Ответный пакет посылается клиенту когда соединение с сервером приложений уже установлено, или когда запрос был отклонен, или же когда оперция завершилась ошибкой.
+—-+—-+—-+—-+—-+—-+—-+—-+
| VN | CD | DSTPORT| DSTIP |
+—-+—-+—-+—-+—-+—-+—-+—-+
size of: 1 1 2 4
VN – это версия протокола, должна иметь значение 0.
CD – результирующий код, возможны следующие значения:
90: запрос выполнен
91: запрос отклонен или завершился ошибкой
92: запрос отклонен потому, что SOCKS4 сервер не может соединиться с identd (*) клиента
93: запрос отклонен потому, что клиентская программ и identd (*) сообщают SOCKS4 серверу различные userid
Остальные поля должны игнорироваться.
Сервер SOCKS4 сразу же рвет соединение после уведомеление клиента об отлоненном запросе или ошибке. Успешный же запрос клиента означает, что SOCKS4 сервер готов передавать трафик в обоих направлениях. С этого момента клиент может обмениваться данными через SOCKS4 сервер, как если бы он был подключен к серверу приложений.
2) BIND
Клиент соединяется с SOCKS4 сервером и посылает BIND запрос когда он готовится к входящему соединению от сервера приложений. Это поисходит только после того, как уже было установлено первичное соединение с сервером приложений через SOCKS сервер командой CONNECT. Вот типичный фрагмент последовательности дейтсвий:
-bind(): получает сокет
-getsockname(): получает IP адерс и номер порта сокета
-listen(): готовится принять вызов от сервера приложений
-использует первичное подключение, чтобы сообщить серверу приложений IP адрес и номер порта, на который ему следует установить соединение
-accept(): принимает соедининие от сервера приложений
Назначение операции BIND – это поддержка такой последовательности, когда использование сокета на SOCKS4 сервере предпочтительнее, чем использование сокета клиента.
Клиент включает в пакет запроса IP адрес сервера приложений, удаленный порт используемый в первичном подключении, и userid.
+—-+—-+—-+—-+—-+—-+—-+—-+—-+—-+….+—-+
| VN | CD | DSTPORT| DSTIP | USERID |NULL|
+—-+—-+—-+—-+—-+—-+—-+—-+—-+—-+….+—-+
size: 1 1 2 4 variable 1
VN опять равно 4 (версия протокола SOCKS4)
CD должно быть 2, что означает BIND-запрос
Сервер SOCKS4 использует информацию от клиента, чтобы решить, принять или отклонить запрос клиента. Сервер отсылает назад к клиенту ответ в таком же формате, как и ответ на CONNECT запрос, т.е.
+—-+—-+—-+—-+—-+—-+—-+—-+
| VN | CD | DSTPORT| DSTIP |
+—-+—-+—-+—-+—-+—-+—-+—-+
size: 1 1 2 4
VN – это версия протокола, должна иметь значение 0.
CD – результирующий код, возможны следующие значения:
90: запрос выполнен
91: запрос отклонен или завершился ошибкой
92: запрос отклонен потому, что SOCKS4 сервер не может соединиться с identd (*) клиента
93: запрос отклонен потому, что клиентская программ и identd (*) сообщают SOCKS4 серверу различные userid
Однако, если запрос был принят (CD == 90), тогда поля DSTPORT и DSTIP несут полезную информацию.
В этом случае, SOCKS4 сервер создает сокет для ожидания входящего соединения и посылает номер порта и IP адрес этого сокета клиенту в DSTPORT и DSTIP соответственно. Если DSTIP в ответе сервера равно 0 (значение константы INADDR_ANY), тогда клиенту следует заменить 0 на IP адрес SOCKS4 сервера, с которым он соединен в данный момент. (Это случается, если SOCKS4 сервер не является мультиадресным хостом)
Обычно эти два числа могут быть получены приложением клиента с помощью последующего вызова функции getsockname().
Протокол приложения должен предоставлять способ отправки этих двух значений от клиента к серверу приложений, чтобы он мог начать подключение, когда соединением между ним и SOCKS4 сервером более предпочтительным, чем обычное прямое соединение, которое бывает в нормальных условиях.
SOCKS4 сервер посылает второй ответный пакет клиенту, когда ожидаемое подключение от сервера приложений установлено.
SOCKS сервер сверяет IP адрес соединяющегося хоста со значением DSTIP заданного в BIND-запросе клиента.
Если они не совпадают, тогда во втором ответном пакете клиенту значение поля CD выставляется 91, и SOCKS сервер закрывает оба соединения.
При совпадении значений, значение поле CD во втором ответе клиенту выставляется 90 и SOCKS сервер спсобен переправлять трафик между этими двумя сторонами соединений. С этого момента клиент может получать/полсылать данные через соединение SOCKS сервера, как если бы он имел прямое соединение с сервером приложений.
Для обеих операций CONNECT и BIND, сервер устанавливает лимит времени (2 минуты в текущей реализации CSTC) для создания соединения с сервером приложений. Если по истечении лимита времени соединение не установилось, SOCKS сервер прекращает дальнейшие попытки и закрывает свое соедиение с клиентом.
——————————————————————————–
(*)
Кратко о протоколе IDENT:
Клиент устанавливает соединение с сервером, который, прежде чем слать ответный пакет, устанавливает ответное соединение на порт 113, запрашивает имя пользователя (userid), указывает номера портов с обеих сторон (полагаю, что протокол IDENT нужен из-за отстутствия в протоколе SOCKS 4 каких-либо способов аутентификации клиента).