Writing a simple SOCKS4 server in Assembler language. What is a SOCKS server and why is it needed?

The article is devoted to the SOCKS5 protocol - its internal structure, practical application, as well as SOCKS servers and clients available for the Unix platform

[Valentin Sinitsyn (val AT linuxcenter DOT ru)]

“Sorry, Pooh,” said SAVA. - Tigger chewed all the wires from the mail server, and the mail did not arrive for a long time...
“Wires,” thought Pooh angrily. - Knit socks from these wires.

Andrey Shcherbakov “9600 baud and that’s it, that’s it, that’s it...”

In this article we will talk about the SOCKS protocol[ footnote: "socks" - English. "socks", "stockings"]. With its help you can solve the most different tasks: organize secure access to services located behind firewall(firewall), hide your true IP address while working with unfriendly network resources, or implement a universal proxy server that supports any protocols application level(HTTP, FTP, POP3/SMTP, ICQ, etc.). Unfortunately, despite the simplicity and richness of SOCKS, many system administrators are not very familiar with it and have no idea how it can be useful. I would like to hope that after reading this material, the undeservedly forgotten protocol will take its rightful place in their arsenal. Let’s make a reservation right away: all subsequent presentation will refer to the fifth version of SOCKS, SOCKS5. The previous, fourth version (SOCKS4) is still in circulation on the Internet, however, its capabilities are more limited.

By the way, the name of the protocol has nothing to do with the hosiery items mentioned in the epigraph and is a simple abbreviation for “SOCK-et-S” - “sockets”, or, in a more familiar translation to a computer specialist’s ear, “sockets”. The term was proposed by the creators as a working option, and it stuck. As you know, sockets are the basis of any API that implements network communication - Unix, Winsock, etc. To send data over the network, an application simply needs to write it to a socket, similar to what is done when storing information in a local file. In both cases, the program does not have to worry about what is happening behind the scenes - the addition of user data official information, breaking into segments with their subsequent encapsulation into datagrams and physical sending is carried out by other parts of the operating system - the TCP / IP stack and device drivers, about which the application knows nothing. This “division of labor” allows you to change the message delivery procedure as desired, provided that the application programming interface remains constant. It is this feature that underlies the SOCKS ideology. The main task of this protocol is to introduce into the “normal” data exchange process a certain intermediary called a SOCKS server or SOCKS proxy. When a client (an application that supports SOCKS: Mozilla web browser, ICQ Miranda IM client, etc., see below) wants to send any information over the network, it establishes a connection not with the real recipient, but with the SOCKS server, which, in in turn, forwards the data to its destination, but on its own behalf. From the point of view of the "real" server (for example, the web site that the user wants to view in Mozilla Firefox) SOCKS proxy is the most common client. Thus, the identity (IP address) of the true client is hidden from the server serving it. This very convenient circumstance is fraught with potential danger (you can hide You, but they can from you), therefore, real-life SOCKS servers have developed access control schemes (prohibiting incoming and outgoing connections to a given list of addresses) and support user authorization using a password (see below).

Note that since SOCKS operates at a lower level than the application (namely, transport) level of the OSI model, its support will not require any changes in the logic of the client, much less the server. Indeed, all that is needed is to modify the implementation of the functions responsible for creating network connection and sending data: connect(), bind(), send(), etc. In practice this is usually achieved by intercepting system calls with their subsequent replacement with SOCKS-supporting user analogues. No changes to the source code client applications, much less access to the source texts, as a rule, is not required. This powerful procedure is known as “soxification” and will be discussed in detail below.

Now that we have a general understanding of SOCKS, we can move on to a more detailed look. of this protocol.

SOCKS5 specification

The SOCKS5 protocol is described in detail in RFC1928. Unlike monstrous standards like HTTP 1.1, the SOCKS specification fits into 9 pages and can be easily parsed by anyone. The information offered here is a brief summary of it and is intended to help you in this simple matter.

