SOCKD.CONF(5)

πŸ“¦
version 1.4.4 Β· 2 versions
, in alpine 3.24, arch rolling, epel 10, epel 9, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable

πŸ’– SOCKD.CONF(5) πŸ’– β€” the manual page for the Dante server config file, aka sockd.conf

File Formats Manual Β· SOCKD.CONF(5) Β· part 1 of 6, bestie, we're just getting started


✨ NAME ✨

sockd.conf β€” the syntax of the Dante server configuration file πŸŽ€


🌸 DESCRIPTION 🌸

Okay so, the config file for the Dante server is the girlboss that controls both access controls and logging. It's split into three parts:

  • server settings
  • rules
  • routes
🚨 Not me being serious for one second: server settings must come before rules and routes. No exceptions, periodt.

And if you wanna comment a line out, you just use the standard comment character #. Classic. πŸ’…


πŸ‘‘ SERVER SETTINGS πŸ‘‘

These control the generic behaviour of the server, the whole vibe of it. Each keyword is separated from its value by a : character. Slay.

The following keywords are available:

  • clientmethod β€” A list of acceptable authentication methods for client-rules, listed in order of preference. These are the authentication methods that get checked immediately after the SOCKS client has connected to Dante, and before any socks-negotiation has started.

Supported values are pam.address, pam.any, none, and rfc931 .

For all methods the authentication will be based on solely on the IP-address of the client, possibly in combination with a rfc931 ("ident") lookup towards the host the client is running on.

Any credentials provided during this pass will also be available for use in later socks-rules, when the socks-request from the client is evaluated. 🫢

The default value for this keyword is all methods that may be necessary for the later socks-based authentication methods, as specified as values to the global socksmethod keyword. Normally you should not need to set this keyword, as Dante will set it to the correct value by it self. It's giving self-sufficient. ✨

  • compatibility β€” With the sameport keyword, the server attempts to use the same port on the server's external side as the client used on the server's internal side. This is normally the default, but when this option is given it will be done with privileged ports also, meaning if a client connects to Dante from a privileged port, Dante will attempt to connect to the target destination from a privileged port too.
😭 There can be security issues involved with this, so normally this option should not be set. Consider this your vibe check.

The draft-5.05 keyword will enable usage of parts of the socks v5-05 draft. The only feature from this draft that Dante supports is the "USECLIENTSPORT" extension. Note that there is a conflicting interpretation of this extension, so enabling it might prevent clients using the conflicting interpretation from working correctly. Only affects UDP. πŸ™ˆ

  • cpu β€” The CPU settings for the various type of Dante processes. Note that the possibility for configuring these settings depend on the platform Dante is running on. Not all platforms may provide support for these type of CPU settings.

There are four process types: mother, negotiate, request, and io.

The currently supported options are:

  • schedule.<process type>: <scheduling policy>/<priority>.

Example:

cpu.schedule.mother: SCHED_FIFO/20

The above requests that the kernel schedules the mother process(s) using a first-in, first-out policy, at priority 20.

The default is to not request any specific scheduling.

  • mask.<process type>: <cpu id 1> [cpu id 1 ...]/any.

Example:

cpu.mask.mother: any

Example:

cpu.mask.io: 0 1

The mask gives control over the CPU/cores on which the different process types will run. Specifying the default (all) allows the process type to run on any CPU id. Specifying one or more numeric CPU id limits the process to that set of CPUs.

The cpu keywords (schedule and mask) should in most cases not be necessary. If they are to be used, the io processes are where most of the work is done and adjusting the priority or CPU usage is what is likely to have the most significant performance effect client performance and overhead from the server. The other processes are primarily used during connection/session establishment and changes to settings for the non-io process types will primarily affect these operations.

The default is to not limit processes to any specific cpu.

  • debug β€” Print debug info to the logs. The value sets the debug level. πŸ”
  • errorlog β€” This value can be set to receive only error-related logoutput. Note that this does not include client-specific errors, but only more serious "global" errors.

The possible values are the same as for the logoutput keyword mentioned below.

The intent is to have a special place that only serious errors are logged so that they can discovered quickly. The default is to not have any special place to log errors. 🚨

  • external β€” The address to be used for outgoing connections. The address given may be either an IP address or an interface name. Can be given multiple times for different addresses.
  • external.log.<loglevel>.error β€” See internal.log.<loglevel>.error. This option has an identical syntax and semantics, but applies to error related to the external interface side. πŸ‘―
  • external.protocol β€” By default Dante will use the address families specified and available, and there is no need to set this keyword.

In some cases the operator may however wish to specify an address in a form that may include more than one address family, yet not wish for Dante to use all the address families available for that address form.

