Appendix: SOCKS - A Basic Firewall

This appendix covers the following topics:

About SOCKS

SOCKS is a package consisting of a proxy server, client programs (rftp and rtelnet), and a library (socks3r.lib) 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.

Although no proxy server is shipped with this package, we've posted a free (unsupported) version on QUICS under /usr/free. Our version is called socks.tar.F - you may obtain the original package from:

ftp.nec.com:/pub/security/socks.cstc

How to SOCKSify a client

  1. If your client is using UDP to transfer data, SOCKS can't be used. To see if UDP is being used within your client, you can search for the string ``SOCK_DGRAM'' in your source.
  2. At or near the beginning of main(), you can add a call to SOCKSinit(). Note that this step can be omitted - the only reason for calling SOCKSinit() directly is to associate a name with your SOCKS client (rather than the generic ``SOCKSclient'' default string).
  3. To all cc lines, add the following:
    -Dconnect=Rconnect -Dgetsockname=Rgetsockname \
    -Dbind=Rbind -Daccept=Raccept -Dlisten=Rlisten \
    -Drcmd=Rrcmd -Dselect=Rselect

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

  4. 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 will describe how the SOCKS library expects to be used.

What SOCKS expects

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

  1. Everything must be done in TCP - SOCKS doesn't support UDP.
  2. The first socket function invoked must be either connect() or rcmd().
  3. If connect() is called on a nonblocking socket, no I/O can occur on that socket until another connect(), with the same arguments, returns with -1 and errno set to EISCONN. This is required even if select() on write is used to check the readiness of that socket.
    Note: While a connection is still pending, no attempts may be made to start another connection via connect() or the bind()-getsockname()-listen()-accept() sequence.

  4. The bind() function must be called after a successful connect() call to a host for a specific service.
  5. The bind() call must be followed by 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 the section above entitled ``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.