As noted earlier, SOCKS5 is a transport layer protocol. Its “neighbors” - TCP and UDP are directly used to transmit data coming from the application layer (from custom applications), which means the SOCKS proxy must be able to work correctly with each of them. Note also that the ICMP protocol used by the ping and traceroute utilities is located below the transport layer, and therefore, unfortunately, cannot be cosified.[ Footnote: there are non-standard extensions to the SOCKS protocol that allow you to work with ICMP, however, they will not be discussed in this article].

Before sending any data, the client must go through an authorization procedure on the SOCKS server. To do this, it opens a TCP connection to port 1080 (default value) of the SOCKS server and sends a message over it containing the code numbers of the authentication methods it supports. The SOCKS server selects one of the methods at its discretion and reports its number to the client. A list of some of the possible values ​​is given in Table 1. As you can easily see, authentication can be absent (in practice, this most likely means that the SOCKS server distinguishes clients by their IP addresses) or based on a username and password. In the latter case it is possible a large number of various options, from the trivial “Username/Password Authentication” (RFC 1929), which provides for the transmission of a cleartext password, to the much more secure CHAP (encrypted password, clear data) and GSSAPI (RFC 1961), which can be used for complete cryptographic protection of traffic. After successful authorization, the client is able to send requests (commands), establish outgoing connections, and even receive incoming ones.

Establishing an outgoing TCP connection

To establish an outgoing TCP connection, the client sends a “CONNECT” request to the SOCKS server, which specifies the address and delivery port. To identify the recipient host, both IP addresses (IPv4/IPv6 are supported) and fully qualified domain names can be used. In the latter case, the SOCKS server takes care of resolving them, so the network in which the client operates can, in principle, do without a DNS server. In the response message, the SOCKS server reports an error code (as usual, 0 indicates that the operation was successful), as well as the IP address (BND.ADDR) and TCP port (BND.PORT) that will be used to actually communicate with the requested knot. Since SOCKS servers typically have more than one network interface, this IP address may be different from the one with which the control connection was established. The client then opens a new TCP session with BND.ADDR:BND.PORT and sends data. The outgoing TCP connection is terminated when the control session is closed. Note that a CONNECT request may be rejected by a SOCKS proxy if the source (client) or destination (server) addresses are prohibited [ Footnote: or not explicitly allowed, depending on the specific implementation and policy chosen] to be serviced by the system administrator.

Establishing an outgoing UDP connection

Unlike the TCP streaming protocol, which involves establishing a session, UDP protocol is datagram, and therefore somewhat more difficult to handle. Its support appeared only in SOCKS5.

Before sending UDP datagrams, the client requests the SOCKS server UDP association using the "UDP ASSOCIATE" command. A UDP association is a kind of virtual session between a client and a SOCKS server. In the outgoing request, the client specifies allegedthe address and port that will act as the source of future UDP datagrams. If this information is not yet known when the UDP association is established, the client should use the combination 0.0.0.0:0 (or, say, x.x.x.x:0 if only the port number is unknown). In the response message, the SOCKS server specifies the IP address (BND.ADDR) and UDP port (BND.PORT) to which outgoing datagrams should be sent. In this case, the address and port of their real recipient are indicated directly in the body (we can say that UDP encapsulation takes place). E you parameters, along with the sender's address and port, are used to decide whether a datagram can be sent. As you can easily see, this creates an additional load on the SOCKS server: filtering rules must be applied to each UDP datagram, whereas in the case of a TCP connection, its legitimacy is assessed once, at the time the SOCKS server executes the “CONNECT” command. According to the standard, the SOCKS server must ensure that the IP address of the datagram sender matches the address of the host that created the UDP association. The UDP association is destroyed simultaneously with the closing of the TCP control session in which the UDP ASSOCIATE command was sent.

