Appendix: SOCKS — A Basic Firewall

This appendix covers the following topics:

About SOCKS

SOCKS is a package consisting of a proxy server, client programs, and a library (libsocks) for adapting other applications into new client programs.

The original SOCKS was written by David Koblas (koblas@netcom.com). The SOCKS protocol has changed over time. The client library shipped as of printing corresponds to SOCKS v4.2. Since the server and the clients must use the same SOCKS protocol, this library doesn't work with servers of previous releases; clients compiled with these libraries won't work with older servers.

How to SOCKSify a client


Note: If your client is using UDP to transfer data, you can't use SOCKS. To see if your client uses UDP, search for the string SOCK_DGRAM in your source.

  1. At or near the beginning of main(), you can add a call to SOCKSinit().

    You can omit this step; the only reason for calling SOCKSinit() directly is to associate a name with your SOCKS client (rather than the generic “SOCKSclient” default string).

  2. Add the following options to your compile commands:
    -Dconnect=Rconnect -Dgetsockname=Rgetsockname \
    -Dbind=Rbind -Daccept=Raccept -Dlisten=Rlisten \
    -Drcmd=Rrcmd -Dselect=Rselect

    If you're using a Makefile, add these options to the definition of macro CFLAGS.

    These options replace calls to certain functions with versions that use the SOCKS server:

    Non-SOCKS function: SOCKS function:
    accept() Raccept()
    bind() Rbind()
    connect() Rconnect()
    getsockname() Rgetsockname()
    listen() Rlisten()
    rcmd() Rrcmd()
    select() Rselect()
  3. Link against the SOCKS library by adding -l socks to your link line.

    If you're using a Makefile, simply add this information to the definition of the macro LDFLAGS.

For most programs, the above steps should be sufficient to SOCKSify the package. If the above doesn't work, you may need to look at things a little more closely. The next section describes how the SOCKS library expects to be used.

What SOCKS expects

The SOCKS library covers only some of the socket functions, which must be called in a particular order:


Note: You must use TCP; SOCKS doesn't support UDP.

  1. The first socket function invoked must be either connect() or rcmd().
  2. If you call connect() on a nonblocking socket, no I/O can occur on that socket until another connect(), with the same arguments, returns -1 and sets errno to EISCONN. This is required even if you use select() on write to check the readiness of that socket.

    Note: While a connection is still pending, don't try to start another connection via connect(), or start a sequence of bind(), getsockname(), listen(), and accept().

  3. You must call bind() after a successful connect() call to a host for a specific service.
  4. You must follow the call to bind() by calls to getsockname(), listen(), and accept(), in that order.

Most client programs fit these assumptions very well and can be SOCKSified without changing the code at all using the steps described in How to SOCKSify a client.”

Some client programs use a bind() before each connect(). If the bind() is used to claim a specific port or a specific network interface, the current SOCKS library can't accommodate such use. Very often though, such a bind() call is there for no specific reason and may simply be deleted.