This will typically happen if the operator wishes to specify that Dante should use the addresses on a network interface card which has both IPv4 and IPv6 addresses configured, yet the operator wishes Dante to only use one of these two address families. The operator can then specify the address family he wants Dante too look for when expanding the interface name for IP-addresses to use.

Valid values for this keyword are: ipv4 and ipv6, indicating that Dante should only use the IPv4 address family or only the IPv6 address family, respectively. The default is to use both families, if available.

A corresponding keyword exists for the internal side (see internal.protocol).

  • external.rotation β€” If more than one external address is given, this governs which of the given addresses is selected as the source address for outgoing connections/packets. Note that regardless of which external rotation value is used, all external addresses that are to be used must be listed via the external keyword first.

Valid values are none (the default), route, and same-same.

  • none indicates the first address on the list of external addresses should be used.
  • route indicates the kernels routing table should be consulted to find out what the source address for a given destination will be, and might require you to set user.privileged to root. Note that route might create problems for ftp-clients using active ftp if the Dante bind extension is enabled for the ftp-client.
  • same-same indicates the source address for a given destination should be the same address as the Dante server accepted the clients connection on. πŸͺž
  • internal β€” The internal addresses. Connections will only be accepted on these addresses. The address given may be either an IP address or an interface name.
  • internal.log.<loglevel>.error β€” Specifies that certain system call failures, listed as symbolic errno values, or certain dns failures, listed as symbolic libresolv failure-codes, should be logged, possibly an extra time, at the log-level log-level.

Note that this only applies to errors on the internal interface side only.

A corresponding keyword exists for the external side (see external.log).

In addition to the standard errno and getaddrinfo(3) error symbols, the following special symbols are accepted:

  • no-route β€” Any error related to no route.
  • dns-any β€” Any error related to DNS/hostname-resolving.
  • system-any β€” Any system error. I.e., any errno value.
  • internal.protocol β€” See external.protocol. This option has an identical syntax and semantics, but applies to the internal interface, for addresses to listen to connections from clients on.
  • libwrap.hosts_access β€” If the server is compiled with libwrap support, determines whether the hosts_access() function should be used for access control. When enabled by setting this value to yes, the libwrap library determines if TCP connections or UDP packets should be immediately dropped or not, typically by consulting /etc/hosts.allow and /etc/hosts.deny. These checks are applied to all traffic, before the rule processing starts. The default value is no (disabled). πŸšͺ
  • logoutput β€” This value controls where the server sends logoutput. It can be set to syslog[/facility], stdout, stderr, a filename, or a combination. The default is nowhere. Note that if errorlog is also set, there will be a overlap between what is logged there (errors only), and what will be logged here (errors, and everything else). πŸ˜…
  • socksmethod β€” A list of acceptable authentication methods for socks-rules, listed in order of preference. It is thus important that you specify these in the desired order, normally with the more secure methods first.

Supported values are bsdauth, gssapi, none, pam.any, pam.address, pam.username, rfc931, and username,

If a method is not set in this list it will never be selected. The default is no methods, which means all socks-requests will be blocked. πŸ’€

See the section on AUTHENTICATION METHODS for an explanation of the different methods and their meaning.

  • srchost β€” This keyword allows you to configure a few options that relate to the srchost, i.e., the host the Dante server accepts the connections from.

With the nodnsmismatch keyword, the server will not accept connections from addresses having a mismatch between DNS IP address and hostname. Default is to accept them. 🧚


…and bestie, that's only the beginning. Part 2 is coming, don't go anywhere πŸ’–

  • nodnsunknown β€” flip this on and the server will not accept connections from addresses that have no DNS record. Default? It accepts them. So by default it's just vibing, no cap.
  • checkreplyauth β€” with this, the server checks that the authentication on bind-replies and udp-replies matches whatever is set in the rule and the global socksmethod. Normally you do not want auth on replies, because replies are literally replies being sent to the socks-clients from non-socks clients, so only a limited set of authentication methods are even possible. 😭

The methods possible for TCP are the ones that don't involve the socks protocol in any way at all, and they're listed in the clientmethod section mentioned earlier. For UDP-replies? No methods can be used. That's it. That's the list. πŸ’€

Default is not to check the authentication on replies.

  • timeout.connect β€” how many seconds the server will wait for a connect that was initiated on behalf of the socks-client to complete. Default is 30. Set it to 0 and it'll use the system's default instead.
  • timeout.io β€” how many seconds an established connection is allowed to be idle. Default is 0, meaning forever. Also go peek at the -n option in the sockd(8) manpage, bestie.

You can set individual timeouts for TCP and UDP by suffixing io with .<protocolname>, i.e. timeout.io.tcp or timeout.io.udp.