Many of the existing SOCKS servers experience serious problems if a NAT (Network Address Translation) firewall is placed between them and the client requesting the UDP association. The reason for this lies in the change in the source address and port that occurs the moment the UDP datagram crosses the firewall. As a consequence, the server and the unsuspecting client application begin to speak different languages: the intended source address and port specified in the “UDP ASSOCIATE” command no longer correspond to the actual parameters of the datagrams received by the SOCKS server. As a result, they are discarded as not belonging to the UDP association. The problem could be solved by specifying 0.0.0.0:0 as the intended source (see above), which should be interpreted by the SOCKS server as “any UDP datagram coming from the same address as the command to create the association.” Unfortunately, most of the actual SOCKS servers interpret the standard more narrowly and do not allow you to simultaneously set both the intended address and the sender port to zero. Of the implementations tested by the author, the “trick with forwarding UDP through NAT” described here allows only one to be done - Dante.

Receiving incoming connections

This rather original feature can be useful in cases where the client and the “real” server in the scheme described above are swapped, which can happen, for example, in protocols like FTP. For the purpose of further discussion, we will assume that a “direct” communication channel has already been established between the “client” (the party about to accept the incoming connection) and the “server” (the party initiating the incoming connection) using the “CONNECT” command. To open a “reverse” channel, the “client” must send the “BIND” command to the SOCKS server, specifying in its parameters the IP address and port that it will use to receive the incoming connection. In response, the SOCKS server reports the IP address and port allocated to it to maintain the “reverse” channel. The "client" is expected to pass these parameters to the "server" using the facilities provided by application layer protocols (for example, the FTP "PORT" command). After the SOCKS server accepts (or rejects) the incoming connection, it re-notifies the “client”, telling it the IP address and port used by the “server”. Note that incoming connections can only be accepted by an application whose developers took care of SOCKS support at the design stage. Otherwise (if the application works with the SOCKS server through a sockets program), it will not be able to provide correct information about the address of the socket that is waiting for “feedback” (i.e., it will generate the incorrect “PORT” command in the FTP example discussed above).

"Chains" SOCKS

Come on, get to work. Six rented “at a time” routers through which the signal runs. And all are quite resistant to hacking.

Sergey Lukyanenko “Labyrinth of Reflections”

The architecture of the SOCKS5 protocol makes it easy to combine SOCKS servers into cascades, or as they are also called “chains”. It is noteworthy that all the actions necessary for this can be performed on the client side. The only requirement for the “links” of the chain is that they must “trust” each other (i.e., allow the establishment of incoming and outgoing connections). If the SOCKS servers that form the cascade are not anonymous (that is, they use Username/Password, CHAP, or similar authentication schemes), it is also necessary that the user can successfully complete the authorization procedure on each of them.

Let's assume that we have a set of N SOCKS servers named socks1, socks2, ..., socksN, satisfying all the above requirements. Then, to create a cascade, the client can do the following:

    When outgoing TCP connection: the client connects to socks1, goes through the authorization procedure (if necessary) and sends the “CONNECT” command, specifying socks2 as the delivery address. By executing this request, socks1 will create a new connection with socks2 and will regularly transfer all the information passing through it to the client, while socks2 will not even guess with whom it is actually communicating. The procedure is then repeated until a connection is established between socks(N-1) and socksN. The last server in the cascade connects directly to the node that interests the client. Data transfer takes place in normal mode: The client sends the packet to the socks1 server, which in turn sends it to socks2, ... and so on until the end node is reached.

    When outgoing UDP connection: the client connects to socks1, goes through the authorization procedure and sequentially sends two commands: “CONNECT” (delivery address - socks2) and “UDP ASSOCIATE”. Thus, two new connections are created: a virtual UDP channel between the client and socks1, and a TCP session between socks1 and socks2. Using this TCP session, the client (on behalf of socks1) sends the command “UDP ASSOCIATE” to the socks2 server (opens a UDP channel between socks1 and socks2) and “CONNECT” to the socks3 server. The procedure continues until virtual UDP channels are established between all SOCKS servers in the cascade. To send any data, the client first performs N-fold encapsulation of the UDP datagram, specifying sequentially socks1, socks2, socks3, socksN and the address of the real recipient as the delivery address, and then sends it to the socks1 server. Note that in practice

