home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Practical UNIX & Internet Security

Practical UNIX & Internet SecuritySearch this book
Previous: 22.3 tcpwrapper Chapter 22
Wrappers and Proxies
Next: 22.5 UDP Relayer
 

22.4 SOCKS

SOCKS is a system that allows computers behind a firewall to access services on the Internet. The program allows you to centrally control how programs on your organization's network communicate with the Internet. With SOCKS , you can allow specific services to specific computers, disable access to individual hosts on the Internet, and log as much or as little as you want.

SOCKS was originally written by David Koblas and Michelle Koblas. It has since been extended by Ying-Da Lee at NEC 's Systems Laboratory, and a commercially supported version is available from NEC . The name SOCKS stands for " SOCK -et-S." According to the SOCKS FAQ , "it was one of those `development names' that never left."

SOCKS consists of two parts:

SOCKS server

A program that is run on a host that can communicate directly with both the Internet and the internal computers on your network (e.g., the firewall's gate).

SOCKS client programs

Specially modified Internet client programs that know to contact the SOCKS server instead of sending requests directly to the Internet.

The standard SOCKS distribution comes with client programs for finger , ftp , telnet , and whois . SOCKS also includes a library you can use to create other SOCKS clients at will. Furthermore, many programs, such as NCSA Mosaic, include provisions for using SOCKS to negotiate firewalls.

SOCKS is available for most versions of UNIX , including SunOS, Sun Solaris, IRIX , Ultrix, HP-UX , AIX , Interactive Systems UNIX , OSF /1, Net BSD , UNIX Ware, and Linux. A version called PC SOCKS , by Cornell Kinderknecht, is available for Microsoft Windows. A Macintosh version is under development.

22.4.1 What SOCKS Does

The SOCKS client software works by replacing calls to the UNIX socket functions - connect (), getsocketname (), bind (), accept (), listen () and select () - with its own versions of these functions. In practice, this replacement is done by adding a few macro definitions to the CFLAGS in the Makefile of the program that is used to compile the network client program, and then linking the resulting program with the SOCKS library.

When a SOCKS -modified client attempts to connect to a server on the Internet, the SOCKS library intercepts the connection attempt and instead opens up a connection to the SOCKS server. After the connection is established, the SOCKS client sends through the following information:

  • Version number

  • Connect request command

  • Port number to which the client requested to connect

  • IP address to which the client requested to connect

  • Username of the person initiating the request

The SOCKS server then checks its access control list to see if the connection should be accepted or rejected. If the connection is accepted, the server opens up a connection to the remote machine and then relays all information back and forth. If the connection is rejected, the server disconnects from the client. This configuration is shown graphically in Figure 22.1 .

Figure 22.1: : Using SOCKS for proxying

Figure 22.1

SOCKS can also be used to allow computers behind a firewall to receive connections. In this case, a connection is opened to the SOCKS server, which in turn gets ready to accept connections from the Internet.

SOCKS works only with TCP/IP ; for UDP services (such as Archie), use UDP Relayer as described later in this chapter.

22.4.2 Getting SOCKS

Socks may be freely downloaded from the Internet. The address is:

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

If you operate two nameservers to hide information from the Internet, you will also need to download the file Rgethostbyname.c . This file contains a function that can be used to query multiple nameservers to resolve a hostname.

There is a mailing list devoted to SOCKS and related issues. To join it, send the message "subscribe socks your-email-address " to majordomo@syl.dl.nec.com.

NOTE: This section discusses SOCKS Version 4. At the time of this writing, SOCKS Version 5 was under development. New features in SOCKS 5 include strong authentication, authentication method negotiation, message integrity, message privacy, and support for UDP applications.

22.4.3 Getting SOCKS Running

After you have downloaded the system, you will need to follow these steps to get the system running:

  1. Unpack the SOCKS distribution.

  2. Decide whether you wish to have the SOCKS daemon started automatically when the system starts (boot time), or started by inetd when each SOCKS request is received.

    The advantage of having the daemon start automatically at system start-up is that the daemon will need to read its configuration file only once. Otherwise, the configuration file will have to be read each time a SOCKS connection is requested. We recommend that you have SOCKS started at boot time.

  3. Edit the file Makefile in the main SOCKS directory and the file include/socks.h to reflect the policy of your site. Be sure to edit the variables found in Table 22.4 .

    Table 22.4: Variables

    Variable

    Location

    Purpose/Setting

    SOCKS_DEFAULT_SERVER

    include/socks.h

    Set with the hostname of the computer that hosts the sockd daemon.

    SOCKS_DEFAULT_NS

    include/socks.h

    Set if the clients inside your firewall cannot look up the IP addresses of external hosts.

    NOT_THROUGH_INETD

    include/socks.h

    Set if socksd will be started automatically at system boot.

    SOCKS_CONF

    include/socks.h

    Location of the SOCKS configuration file for client machines.

    SOCKD_CONF

    include/socks.h

    Location of the SOCKS configuration file for the sockd daemon.

    MULTIHOMED_SERVER

    include/socks.h

    Set if sockd will be running on a multihomed server (a gate computer with two Ethernet ports).

    SOCKD_ROUTE_FILE

    include/socks.h

    Location of the SOCKS routing file, for use with multihomed servers.

    FACIST

    Makefile

    Causes SOCKS FTP client to log names of all files transferred.

    FOR_PS

    Makefile

    Causes sockd to display information about its current activity in the output from the ps command.

    SERVER_BIN_DIR

    Makefile

    Directory containing the sockd daemon.

    CLIENTS_BIN_DIR

    Makefile

    Directory containing the SOCKS client programs.

  4. Compile SOCKS with a suitable C compiler.

  5. Verify that sockd compiled properly and with the correct configuration by running sockd with the -ver option:

    % 
    ./sockd -ver
    
     CSTC single-homed, stand-alone SOCKS proxy server version 4.2.
     Supports clients that use Rrcmd().
    %
  6. Become superuser.

  7. Install the SOCKS daemon in the location that you specified in the Makefile ; you may be able to do this by typing " make install.server ".

  8. Add the SOCKS service to your /etc/services file. It should look like this:

    socks			1080/tcp
  9. Now you need to set up the SOCKS configuration file. See the section called "The SOCKS Server Configuration File: /etc/sockd.conf below.

  10. If you decided to have SOCKS start automatically at system boot time, modify your boot configuration files (either by adding a few lines to /etc/rc.local or by creating a new file in /etc/rc2.d/). You can set the start-up by adding a few lines that look like this:

    # Start SOCKS server
    if [ -f /usr/etc/sockd ]; then
          (echo -n "sockd... ")
                    >/dev/console
          /usr/etc/sockd >/dev/console 2>&1
    fi
  11. If you decided to have SOCKS start from inetd (and you probably don't want to do this), add this line to the /etc/inetd.conf file:

    socks stream tcp nowait nobody /usr/etc/sockd 
  12. Start the sockd daemon manually, or reset inetd.

  13. Test the system.

22.4.4 SOCKS and Usernames

SOCKS permits you to allow or deny access to Internet services based on both IP address and the username of the person on the local network making the request. There are two ways that SOCKS can determine the username of a person on the internal network:

  1. Normally, a SOCKS client will send through the username of the person initiating the connection as part of the SOCKS protocol.

  2. SOCKS can also use the ident protocol. For more information, see the section "Identification Protocol (auth) (TCP Port 113)" in Chapter 17.

22.4.5 SOCKS Identification Policy

The choice of identification policy is determined by the way in which the sockd program is invoked and by the /etc/sockd.conf configuration file.

Normally, sockd is invoked with one of three options:

sockd [-ver | -i | -I]

These options have the following meanings:

-ver

Prints the sockd configuration information and exits.

-I

Forces SOCKS to use the ident protocol. Denies access to any client that is not running the ident protocol. Also denies access to clients for which the username returned by the ident protocol does not match the username provided by the SOCKS protocol.

-i

Less restrictive than -I . Denies access to clients when the username returned by the ident protocol is different from the username returned by the SOCKS protocol, but allows use of sockd by users who do not have ident running on their systems.

The identification options -i and -I can be overridden by a statement in the SOCKS configuration file, /etc/sockd.conf.

22.4.6 The SOCKS Server Configuration File: /etc/sockd.conf

The sockd configuration file, /etc/sockd.conf, allows you to control which TCP/IP connections are passed by the sockd daemon. As the daemon usually runs on a computer that has access to both your organization's internal network and the Internet, the sockd.conf file controls, in part, which services are passed between the two.

The sockd program doesn't know the difference between your internal and external networks. It simply receives connections, determines the parameters of the connections (username, source, requested destination, and TCP/IP service), then scans rules in the /etc/sockd.conf file to determine if the connections should be permitted or denied.

The /etc/sockd.conf file is an ASCII text file. Each line consists of a rule to either allow connections or reject (deny) them. The sockd program scans the file from the first line to the last line until a match is found. When a match is found, the action specified by the line is followed.

Lines in the /etc/sockd.conf file may be up to 1023 characters long. Each line has the following form:

[allow | deny] [?=auth] [*=username(s)|filename(s)] 		
source-address source-mask 		
[destination-address destination-mask] 		
[operator destination-port] 		
[: shell-command]

Fields are separated by spaces or tabs. If a number sign (#) is found on the line, everything after the number sign is assumed to be a comment, except as noted below.

If an incoming TCP/IP connection does not match any of the lines in the /etc/sockd.conf configuration file, it is rejected.

Here is an explanation of the fields:

allow | deny

Specifies whether a connection matching the rule on this line should be allowed or denied.

?=auth

If present, this field allows you to override the identification policy specified when the program was invoked. Specify "?=I" to cause sockd to reject the connection if the user on the client machine is not running ident , or if the name returned by ident is not the same as the username sent by the SOCKS client. Specify "?=i" to cause sockd to reject the connection if the name returned by ident is not the same as the name sent by the SOCKS client.

*=username(s)|filename(s)

If present, causes the rule to match a particular username. You can also specify a filename, in which case the usernames are read out of the file (one username per line). Here are some examples:

Username

Result

*= simsong

Matches the user simsong .

*= fred,julie

Matches the users fred and julie .

*= /etc/goodusers

Matches anybody in the file /etc/goodusers.

*= fred,/etc/goodusers

Matches the user fred and all of the users in the file /etc/goodusers.

source-address source-mask

The address and mask allow you to specify a match for a single IP address or a range of addresses. The source-address may be either an IP address in the form hhh.iii.jjj.kkk or an Internet hostname; the source-mask must be an IP address mask in the form hhh.iii.jjj.kkk.

The source-mask specifies which bits of the source-address should be compared with the actual address of the incoming IP connection. Thus, a source-mask of 0.0.0.0 will cause the rule to match any IP address, while a source-mask of 255.255.255.255 will only allow for an exact match. These and other possibilities are explored in the table below:

source-address

source-mask

Result

18.80.0.1

255.255.255.255

Matches the host 18.80.0.1.

204.17.190.0

255.255.255.0

Matches any host on the subnet 204.17.190.

10.80.0.1

255.0.0.0

Matches any host on net 10.

0.0.0.0

0.0.0.0

Matches every host on the Internet.

operator destination-port

These optional arguments allow you to specify a particular TCP service or a range of TCP/IP ports. For example, you can specify "le 1023" to select all of the UNIX "privileged" ports, or you can specify "eq 25" to specify the SMTP port. The following table lists all of the operators:

operator

Meaning

eq

Equal to

neq

Not equal to

lt

Less than

le

Less than or equal to

gt

Greater than

ge

Greater than or equal to

: shell-command

You can specify a command that will be executed when the line is matched. The command line is executed by the Bourne shell (/bin/sh). Before the line is executed, the following substitutions are made:

Token

Replaced With

%A

The fully qualified domain name (FQDN) of the client (the computer contacting sockd ), if it can be determined; otherwise, the computer's IP address

%a

The IP address of the client

%c

The direction of the connection ; replaced with connect if the client is attempting to make an outgoing connection, or bind if the client is waiting for an incoming connection

%p

The process ID of sockd

%S

The service name, if it can be determined from the /etc/services database; otherwise, the destination port number

%s

The destination port number

%U

The username reported by identd

%u

The username sent by the client program

%Z

The FQDN name of the destination host, if it can be determined; otherwise, the computer's IP address

%z

The IP address of the destination computer

%%

"%"

Obviously, token expansions that require that sockd look up a value in a database (such as %A, %S, and %Z) will take longer to execute than token expansions that merely report an IP or port number (such as %a, %s and %z).

This example command runs finger to determine the users on a particular computer, and then sends the results to the root account of the computer that is running sockd:

/usr/ucb/finger @%A | /bin/mailx -s 'SOCKS: rejected %u@%A' root

22.4.6.1 #NO_IDENTD and #BAD_ID

In addition to the pattern matching described above, sockd allows you to specify rules that will match any computer contacting the sockd daemon which is not running the ident protocol, or for which the username returned by the ident protocol is different from the username provided in the initial sockd contact. These lines have the form:

#NO_IDENTD: command
#BAD_ID: command

22.4.6.2 Example /etc/sockd.conf configuration files

Here are some example lines from an /etc/sockd.conf configuration file. The configuration file is designed to protect an organization that has placed a set of UNIX workstations on IP subnet 204.99.90.

deny

204.99.90.0 255.255.255.0 204.99.90.0 255.255.255.0

This initial rule disallows access to the internal network from internal computers using SOCKS . (Why tie up the SOCKS server if you don't need to?)

allow

0.0.0.0 0.0.0.0 204.99.90.100 255.255.255.255 eq 25

Allows connections to port 25 ( SMTP ) of the machine 204.99.90.100. This allows incoming electronic mail to that network.

allow

204.99.90.100 255.255.255.255 0.0.0.0 0.0.0.0 eq 25

Allows outgoing connections from the machine 204.99.90.100 to port 25 of any computer on the Internet. This rule allows the organization to send mail to outside computers.

allow

204.99.90.0 255.255.255.0 0.0.0.0 0.0.0.0

Allows outgoing connections from any host on subnet 204.99.90 to any computer on the Internet. If you have this rule, the previous rule is unnecessary.

deny

0.0.0.0 0.0.0.0 204.99.90.255 255.255.255.000 eq 23 : \

safe_finger @%A |/bin/mailx -s 'Telnet denied from %U/%A' root

This rather complex rule denies any attempted login to the organization's internal network. In addition to stopping the logins, it also does a finger of the computer from where the attempt is coming and sends email to the root account of the computer running sockd . If the remote machine is running the ident protocol, the username will be sent as well.

NOTE: Do not use reverse finger for logging contacts on the finger port (port 79). Otherwise, a loop may result, with two sockd daemons continually attempting to finger each other until they are manually shut down or the disks fill up.

deny

0.0.0.0 0.0.0.0 204.99.90.0 255.255.255.0

Denies all other connections to the subnet 204.99.99. Strictly speaking, this rule is not necessary, as a connection that does not specifically match the "allow" rules above will be rejected.

22.4.7 SOCKS Client Configuration File: /etc/socks.conf

Each client that wishes to use the sockd server must also have its own configuration file. The configuration file has a syntax that is similar to, but slightly different from, the syntax of the /etc/sockd .conf file.

When a SOCKS client attempts to make an outgoing connection to another host on the Internet, or when it calls the Rbind() function to accept an incoming connection, the SOCKS library scans the /etc/socks.conf configuration file line by line, starting with the first line, until it finds a line that matches the requested connection. The library then performs the action that is specified in the file.

Each line in the file can have the following form:

deny [*=username(s)|filename(s)] destination-address destination-mask  		
	[operator destination-port] 		
	[: shell-command]

direct [*=username(s)|filename(s)] destination-address destination-mask  		
	[operator destination-port] 		
[: shell-command]

sockd [@=serverlist] [*=username(s)|filename(s)]  		
	destination-address destination-mask  		
	[operator destination-port] 		
	[: shell-command]

Most of these fields are similar to those in the /etc/sockd.conf file. The differences are described below:

deny

The deny operator specifies that a TCP/IP connection that matches the line should be denied. (Remember, even though this connection will prevent the SOCKS package from making a connection to the site in question, the user may still have the option of connecting to the site using a client program that has not been linked with the SOCKS library. Thus, the deny operator running on the client computer is not a substitute for a suitable firewall choke. For more information on firewalls, see Chapter 21, Firewalls .)

direct

The direct operator tells the SOCKS library that the TCP/IP connection should be sent directly through.

sockd [@=serverlist]

The sockd operator tells the SOCKS library that the TCP/IP connection should be sent to the sockd daemon, which presumably will then pass it through to the outside network.

The name of the host that is running the sockd server is compiled into the SOCKS library. It may also be specified on the command line, the SOCKS_SERVER environment variable, or it may be specified in the /etc/socks.conf configuration file using the @ argument. More than one server may be specified by separating the names with a comma, such as:

sockd @=socks1,socks2,sock3 0.0.0.0 0.0.0.0

In SOCKS version 4.2, the servers are tried in the order in which they appear in the configuration file. Thus, you can specify different servers in different orders on different clients to distribute the load. (A more intelligent approach, though, would be for the servers to be tried in random order.)

22.4.7.1 Example /etc/socks.conf file

This simple configuration file, for an organization administrating the subnet 204.90.80, specifies that all connections to organization's internal subnet should go direct, while all connections to the outside network should go through the SOCKS server:

direct 204.90.80.0 255.255.255.0
sockd @=socks-server 0.0.0.0 0.0.0.0