You can also set individual timeouts inside rules, using that exact same syntax. Whatever timeout you set in the rule overrides the default timeouts for the clients matching that rule. ✨

  • timeout.negotiate β€” how many seconds a client can spend negotiating with the Dante server for a socks session before Dante closes the connection on them. Default is 30. Set it to 0 for forever, though that is strongly discouraged β€” like, don't. πŸ™ˆ
  • timeout.tcp_fin_wait β€” the timeout for the equivalent of TCP's FIN-WAIT-2. Default is 0, which means use the system's default (normally, no timeout).
  • udp.connectdst β€” turns on or off whether the server should attempt connecting UDP sockets to the destination. Valid values are yes and no.

The default is yes, which improves UDP performance, but it may not be compatible with some UDP-based application protocols, because it means the server can only receive packets from the destination address.

The socket will only remain connected as long as the client only sends UDP packets to one destination address. If packets get sent to multiple destinations, the socket will no longer remain connected and replies can be received from any destination. Main character energy from that socket honestly. πŸ’…


🌸 Userids 🌸

On platforms that provide a privilege-model supported by Dante, the Dante server does not use userid-switching via the seteuid(2) system call. On other platforms, it is prudent to set the userid the Dante server uses to appropriate values. The Dante server can use two different userids, or three if it was compiled with libwrap support. Here they are, bestie:

  • user.privileged β€” the username used for doing privileged operations. If you need special privileges to read the sockd.conf file or to write the sockd.pid file (you can create it manually before starting sockd, just saying), or if you have anything in your config that requires binding privileged TCP/UDP ports (ports below 1024), or if you use some sort of password-based authentication, this probably needs to be set to root.

If none of that applies to you, you can probably set it to the same value as user.unprivileged. 🫢

  • user.unprivileged β€” the user the server runs as most of the time. This should be an id with as little privileges as possible. It is recommended that a separate userid is created for this purpose. Periodt.
  • user.libwrap β€” the user used to execute libwrap commands. Normally this should be the same as user.unprivileged.

🧚 MODULES 🧚

The following modules are supported by Dante. Modules are purchased separately from Inferno Nettverk A/S and may add extra functionality that most users don't need. Peep the Dante homepage for more info. πŸ’–

  • bandwidth β€” this module gives you control over how much bandwidth the Dante server uses on behalf of different clients or to different targets.
  • redirect β€” this module gives you control over what addresses the server will use on behalf of the clients, and also lets you redirect client requests to a different address. Iconic, honestly.

πŸ’… SOCKET OPTIONS πŸ’…

The server supports setting a large number of low-level socket options on both incoming and outgoing traffic. Most users will not need to set any of these, but some might want to, to enable special network features or to run various experiments. Live your truth.

Options can be set globally as defaults for all traffic, or set inside the access control rules so they only affect clients and targets matching that given rule.

Which socket options are available varies between platforms, so during configuration and building of the server, the available ones get determined. Currently, the following options should be detected, when available, for the specified protocol levels:

  • SOCKET β€” so_bindany, so_broadcast, so_debug, so_dontroute, so_jumbo, so_keepalive, so_oobinline, so_priority, so_rcvbuf, so_rcvbufforce, so_rcvlowat, so_sndbuf, so_sndbufforce, so_sndlowat, so_useloopback
  • TCP β€” tcp_cork, tcp_cwnd, tcp_init_cwnd, tcp_keepcnt, tcp_keepidle, tcp_keepintvl, tcp_linger2, tcp_maxrt, tcp_maxseg, tcp_md5sig, tcp_nodelay, tcp_noopt, tcp_nopush, tcp_sack_enable, tcp_stdurg, tcp_syncnt, tcp_window_clamp
  • UDP β€” udp_cork
  • IP β€” ip_auth_level, ip_dontfrag, ip_esp_network_level, ip_esp_trans_level, ip_freebind, ip_ipcomp_level, ip_minttl, ip_mtu_discover, ip_portrange, ip_recvtos, ip_tos, ip_ttl

The syntax for setting socket options goes like this:

<direction>.<level>.<option>: <value>

The value field corresponds to the value that the socket option should be set to. For many socket options this is an integer value. The level and option values correspond to the socket names and protocol levels listed above. Both should be in lower-case.

The direction keyword specifies whether the socket option should be set for traffic on the internal or the external interface, and it can have the values internal and external. For example, to set the IP_TOS socket option on outgoing traffic, you'd use this syntax:

external.ip.ip_tos: 0x10

In that example, the argument value (0x10) is specified as a hex value. For some of the socket options the value can also be set symbolically. Currently that's possible for the following option, with the listed values:

  • ip_portrange β€” ip_portrange_default, ip_portrange_low, ip_portrange_high