this optioncascading is extremely rare. This is due to the fact that SOCKS servers, like NAT Firewalls, can change the source port of the datagram, which will lead to problems described in detail in the section “Establishing an outgoing UDP connection”. ) for Windows or ProxyChains ( ) for Unix. Cascading SOCKS servers is also an integral part of some soxifiers, most notably FreeCap (http://www.freecap.ru/ ).

SOCKS servers

Now that we are well familiar with the operating principles of a SOCKS server, it’s time to move from theory to practice. There are a large number of programs in the world that implement the SOCKS5 protocol. They cover all the popular ones OS(Unix, Windows, ...) and distribution methods (freeware, shareware, open-source, etc.). Here we will briefly consider the most famous (or interesting from the author’s point of view) implementations.

Let's start with SOCKS5 Reference Implementation (http://www.socks.permeo.com/), made by NEC and owned by currently Permeo company. Current version numbered 1.0r11 and dated August 2000. As you can easily guess from the name, this server is a reference implementation of the protocol and, generally speaking, is not intended for industrial use. However, for reasons that are not very clear to me, it was included in the FreeBSD ports, and therefore is a de facto standard on this platform. The product has GSSAPI support and is distributed in source code, but under a proprietary license. Commercial use of this server is prohibited.

Dante, developed by the Norwegian company Inferno Nettverk, is especially popular among Linux supporters. The product is developing, although not very rapidly ( latest version, 1.1.15, dated January 31, 2005) and is quite suitable for practical use. As mentioned earlier, Dante allows UDP associations to work correctly even if they go through a NAT Firewall. The program is distributed in source code under the BSD license. Dante includes a library for transparent coxification of Unix applications (see below)

Valentin Sinitsyn (val AT linuxcenter DOT ru) - Universal proxy server

Such a proxy server controls the client’s rights to access external resources and transmits the request to the server. SOCKS can also be used in the opposite way, allowing external clients to connect to servers behind a firewall.

Unlike HTTP proxy servers, SOCKS transmits all the data from the client without adding anything from itself, that is, from the point of view of the end server, the SOCKS proxy is a regular client. SOCKS is more universal - it does not depend on specific application layer protocols (layer 7 of the OSI model) and is based on the TCP/IP standard - layer 4 protocol. But the HTTP proxy caches data and can more carefully filter the content of the transmitted data.

This protocol was developed by David Koblas, a system administrator at MIPS Computer Systems. After MIPS became part of Silicon Graphics (SGI) that year, Koblas gave a talk on SOCKS at the Usenix Security Symposium, and SOCKS became publicly available. The protocol was extended to version 4 by Ying-Da Lee of NEC Systems Laboratory.

SOCKS 4 protocol

SOCKS 4 is designed to work through a firewall without authentication for client-server applications running over TCP, such as TELNET, FTP, and popular communication protocols such as HTTP, WAIS, and GOPHER. Essentially, a SOCKS server can be thought of as a firewall that supports the SOCKS protocol.

A typical SOCKS 4 request looks like this (each field is one byte):

Client request to SOCKS Server:

  • field 1: SOCKS version number, 1 byte (should be 0x04 for this version)
  • field 2: command code, 1 byte:
    • 0x02 = TCP/IP port assignment (binding)
  • field 3: port number, 2 bytes
  • field 4: IP address, 4 bytes
  • field 5: user ID, variable length string, terminated with a null byte (0x00). The field is intended to identify the user (see Ident)

Server response to SOCKS Client:

  • field 1: null byte
  • field 2: response code, 1 byte:
    • 0x5a = request granted
    • 0x5b = request rejected or invalid
    • 0x5c = The request failed because identd is not running (or is not accessible from the server)
    • 0x5d = The request failed because the client identd could not validate the user ID in the request
  • field 3: 2 arbitrary bytes, should be ignored
  • field 4: 4 arbitrary bytes, should be ignored

SOCKS 5 protocol

SOCKS 5 extends the SOCKS 4 model by adding UDP support, providing universal schemes strong authentication and extends addressing methods by adding support for domain names and IPv6 addresses. Initial installation The connection now consists of the following:

  • The client connects and sends a greeting that includes a list of supported authentication methods
  • The server chooses one of them (or sends a request failure response if none of the proposed methods is acceptable)
  • Depending on the chosen method, a number of messages may pass between the client and server
  • The client sends a connection request, similar to SOCKS 4
  • Server responds, similar to SOCKS 4

Authentication methods are numbered as follows:

  • 0x00 - no authentication required
  • 0x01 - GSSAPI
  • 0x02 - username/password
  • 0x03-0x7F - reserved by IANA
  • 0x80-0xFE - reserved for private use methods

Initial greeting from the client:

  • field 2: number of supported authentication methods, 1 byte
  • field 3: authentication method numbers, variable length, 1 byte for each supported method

The server reports its choice:

  • field 1: SOCKS version, 1 byte (0x05 for this version)
  • field 2: selected authentication method, 1 byte, or 0xFF if no acceptable method was proposed

Subsequent identification depends on the chosen method.

Customer Request:

  • field 1: SOCKS version number (should be 0x05 for this version)
  • field 2: command code, 1 byte:
    • 0x01 = setting up TCP/IP connection
    • 0x02 = TCP/IP port assignment (binding)
    • 0x03 = UDP port association
  • field 3: reserved byte, must be 0x00
  • field 4: address type, 1 byte:
    • 0x01 = IPv4 address
    • 0x03 = domain name
    • 0x04 = IPv6 address
  • field 5: address assignment
    • 4 bytes for IPv4 address
    • 16 bytes for IPv6 address
  • field 6: port number, 2 bytes

Server response:

  • field 1: SOCKS version number, 1 byte (0x05 for this version)
  • field 2: response code, 1 byte:
    • 0x00 = request granted
    • 0x01 = SOCKS server error
    • 0x02 = connection is prohibited by the ruleset
    • 0x03 = network unavailable
    • 0x04 = host unreachable
    • 0x05 = connection refused
    • 0x06 = TTL expired
    • 0x07 = Command not supported / protocol error
    • 0x08 = address type not supported
  • field 3: byte reserved, must be 0x00
  • field 4: subsequent address type, 1 byte:
    • 0x01 = IPv4 address
    • 0x03 = domain name
    • 0x04 = IPv6 address
  • field 5: address assignment
    • 4 bytes for IPv4 address
    • the first byte is the length of the name, followed by the domain name without a terminating null
    • 16 bytes for IPv6 address
  • field 6: port number, 2 bytes

Implementations

  • Sun Java System Web Proxy Server - caching proxy server for Solaris, Linux, Windows. Supports HTTPS, NSAPI I/O filters, dynamic reconfiguration and reverse proxy.
  • DeleGate is a multifunctional application level gateway and proxy server that runs on various platforms. In addition to SOCKS, it also supports HTTP(S), FTP, NNTP, SMTP, POP, IMAP, LDAP, Telnet, DNS and other protocols.
  • 3proxy - lightweight proxy server with SOCKS-proxy support
  • WinGate is a multi-protocol proxy server with SOCKS support for Windows.
  • OpenSSH allows you to dynamically create tunnels defined through a subset of the SOCKS protocol.

see also

Links

  • RFC 1928 - SOCKS Protocol Version 5
  • RFC 1928 (Russian) - SOCKS 5 Protocol
  • RFC 1929 - Username/Password Authentication for SOCKS V5
  • RFC 1961 (English) - GSS-API Authentication Method for SOCKS Version 5
  • SOCKS: A protocol for TCP proxy across firewalls - SOCKS 4 protocol

Wikimedia Foundation.

2010.

    See what "SOCKS" is in other dictionaries: SOCKS

    See what "SOCKS" is in other dictionaries:- is an Internet protocol that allows client server applications to transparently use the services of a network firewall. SOCKS is an abbreviation for SOCKetS [ ]… … Wikipedia

    - Saltar a navegación, búsqueda SOCKS es un protocolo de Internet que permite a las aplicaciones Cliente servidor usar de manera transparente los servicios de un firewall de red. SOCKS es una abreviación de SOCKETS . Los clientes que hay detrás… … Wikipedia Español

    A network protocol that allows client-server applications to transparently use services behind firewalls. SOCKS is short for SOCKetS (sockets). Clients behind a firewall needing access to... ... Wikipedia Socks

    A network protocol that allows client-server applications to transparently use services behind firewalls. SOCKS is short for SOCKetS (sockets). Clients behind a firewall needing access to... ... Wikipedia- im Briefing Room des Weißen Hauses Betty Currie und Socks … Deutsch Wikipedia

Some time ago I wanted to try to implement a proxy server for my own needs, and one that could be used in the future, and also that its size would be minimal. The natural option for me was implementation using assembler. The program turned out to be small, convenient, and in the future I used it very often. But now, after years have passed, I would like to show the simplest implementation of one protocol, SOCKS4. This protocol was created so that clients located on the local network behind the firewall could access the external network. At the same time, in this case, it is possible to control client requests :) The very first thing you need to do when implementing is to read the documentation describing this protocol, since we want our protocol to be understood by standard programs, without “undermining with a file.” So, the documentation:

