fproxy

Info

fproxy is a generic tcp, load-balacing, IPv6-ready (reverse) proxy, which can operate on Unix sockets as well. It claims to be fast, since it avoids forking for each connection. Instead, it uses the epoll framework and splice provided by recent versions of Linux (support for kqueue on FreeBSD may come some day). Configuration is done through command line parameters only. For reconfiguration, you have to send a SIGQUIT to the running instance of fproxy to exit nicely, and then start with modified parameters. To avoid service downtime, you can run two or more instances in parallel, even if they are bound to the same cluster address (read: same listening socket). If you send SIGHUP, it will close and re-open its log and errorlog files. On SIGTERM it will exit immediately.
If compiled with -DUSE_SPLICE, fproxy will use splice() instead of read()/write(), but will also disable Unix sockets.
If compiled with -DUSE_LOCALTIME, timestamps will be in local time instead of GMT, although GMT avoids calling stat() on /etc/localtime every second.

Usage

fproxy V0.7 - non-forking tcp proxy using the epoll() framework
Compile time flags: DIETLIBC USE_SPLICE

fproxy [-o<logfile>] [-e<errorlog>] [-p<pidfile>] [-f] [-d] [-y<# bytes>]
       [-t<timeout>] [-g<grace>] [-s0] [-s1] [-s2] [-s3] [-s4]
       <cluster[:port]> [ ... ] -- <backend[:port]> [ ... ]

fproxy -h

  -h               this help ;-)
  -o<logfile>      use <logfile> for logging instead of /var/log/fproxy.log
  -e<errorlog>     use <errorlog> for error messages
                   instead of /var/log/fproxy.err
  -p<pidfile>      write process id into <pidfile>,
                   not into /var/run/fproxy.pid
  -f               do not fork and detach from controlling terminal;
                   do not use pidfile
  -d               do not fork and detach from controlling terminal;
                   do use neither logfile, errorlog, nor pidfile
  -y<# bytes>      open new connection to backend servers only if the client
                   wrote <# bytes>, eg. use -y6 for preventing a SYN attack
                   against a webserver (nb. strlen("GET /\n") = 6);
                   -y0 disables this feature, which is also the default
  -t<timeout>      drop idle client connections after <timeout> seconds;
                   -t0 disables timeout handling, which is also the default
  -g<grace>        reenables a failed backend after <grace> seconds;
                   defaults to 60 seconds
  -s0              select backends in a round robin fashion
  -s1              select backend with least connections handled so far
  -s2              select backend with least bytes (in + out) processed so far
  -s3              select backend with least connection time consumed so far
  -s4              (default) select backend in a weighted fashion, using number
                   of connections, processed bytes and connection time to
                   calculate to workload of each backend
  <cluster[:port]> path to Unix socket, or IPv4 or IPv6 address w/ optional
                   tcp port on which this machine accepts connections;
                   surround IPv6 addresses in square brackets;
                   port defaults to 80
  <backend[:port]> path to Unix socket, or IPv4 or IPv6 address w/ optional
                   tcp port to which client connections be proxied;
                   surround IPv6 addresses in square brackets;
                   port defaults to 80

 send SIGHUP  to reopen logfile and errorlog
 send SIGQUIT to exit nicely (don't accept any new client connections, wait
              for active connections to finish normally)
 send SIGTERM to exit immediatelly

Example

redirect all web traffic on localhost to three backends:

$ ./fproxy 127.0.0.1 -- 192.168.1.10 192.168.1.11 192.168.1.12

Log format

fproxy utilizes a httpd-like log format:

127.0.0.1 - - [31/Jul/2011:13:00:00 +0200] "POST 192.168.0.1" 200 848 8 940087 8
where:
127.0.0.1client's ip address
- -ident user and authuser are always unset
[31/Jul/2011:13:00:00 +0200]date, time, and offset from UTC when the client disconnected
POSTrequest method; GET if command line argument -y is zero, POST otherwise
192.168.0.1backend's ip address
200status code
848number of bytes received from the client
8number of seconds the client was connected
9400087number of bytes received from the backend
8number of seconds the backend was connected

Download