The IP_TOS socket option also supports this, but handling it is somewhat complicated by the same bits having different meanings in different RFCs. Handling it is done with a subfield that indicates the type of argument that should be used. The following subfields are defined and should be added to the name of the socket option as specified below:

  • ip_tos.dscp β€” af11 af12 af13 af21 af22 af23 af31 af32 af33 af41 af42 af43 cs0 cs1 cs2 cs3 cs4 cs5 cs6 cs7 ef
  • ip_tos.prec β€” netcontrol internetcontrol critic_ecp flashoverride flash immediate priority routine
  • ip_tos.tos β€” lowdelay throughput reliability

When numerical arguments are given to subfields, the values are shifted to apply only to the subfield bit range. This example shows the different ways of setting IP_TOS to lowdelay on external traffic:

external.ip.ip_tos:     0x10       #base value, numerically
external.ip.ip_tos.tos: 0x08       #subfield, numerically
external.ip.ip_tos.tos: lowdelay   #subfield, symbolically

The first value sets the value directly. The second sets only the TOS bits, which get shifted relative to the base value. The final line sets the TOS value symbolically. Slay. ✨

This functionality gives you a large amount of control over socket options, but it should not be used without some understanding of how the kernel allows the socket option to be set, and the limitations that apply when socket options are set as either defaults or in rules. Do your homework first, bestie. πŸ“š

Setting a socket option in a client pass or socks-rules will cause any defaults to be overridden. Global options are set before bind() is called on internal sockets, or before connect() is called on external sockets. Options set in client rules are also applied before bind() is called on the internal socket, but they cannot be set for the external socket. For socks-rules, both external and internal options can be set, but because the socks-request must be interpreted before the rules can be evaluated, socket options can only be set on internal sockets after the connection has been received.

Some socket options must be set before a connection has been established, while others can only be set after a connection has been established. Others can be set at any time. The range of it. 🌈

Socket options that aren't listed above can also be set by specifying the socket option name numerically, for example:

external.ip.10:     0x12

In this example, the socket option corresponding to the value 10 will be set. These numbers are platform dependent but can typically be determined by looking at the appropriate system header files. Specifying options numerically might result in some warnings, but it allows any socket option to be specified, as long as it takes a numerical argument. This is not the recommended approach for setting socket options, but it represents a simple way of setting socket options that aren't directly supported by the server, such as local kernel extensions.

✨ AUTHENTICATION METHODS ✨

The Dante server supports the following authentication methods. Some installations of Dante may support only a subset of these, depending on platform support. 🫢

  • none β€” this one is giving "no auth needed" energy. Literally requires no form of authentication. πŸ’€
  • username β€” bestie, the client has to provide a username and password. And this info must match the username and password given in the system password file. No cap. πŸ”
  • gssapi β€” this one needs a whole Kerberos environment set up, and depending on the gssapi settings you choose, it can provide strong encryption and authentication. It's giving secure. πŸ”₯
  • rfc931 β€” requires the host the socks client runs on to provide a rfc931 ("ident") username for the client. And that username has to match a username given in the system password file. periodt. πŸͺͺ
  • pam.address β€” IP-based (rhosts) PAM authentication. Simple as that. ✨
  • pam.any β€” will try to match against any type of PAM authentication, depending on the information that is currently available. Normally of limited use, and you should instead set the pam-based method(s) you actually want. Like, don't be lazy bestie. πŸ™ˆ
  • pam.username β€” username/password-based PAM authentication. Similar to the method username, but the information is passed to the PAM subsystem for authentication, rather than Dante using the system password file directly. When using PAM, be wary of memory leakages and other bugs in the external PAM library Dante will have to use on your platform. ⚠️ That's a real warning, not me being dramatic (well, maybe a little).
  • bsdauth β€” this method requires the available client data to be verified by the BSD Authentication system. Similar to the method username, but passed to the BSD authentication system instead. πŸ“

🌈 ADDRESSES 🌈

Each address field can be one of these cuties: an IP address (and where required, a netmask, separated from the IP address by a / sign), a hostname, a domainname (designated so by the leading .), or an interface name. πŸ’…

An IP address can be given in IPv4 form, IPv6 form, or as the special value 0/0, which matches all IP addresses, be they IPv4 or IPv6. The latter is intended for use in rules that should match both IPv4 and IPv6 clients or targets. 🌐

Each address, except the external address, can include an optional port specifier. πŸ‘‘

✨ RULES ✨

okay bestie, this is the part where it gets real. there are two whole sets of rules and they vibe at completely different levels, so don't mix them up πŸ’…

The ones prefixed with client get checked first, and their whole job is deciding whether a client is even allowed to connect to the Dante server at all. we call them "client-rules". they start with client pass if the rule lets the client through, or client block if the rule shuts them down πŸ™…β€β™€οΈ

ngl, it's recommended that client-rules do not use hostnames β€” only IP-addresses β€” for both security and performance reasons. these rules operate at the TCP level.