Now, armed with a description, let's get started. The job of a proxy server is to accept a request from a client in a certain format, generate a socket and connect it to the address requested by the client, and then ensure the exchange of data between two sockets until they are closed by the server or client. Let's start implementation.

Macros and data structures used in the program

Let's create an include file, includes.inc. IN this file we place the standard ones, at writing Windows programs macros + structures for working with SOCKS4. Here I will not give all the macros, I will only give the description and functionality necessary to solve the main problem, everything else you will find in the attached file with the source codes.
; SOCKS4 – The structure used by the client when requesting a connection; to the specified server(DSTIP)/port(DSTPORT) CONNECT_SOCK4 Struc VN Db ?

By and large, the CONNECT_SOCK4 and RESPONSE_SOCK4 structures are no different, since we implement the protocol without authorization. But I decided to leave them separately so that in the future I could easily change them for improvement. In the structures themselves, in the VN variable, the protocol version is indicated; in our case, there should always be 4; in the case of SOCKS5, this variable contains 5 (the protocol is basically similar). The CD variable is used to return to the client the result of the proxy server request to the address requested by the client (90 - connection successful / 91 - connection failed).
We actually have three stages in the program.
* First, we initialize the socket, listen to the socket for client requests, and create a processing thread.
* The second stage is the analysis of the client’s request, an attempt to create and connect a socket to the server requested by the client.
* And the final, third stage is sending data between the client socket and the socket created and connected by us to the requested address.

