secnet - flexible VPN software * Introduction secnet allows large virtual private networks to be constructed spanning multiple separate sites. It is designed for the case where a private network connecting many hosts is 'hidden' behind a single globally-routable IP address, but can also be applied in other circumstances. It communicates entirely using UDP, and works well with gateways that implement network address translation. If you are installing secnet to join an existing VPN, you should read the 'INSTALL' file and your particular VPN's documentation now. You may need to refer back to this file for information on the netlink and comm sections of the configuration file. If you are thinking about setting up a new VPN of any size (from one providing complete links between multiple sites to a simple laptop-to-host link), read the section in this file on 'Creating a VPN'. * Creating a VPN XXX TODO * secnet configuration file format By default secnet on linux reads /etc/secnet/secnet.conf. The default may be different on other platforms. This file defines a dictionary (a mapping from keys to values) full of configuration information for secnet. Two keys must be defined in this file for secnet to start. One is "system", a dictionary containing systemwide control parameters. The other is "sites", a list of all the sites that you intend to communicate with. The configuration file has a very simple syntax; keys are defined as follows: key definition; or key = definition; (the "=" is optional) Keys must match the following regular expression: [[:alpha:]_][[:alnum:]\-_]* i.e. the first character must be an alpha or an underscore, and the remaining characters may be alphanumeric, '-' or '_'. Keys can be defined to be a comma-separated list of any of the following types: a boolean a string, in quotes a number, in decimal a dictionary of definitions, enclosed in { } a "closure", followed by arguments a path to a key that already exists, to reference that definition Note that dictionaries can be nested: a key in one dictionary can refer to another dictionary. When secnet looks for a key in a particular directory and can't find it, it looks in the dictionary's lexical 'parents' in turn until it finds it (or fails to find it at all and stops with an error). Definitions can refer to previous definitions by naming them with a path. Paths are key1/key2/key3... (starting from wherever we find key1, i.e. in the current dictionary or any of its parents), or alternatively /key1/key2/key3... (to start from the root). Definitions cannot refer to future definitions. Example: a=1; b=2; c={ d=3; e=a; }; f={ a=4; g=c; }; The following paths are valid: a is 1 b is 2 c is a dictionary: c/d is 3 c/e is 1 f is a dictionary: f/a is 4 f/g is a dictionary: f/g/d is 3 f/g/e is 1 Note that f/g/e is NOT 4. In a future version of secnet it will also be permissible to list other dictionaries before a dictionary definition, eg. {definitions}. These will be searched in order for keys, before the lexical parent. (This is not yet implemented) Elements that are lists are inserted into lists in definitions, not referenced by them (i.e. you can't have lists of lists). Some closures may be followed by an argument list in ( ), and may return any number of whatever type they like (including other closures). Some types of closure (typically those returned from invokations of other closures) cannot be invoked. closure { definitions } is short for closure({definitions}). The main body of secnet, and all the additional modules, predefine some keys in the root dictionary. The main ones are: yes, true, True, TRUE: the boolean value True no, false, False, FALSE: the boolean value False makelist: turns a dictionary (arg1) into a list of definitions (ignoring the keys) readfile: reads a file (arg1) and returns it as a string Keys defined by modules are described below, in the module documentation. Other configuration files can be included inline by writing "include filename" at the start of a line. After the configuration file is read, secnet looks for particular keys in configuration space to tell it what to do: system: a dictionary which can contain the following keys: log (log closure): a destination for system messages userid (string): the userid for secnet to run as once it drops privileges pidfile (string): where to store its PID sites: a list of closures of type 'site', which define other tunnel endpoints that secnet will attempt to communicate with * secnet command line options XXX TODO * secnet builtin modules ** resolver Defines: adns (closure => resolver closure) adns: dict argument config (string): optional, a resolv.conf for ADNS to use ** random Defines: randomsrc (closure => randomsrc closure) randomsrc: string[,bool] arg1: filename of random source arg2: if True then source is blocking ** udp Defines: udp (closure => comm closure) udp: dict argument port (integer): UDP port to listen and send on buffer (buffer closure): buffer for incoming packets authbind (string): optional, path to authbind-helper program ** util Defines: logfile (closure => log closure) syslog (closure => log closure) sysbuffer (closure => buffer closure) logfile: dict argument filename (string): where to log to class (string list): what type of messages to log { "debug-config", M_DEBUG_CONFIG }, { "debug-phase", M_DEBUG_PHASE }, { "debug", M_DEBUG }, { "all-debug", M_DEBUG|M_DEBUG_PHASE|M_DEBUG_CONFIG }, { "info", M_INFO }, { "notice", M_NOTICE }, { "warning", M_WARNING }, { "error", M_ERROR }, { "security", M_SECURITY }, { "fatal", M_FATAL }, { "default", M_WARNING|M_ERROR|M_SECURITY|M_FATAL }, { "verbose", M_INFO|M_NOTICE|M_WARNING|M_ERROR|M_SECURITY|M_FATAL }, { "quiet", M_FATAL } syslog: dict argument ident (string): include this string in every log message facility (string): facility to log as { "authpriv", LOG_AUTHPRIV }, { "cron", LOG_CRON }, { "daemon", LOG_DAEMON }, { "kern", LOG_KERN }, { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, { "lpr", LOG_LPR }, { "mail", LOG_MAIL }, { "news", LOG_NEWS }, { "syslog", LOG_SYSLOG }, { "user", LOG_USER }, { "uucp", LOG_UUCP } sysbuffer: integer[,dict] arg1: buffer length arg2: options: lockdown (boolean): if True, mlock() the buffer ** site Defines: site (closure => site closure) site: dict argument local-name (string): this site's name for itself name (string): the name of the site's peer netlink (netlink closure) comm (comm closure) resolver (resolver closure) random (randomsrc closure) local-key (rsaprivkey closure) address (string): optional, DNS name used to find our peer port (integer): mandatory if 'address' is specified: the port used to contact our peer networks (string list): networks that our peer may claim traffic for key (rsapubkey closure): our peer's public key transform (transform closure): how to mangle packets sent between sites dh (dh closure) hash (hash closure) key-lifetime (integer): max lifetime of a session key, in ms [one hour] setup-retries (integer): max number of times to transmit a key negotiation packet [5] setup-timeout (integer): time between retransmissions of key negotiation packets, in ms [1000] wait-time (integer): after failed key setup, wait this long (in ms) before allowing another attempt [20000] renegotiate-time (integer): if we see traffic on the link after this time then renegotiate another session key immediately [depends on key-lifetime] keepalive (bool): if True then attempt always to keep a valid session key log-events (string list): types of events to log for this site unexpected: unexpected key setup packets (may be late retransmissions) setup-init: start of attempt to setup a session key setup-timeout: failure of attempt to setup a session key, through timeout activate-key: activation of a new session key timeout-key: deletion of current session key through age security: anything potentially suspicious state-change: steps in the key setup protocol packet-drop: whenever we throw away an outgoing packet dump-packets: every key setup packet we see errors: failure of name resolution, internal errors all: everything (too much!) netlink-options (string list): options to pass to netlink device when registering remote networks soft: create 'soft' routes that go away when there's no key established with the peer allow-route: allow packets from our peer to be sent down other tunnels, as well as to the host ** transform Defines: serpent256-cbc (closure => transform closure) ** netlink Defines: null-netlink (closure => netlink closure) null-netlink: dict argument name (string): name for netlink device, used in log messages networks (string list): networks on the host side of the netlink device exclude-remote-networks (string list): networks that may never be claimed by any remote site using this netlink device local-address (string): IP address of host's tunnel interface secnet-address (string): IP address of this netlink device mtu (integer): MTU of host's tunnel interface ** slip Defines: userv-ipif (closure => netlink closure) userv-ipif: dict argument userv-path (string): optional, where to find userv ["userv"] service-user (string): optional, username for userv-ipif service ["root"] service-name (string): optional, name of userv-ipif service ["ipif"] buffer (buffer closure): buffer for assembly of host->secnet packets plus generic netlink options, as for 'null-netlink' ** tun Defines: tun (closure => netlink closure) [only on linux-2.4] tun-old (closure => netlink closure) tun: dict argument device (string): optional, path of TUN/TAP device file ["/dev/net/tun"] interface (string): optional, name of tunnel network interface ifconfig-path (string): optional, path to ifconfig command route-path (string): optional, path to route command buffer (buffer closure): buffer for host->secnet packets plus generic netlink options, as for 'null-netlink' tun-old: dict argument device (string): optional, path of TUN/TAP device file ["/dev/tun*"] interface (string): optional, name of tunnel network interface interface-search (bool): optional, whether to search for a free tunnel interface (True if 'device' not specified, otherwise False) ifconfig-path (string): optional, path to ifconfig command route-path (string): optional, path to route command plus generic netlink options, as for 'null-netlink' ** rsa Defines: rsa-private (closure => rsaprivkey closure) rsa-public (closure => rsapubkey closure) rsa-private: string[,bool] arg1: filename of SSH private key file (version 1, no password) arg2: whether to check that the key is usable [default True] rsa-public: string,string arg1: encryption key (decimal) arg2: modulus (decimal) ** dh Defines: diffie-hellman (closure => dh closure) diffie-hellman: string,string[,bool] arg1: modulus (hex) arg2: generator (hex) arg3: whether to check that the modulus is prime [default True] ** md5 Defines: md5 (hash closure) ** sha1 Defines: sha1 (hash closure)