The other set, which we call "socks-rules", is prefixed with socks and operates at the socks protocol level.

These start with socks pass for a rule that allows the client, or socks block for a rule that blocks the client.

Here's the tea: these rules are only checked if the client connection already got the green light from the client-rules. the socks-rules are what evaluate the socks request the client sends πŸ¦‹

And while it's less important that these rules use only IP-addresses β€” provided the client-rules have been configured to only allow access from a pre-defined range of client IP-addresses β€” it's still recommended. do it anyway, bestie, your future self will thank you πŸ’–


Both sets of rules include a pass or deny keyword. that keyword is literally the decider of whether connections matching the rule get passed through or blocked. main character energy for one little word, honestly πŸ‘‘

Both the client-rules and the socks-rules also specify a from/to address pair which gives the addresses the rule will match.

In both contexts, from refers to the client's address, i.e., the address the client is connecting to the Dante server from. the to address, though? it means different things depending on whether it's chillin' in a client-rule or a socks-rule. so pay attention 🫢

  • In the client-rule context, to means the address the request is accepted on, i.e., an address the Dante server listens on.
  • In the socks-rule context, to means the client's destination address, as expressed in the client's socks request. i.e., the address the Dante server should connect to (for TCP sessions) or send packets to (for UDP sessions) on behalf of the client.

Both sets of rules are evaluated on a "first match is best match" basis. that means the first rule matched for a particular client or socks request is the rule that will be used. no takebacks, no re-dos, periodt ✨

In addition to the addresses there's a set of optional keywords you can hand over. there are two forms of keywords: conditions and actions. for each rule, all conditions are checked and if they match the request, all actions are executed.

The list of condition keywords is: clientcompatibility, clientmethod, command, from, group, socksmethod, protocol, proxyprotocol, to, user.

The list of action keywords is: bandwidth, libwrap, log, session, redirect, timeout.connect, timeout.negotiate, timeout.io, timeout.tcp_fin_wait, and udp.portrange.

The format and content of the keyword as used in client-rules or socks-rules is identical, but client-rules can contain only a subset of the keywords that socks-rules may contain. sad but true 😭