Implementation of the first stage, initialization of the program:

; The main procedure is the starting procedure for the WinMain program Proc LOCAL ThreadId, hServSock:DWORD LOCAL hostname :BYTE LOCAL _wsa:WSADATA LOCAL _our:sockaddr_in ; Launching the library for working with sockets, we use the functionality of version 1.1, ; let's request it as a minimum invoke WSAStartup, 0101h, ADDR _wsa .if eax == 0 ; We take our address, prepare a structure to initialize the server socket 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 ; Enter the port on which we want to listen to incoming messages mov ax, SOCKS_PORT invoke htons, eax mov _our.sin_port, ax invoke socket, AF_INET, SOCK_STREAM, 0 .if eax != INVALID_SOCKET ; Save the created server socket mov hServSock, eax ; We bind the server socket to our address and the required port invoke bind, hServSock, ADDR _our, SIZEOF sockaddr_in .if eax != SOCKET_ERROR @@: ; Initiate the socket to wait invoke listen, hServSock, SOMAXCONN .repeat ; A client has arrived, we receive a socket with the incoming client invoke accept, hServSock, NULL, NULL .until eax != INVALID_SOCKET ; Create a thread in which the current client will be processed xchg eax, ebx invoke CreateThread, NULL, NULL, ADDR socketThread, ebx, NULL, ADDR ThreadId ; We leave to wait for clients jmp @B .endif .endif invoke closesocket, hServSock .endif invoke ExitProcess, 0 WinMain Endp
This is our first procedure, I tried to comment on the code as much as possible so that you can figure it out, but if something is still not clear, please contact either me or MSDN. Basically all the code is written using MASM and WinAPI syntax. The result of the above function should be a working socket on one of the network addresses of your machine (local address, or external address if you have a real IP) + based on the client connection, the function creates a separate thread used to work with the incoming client. Now let's move on...