🌸 The contents of a client-rule can be:

  • bandwidth β€” The clients matching this rule will all share the given amount of bandwidth, measured in bytes per second. Requires the bandwidth module.
  • clientcompatibility β€” Enables certain options for compatibility with broken clients. Valid values are: necgssapi, for compatibility with clients implementing GSSAPI the NEC socks way. (we're being nice to the broken ones πŸ’œ)
  • from β€” The rule applies to requests coming from the specified address.
  • group β€” The user must belong to one of the groups given as value.
heads up bestie: if gssapi-based authentication is used, the username as provided to the Dante server normally includes the Kerberos domain. The name must be listed on the same form here and in the system groupfile (usually /etc/passwd) if it is to be used.
  • gssapi.enctype β€” Which encryption to enforce for GSSAPI-authenticated communication. Possible values are clear, integrity, or confidentiality. The default is to accept whatever the client offers except clear, as clear is not part of the SOCKS GSSAPI standard. 🚫
  • gssapi.keytab β€” Value for keytab to use. The default is "FILE:/etc/sockd.keytab".
  • gssapi.servicename β€” Which servicename to use when involving GSSAPI. Default is "rcmd".
  • libwrap β€” The server will pass the specified parameter line to libwrap for execution.
  • log β€” Used to control logging. Accepted keywords are connect, disconnect, data, error, ioop, and tcpinfo. The default is no logging. (the silent treatment, but make it intentional πŸ™ˆ)
  • session β€” Control the max number of sessions or session establishment rate. See below for details.
  • clientmethod β€” Require that the connection be "authenticated" using one of the given clientmethods.
  • pam.servicename β€” Which servicename to use when involving pam. Default is "sockd".
  • port β€” Parameter to from, to and via. Accepts the keywords eq/=, neq/!=, ge/>=, le/<=, gt/>, lt/< followed by a number. A port range can also be given as "port <start #> - <end #>", which will match all port numbers within the range <start #> and <end #>.

The default is to match all ports.

  • redirect β€” The source and/or destination can be redirected using the redirect statement. Requires the redirect module.

The syntax of the redirect statement is as follows:

redirect from: ADDRESS

See the redirect manual for detailed information.

  • socksmethod β€” If the client offers more than one authentication method, Dante will select the method to use based on the order the methods are listed here. Valid values are the same as in the global socksmethod line. Normally there will be no need to set this keyword in a client-rule, but if it is set and the client offers none of the methods listed, the client will be blocked at this stage. oop πŸ’€
  • timeout.negotiate β€” See the global timeout.negotiate option.
  • to β€” The rule applies to requests going to the address given as value.
  • user β€” The user must match one of the names given as value. If no user value is given for a rule requiring usernames, the effect will be the same as listing every user in the password file.
same deal as before, bestie: if gssapi-based authentication is used, the username as provided to the Dante server normally includes the Kerberos domain. The name must be listed on the same form here if it is to be used.

πŸŽ€ The contents of a socks-rule can be:

  • bandwidth β€” The clients matching this rule will all share the given amount of bandwidth, measured in bytes per second. Requires the bandwidth module.
  • bsdauth.stylename β€” The name of the BSD authentication style to use. The default is to not specify a value, causing the default system style to be used.
  • command β€” The rule applies to the given commands. Valid commands are bind, bindreply, connect, udpassociate and udpreply. Can be used instead of, or to complement, protocol. The default is all commands valid for the protocols allowed by the rule.
  • from β€” The rule applies to requests coming from the address given as value.
  • group β€” The user must belong to one of the groups given as value.
  • libwrap β€” The server will pass the line to libwrap for execution.
  • log β€” Used to control logging. Accepted keywords are connect, disconnect, data, ioop, and tcpinfo.
  • session β€” Control the max number of sessions or session establishment rate. See
  • socksmethod β€” Require that the connection be established using one of the given authentication methods. A method normally refers to the socks client part of the rule, and thus authenticates the client, and not the target destination (see checkreplyauth for information about authentication the target destination). Valid values are the same as in the global socksmethod line.
  • pam.servicename β€” What servicename to use when involving pam. Default is "sockd".
  • port β€” Parameter to from, to and via. Accepts the keywords eq/=, neq/!=, ge/>=, le/<=, gt/>, lt/< followed by a number. A portrange can also be given as "port <start #> - <end #>", which will match all port numbers within the range <start #> and <end #>.

The default is all ports.

  • protocol β€” The rule applies to the given protocols. Valid values are tcp and udp. The default is all supported protocols that can apply to the given commands.
  • proxyprotocol β€” The rule applies to requests using the given proxy protocol. Valid proxy protocols are socks_v4 and socks_v5. The default is all supported proxy protocols.
  • redirect β€” The source and/or destination can be redirected using the redirect statement. Requires the redirect module.

The syntax of the redirect statement is as follows:

redirect from: ADDRESS

redirect to: ADDRESS

The semantics of from and to vary according to command. See the redirect manual for detailed information.

  • timeout.connect β€” See the global timeout.connect option.
  • timeout.io β€” See the global timeout.io option.
  • timeout.tcp_fin_wait β€” See the global timeout.tcp_fin_wait option.
  • to β€” The rule applies to requests going to or using the address given as value. Note that the meaning of this address is affected by command. πŸ‘€
  • udp.portrange β€” The argument to this keyword is two port numbers, separated by a dash (-). They specify the UDP port-range that will be used between the socks-client and the Dante-server for UDP packets. Note that this has no relation to the UDP port-range used between the Dante-server and external, non-socks, clients/servers.
  • user β€” The user must match one of the names given as value. If no user value is given for a rule requiring usernames, the effect will be the same as listing every user in the password file.

πŸ’… SESSION πŸ’…

okay so the session keyword is that girl β€” you can drop it into any rule to cap how many sessions can be active at once and how fast new ones get established. there are two main commands doing the heavy lifting here:

  • session.max β€” controls the max number of sessions that can be matched 🎯
  • session.throttle β€” controls the connection rate πŸƒβ™€οΈ

both of these can be applied as the total limit for all matching clients, and they can be set as global defaults or inside any of the rule types. slay.

session.max takes a number as its argument β€” that number is the highest number of allowed simultaneous connections. simple as that bestie.

session.throttle takes two numbers separated by a slash character, where the first one = the number of connections and the second one = a time duration in seconds. so if more than the specified number of connections show up within the specified number of seconds, the extra connections get dropped. bye πŸ’€


✨ Stateful tracking (the per-IP glow-up) ✨

stateful session tracking on a per IP-address basis is also supported, and it's giving main character energy. for stateful tracking, the limits apply to each connection with a matching IP-address, and the session.state.key keyword is what controls how that IP-address gets determined. rn two values are supported:

  • from β€” the limit gets applied to all hosts with the same source IP-address 🫢
  • hostid β€” the limit gets applied to all TCP connections with the same hostid value πŸ”‘

if you're using a hostid value, the session.state.key.hostindex keyword can be used to choose which of the two hostid values are used β€” and the first value is the default.


πŸŽ€ How limits get evaluated πŸŽ€

limits are evaluated in this exact order, no skipping:

  1. client rules first
  2. then hostid rules
  3. finally socks rules

by default, a limit set in a matching client rule will also be used in any subsequent matching hostid or socks rules, unless either of those rules also have session limit keywords. that's the session inheritance situation.

this inheritance can be disabled in client and hostid rules, which makes them only apply in the rule where they actually appear. you do that by setting session.inheritable to no.

heads up bestie: the session keywords must be set in a rule (either client, hostid, or socks). setting them globally is not supported. periodt.

🌈 TRAFFIC MONITORING 🌈

the Dante server can be configured to monitor the traffic passing through it and trigger alarms based on the observed network traffic. obsessed honestly.

the alarms are specified in so-called monitors. these objects have the same general format as the rules Dante uses for access control, and they enable passive monitoring of network traffic β€” or the lack of network traffic πŸ‘€

here's the general monitor syntax, specifying a monitor without any monitoring operations:

monitor {
 from: 0.0.0.0/0 to: www.example.org port = 80
 protocol: tcp
}

a monitor can include many of the same keywords available in the Dante ACL rules. the following subset is currently supported:

  • from β€” normally specifies what SOCKS client addresses/networks to monitor πŸ•΅οΈβ™€οΈ
  • to β€” normally specifies what target addresses/networks to monitor 🎯
  • protocol β€” can be used to restrict monitoring to a certain protocol (TCP, UDP or both). Note: only TCP should be used for now ⚠️
  • hostid β€” can be used to restrict monitoring to only clients with a specific hostid value set πŸ”‘
  • hostindex β€” used along with the hostid keyword to control which of the two possible hostid values will be used when matching
NOTE: it's currently recommended that the protocol keyword is always specified and set to tcp, because there's currently only limited support for monitoring of UDP traffic, and testing of UDP traffic monitoring has not been done. so like, don't test it. 🫣

the main function of monitors is to provide a container for one or more alarms, which are specified using a new set of keywords that are not available for other rules. alarms specify a condition that will cause Dante to log a warning if that condition is triggered. πŸ””

active TCP sessions will at most match one monitor, but multiple alarms can be specified in a single monitor. this makes it possible to specify multiple sets of conditions for the same TCP sessions, depending on what network interface the traffic is transferred on and whether the traffic is being received or transmitted. very versatile, very demure.

alarms can trigger as a result of periods of no or little data being transmitted, or a large numbers of TCP connections disconnecting during a short period of time, or for other reasons. see below for a complete list of what conditions alarms can be enabled for πŸ‘‡


πŸ’Ύ Data alarms πŸ’Ύ

adding an alarm.data keyword to a monitor will result in warnings being logged if there are periods with too little network traffic. it's giving "girl where is the data".

Dante has four network paths, and data alarms can be configured independently for each of them:

  • internal.alarm.data.recv β€” data received on Dante's internal interface (data sent from the SOCKS clients to Dante) πŸ“₯
  • internal.alarm.data.send β€” data sent out on Dante's internal interface (data sent from Dante to the SOCKS clients) πŸ“€
  • external.alarm.data.recv β€” data received on Dante's external interface (data sent from the target servers to Dante) πŸ“₯
  • external.alarm.data.send β€” data sent out on Dante's external interface (data sent from Dante to the target servers) πŸ“€

the data.alarm keyword takes two parameters: a byte count and a duration in seconds. the alarm will trigger if the specified number of seconds pass with only the specified number of bytes (or less) being transmitted.

the syntax is as follows:

internal.alarm.data.recv: DATALIMIT in INTERVAL

DATALIMIT is a number that specifies the byte limit. INTERVAL is a number that specifies the duration. if only DATALIMIT bytes (or less) have been transferred during a period of INTERVAL seconds, an alarm will trigger in Dante. πŸ”₯


πŸ¦‹ the data alarm life cycle πŸ¦‹

data alarms trigger when a period of data idleness has been detected. once a data alarm has triggered it will remain active until it is cleared. a warning will be logged when the alarm triggers and then again when the alarm condition is cleared. in between these two points, no warnings related to this alarm will be logged. this avoids repeating the same alarm/warning multiple times during network problems that last for an extended amount of time. thoughtful queen behavior πŸ’…

when the alarm is cleared, Dante will also include information about how long the alarm condition lasted. πŸ•°οΈ

a data alarm can be cleared in two ways:

  1. automatically β€” once enough data has been transferred in a short enough amount of time ✨
  2. manually β€” by sending the Dante server a SIGHUP signal. a SIGHUP will cause all active alarms to be cleared. no log messages indicating that the alarms have cleared will be logged when alarms are cleared in this way 🀫

once an alarm has been cleared, it can trigger again if enough data is not being transferred.

note that data alarms will trigger regardless of whether there are active sessions matching the monitor or not; if enough data is not being transmitted or received, a data alarm will trigger. alarms will trigger also shortly after server startup, if the Dante server does not receive sufficient traffic to prevent the alarms from triggering. 😭
also note: the message indicating that an alarm has cleared is not logged if the alarm was cleared due to a SIGHUP signal being received.

πŸ”Œ Disconnect alarms πŸ”Œ

the disconnect alarms are related to connection disconnects, and by using the alarm.disconnect keyword the Dante server can log warnings based on the number and rate of terminated connections. rip to those connections fr fr πŸ’€

there are two variants of the alarm keyword β€” one for the internal network interface, between the SOCKS clients and Dante, and one for the external interface, between the Dante server and the target servers:

  • internal.alarm.disconnect β€” connections between SOCKS clients and the Dante server 🫢
  • external.alarm.disconnect β€” connections between the Dante server and target servers 🌐

each alarm keyword takes three parameters: a minimum count, a ratio value, and a time interval. the following format is used:

internal.alarm.disconnect: MINCOUNT/RATIO in INTERVAL
  • MINCOUNT β€” the minimum number of connections that must be disconnected for the alarm to trigger
  • RATIO β€” used together with the MINCOUNT to express the number of connections, relative to the total number of connections that have existed in the time period, that must be disconnected for the alarm to trigger
  • INTERVAL β€” the time in seconds within which the disconnects must occur for the alarm to trigger

🌸 tuning your alarm values 🌸

to set values that are useful, some knowledge about the expected amount of network traffic and number of sessions is required. iykyk.

  • if the rate of disconnects, as a percentage, is lower than the ratio specified, an alarm will not trigger.
  • conversely, if the MINCOUNT is set too low, alarms might trigger too frequently, because only a small number of disconnects might be sufficient to achieve the required number of disconnects and disconnect ratio at times when there are only a few active sessions. πŸ™ˆ

πŸ‘‘ which connections count? πŸ‘‘

only connections that are terminated on the specified interface are counted, i.e., an external.alarm.disconnect alarm will only trigger for connections that are terminated on the network interface between the Dante server and the target server β€” either by the target server closing the connection to Dante, or by Dante receiving a fatal network error from that side of the connection (e.g., a TCP RST packet). πŸ’₯

connections that are closed on the internal interface (by the SOCKS clients) will not count towards a disconnect alarm on the external side. likewise, connections closed by target servers will not count towards a disconnect alarm on the internal side.

a practical consequence of this is that if a large number of connections are simultaneously closed by both the client and the target server, each connection will only be counted as a disconnect on one of the sides; either the external side or the internal side, depending on which side closes the connection first. first come, first counted bestie πŸ’…


🎯 how alarms fire 🎯

alarms trigger each time a sufficient number disconnects occur. each sufficiently large burst of disconnects will result in an alarm, but normally at most one warning per alarm will be logged during each time interval β€” though this might change in a later version of Dante. πŸ‘€

separate alarms are produced for each distinct alarm keyword when multiple alarms are specified in a monitor rule. 🌈

🌸 ROUTES 🌸

okay so routes? They get their own keyword: route. Inside a pair of curly braces {} there's a lil set of keywords that control how that route behaves. For the whole explanation, go check socks.conf(5) β€” it's described there. This is how you do the so-called "server-chaining", where one socks-server connects to another socks-server further upstream. πŸ’«

The syntax for these routes is exactly the same as the routes the client uses. So yeah, please see socks.conf(5) for info about the route syntax. Same page, different vibe. 🫢

But bestie, there are some special things you need to be aware of when it comes to serverchaining and routes specified for the server:

  • At present serverchaining is only supported for the tcp connect command. no cap.
  • If the route specifies that a username/password-method should be offered to the upstream proxy, Dante will forward the username/password received from its own client to the foreign upstream proxy, meaning the upstream proxy will receive the user's username and password in cleartext from Dante. 🚨
  • At present serverchaining does not scale well in Dante and should not be used for anything but minimal client loads. Like, minimal minimal. πŸ™ˆ

✨ EXAMPLES ✨

See the example/ directory in the distribution. That's the whole example situation, bestie. Go peek. πŸ‘€πŸ’–


πŸŽ€ FILES πŸŽ€

  • /etc/sockd.conf β€” Dante server configuration file.
  • /etc/passwd β€” systemfile used when doing standard username/password authentication.

πŸ‘‘ AUTHORS πŸ‘‘

For inferno Nettverk A/S:

  • Michael Shuldman
  • Karl-Andre' Skevik

πŸ”— SEE ALSO πŸ”—

Information about new releases and other related issues can be found on the Dante WWW home page: http://www.inet.no/dante/

Information about commercial support can be found on the Dante WWW support page: http://www.inet.no/dante/support.html


And that's the whole SOCKD.CONF(5) page, bestie β€” source/version SOCKD.CONF(5), dated July 29 2013. Stay iconic, stay chained (only for minimal client loads tho) πŸ’…βœ¨πŸ¦‹

πŸ“¦ where this page comes from