Second stage, analysis of the client's request

In the second step, all that needs to be done is to accept a CONNECT_SOCK4 structure, create a socket, try to connect it, and send a response to the client. Implementation:

SocketThread Proc sock:DWORD LOCAL lpMem, _csock, ThreadId, dAmount:DWORD LOCAL Remote:sockaddr_in LOCAL wrFds, rdFds:fd_set LOCAL hResp:RESPONSE_SOCK4 ; Getting ready to read data from the socket invoke FdZero, ADDR rdFds invoke FdSet, sock, ADDR rdFds invoke select, NULL, ADDR rdFds, NULL, NULL, NULL ; We get the size of the data waiting to be read invoke ioctlsocket, sock, FIONREAD, ADDR dAmount ; We reserve memory for data mov lpMem, @Result(LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, dAmount) ; Read request data from the socket invoke recv, sock, lpMem, dAmount, 0 ; The request came lea edi, hResp mov esi, lpMem ; Esi contains a user request. We handle (here) only the SOCKS4 version, ; SOCKS5 can, in principle, be processed here, but that will come later... Assume Esi: Ptr CONNECT_SOCK4 Assume Edi: Ptr RESPONSE_SOCK4 .if .VN == 4 ; Implementation of the SOX 4 protocol .if .CD == 1 invoke socket, AF_INET, SOCK_STREAM, 0 .if eax != INVALID_SOCKET mov _csock, eax ; We take the data of the remote host with which the client wants to connect 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 contains the answer to the user mov .VN, 0 mov .DSTPORT, cx mov .DSTIP, edx ; We are trying to connect with remote server invoke connect, _csock, ADDR Remote, SIZEOF Remote .if !eax ; We are preparing a response that we have connected mov .CD, 90 ; We send the client a response containing the result of the connection attempt invoke send, sock, ADDR hResp, SIZEOF RESPONSE_SOCK4, 0 ; We form a structure with information about the server and; connected client sockets; - by server here I mean the socket connected to the client; who sent the request; - by client I mean a socket connected to the server; whose data was requested by the client 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 ; We start the socket processing thread (reading from the client and transmitting to the server socket) invoke CreateThread, NULL, NULL, ADDR ClientSock, ebx, NULL, ADDR ThreadId .else ; If the connection fails, close the client socket invoke closesocket, _csock ; We say that there was a connection error mov , 91 ; We send the client a response containing the result of the connection attempt invoke send, sock, ADDR hResp, SIZEOF RESPONSE_SOCK4, 0 .endif .endif .endif .endif Assume Edi: Nothing Assume Esi: Nothing ; Freeing the memory allocated for the request invoke LocalFree, lpMem ret socketThread Endp
The result of this procedure is a connected socket, as well as a created thread that implements data exchange between two sockets. It's simple. One has only to clarify that several addressing points are used here within the structures that were introduced into MASM to make the programmer’s life easier. First point, the “Assume” macro.
The line Assume Esi: Ptr CONNECT_SOCK4 tells the compiler that this register (Esi) contains the address of the CONNECT_SOCK4 structure, which further simplifies accessing variables within this structure. Assume Esi:Nothing cancels the binding. To better understand, it might be easier if I list a few addressing options:
Assume Esi:Ptr CONNECT_SOCK4 mov al, .VN ; We place in AL the byte value from the variable VN structure mov al, .CD ; Place the variable CD mov ax in AL. .DSTPORT ; Place the DSTPORT variable in AX Assume Esi:Nothing
or
mov al, ; Place the byte value from the VN variable in AL mov al, ; Place the variable CD mov ax, ; Place the DSTPORT variable in AX
or
mov al, byte ptr ; Place variable VN in AL mov al, byte ptr ; Place the CD variable in AL mov ax, word ptr ; Place the DSTPORT variable in AX

I think it’s obvious to you, just as it is to me, that it’s faster, more convenient and clearer to use the first option. Although if it is necessary to refer to one variable of the structure, the second option has a right to exist. I think it is better to use the third option in cases where the data at the address is not structured. But, as you know, every Tambov wolf has its own taste and color. Use the method that is most convenient for you.
One more point worth clarifying. Result macro. This macro was written so that you can call a WinAPI function in one line and write the execution result to a register or memory. So the line:
mov lpMem, @Result(LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, dAmount)
First makes a call like this:
invoke LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, dAmount
and after execution this call the execution result (Eax) is stored in the lpMem variable. In this specific case, memory will be allocated, and the address at which the area allocated for us is located will be written to the variable.

Stage three, data transfer

So, the two most difficult stages have been completed. The client arrived, we connected him to the remote server, and it was time for the simplest “monkey” work. Transfer data between two sockets. Let's do it quickly and easily:
; A stream reading from the client socket and sending it to the server socket.... ClientSock Proc Param:DWORD LOCAL sserver, sclient:DWORD LOCAL rdFds:fd_set LOCAL dAmount, lpBuf: DWORD ; In Param we have information about the server and client sockets; transfer to local variables mov ebx, Param Assume Ebx: Ptr THREAD_DATA mov eax, .Server mov sserver, eax mov eax, .Client mov sclient, eax Assume Ebx: Nothing ; Don't forget to free up memory 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 ; Check if there is data to read.if eax == SOCKET_ERROR || eax == 0 ; No data - exit jmp @F .endif ; Is there data from the server that needs to be passed to the client? invoke FdIsSet, sserver, ADDR rdFds .if eax ; We get the size of the data waiting to be read invoke ioctlsocket, sserver, FIONREAD, ADDR dAmount ; Reserve memory for data 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 ; Is there data from the client to send? server socket
?
That's it, hurray! Let's compile and try. In principle, the best option is FireFox. In the connection settings, we specify that you need to use a SOCKS4 proxy server. We indicate its address and the port on which it is located. After that, we save the settings and enjoy the Internet, passed through our proxy, 3.5 kbytes in size))) Yes, I’ll clarify. For compilation it is necessary to have the package installed

Good day, dear friends, acquaintances, readers, admirers and other individuals. In this article, as you understand from the title, we will talk about what is See what "SOCKS" is in other dictionaries: server and why it is needed at all.

Of course, this information will be more useful to interested people than to the average user, but, in principle, knowledge of such things may also be useful to him... because who knows how life will turn out.

General and detailed description of SOCKS

This is a protocol that allows network applications interact through a firewall that blocks direct connection. In this case, a special intermediate server is used, access to which is allowed for both clients.

It transmits data received from the first client to the second and back. Unlike, through See what "SOCKS" is in other dictionaries: a proxy can allow any traffic (say, ). Besides See what "SOCKS" is in other dictionaries: transmits “clean” data without adding anything extra from itself, so it is more difficult to detect.

In everyday life See what "SOCKS" is in other dictionaries: Proxy is most often used to access sites that are prohibited. In this situation, it turns out that you are accessing the server, and not a prohibited Internet address, so the connection is not blocked.

The second reason why you can use these servers is for anonymity, namely hiding. In this case, it is not you who establishes the connection to the remote Internet server, but See what "SOCKS" is in other dictionaries: proxy, so the end server is unlikely to receive any information about you and your computer.

Afterword

That's it. I hope now you at least roughly understand what it is in general and why it may be necessary in general.

About how to specifically work with See what "SOCKS" is in other dictionaries: and other proxies to hide their IP will be written in a separate article, unless of course someone needs and is interested in it.

As always, if you have any questions, thoughts, additions, etc., then welcome to comment on this material.