HOSTS_ACCESS(5)

๐ŸŽ€ HOSTS_ACCESS(5) ๐ŸŽ€

okay so bestie, this is hosts_access, the File Formats Manual page for host access control files ๐Ÿ’… it's section 5 btw, so it's all about the format of the files. let's get into it ๐Ÿซถ

๐ŸŒธ NAME

hosts_access - format of host access control files โœจ

๐Ÿ’– DESCRIPTION

okay so this page explains a simple access control language that's based on client patterns (host name/address, user name) and server patterns (process name, host name/address) ๐Ÿฆ‹ examples are at the end, so if you're impatient like me, just skip straight to the EXAMPLES section and get your vibe on ๐Ÿ™ˆ

the extended version of the language is in the hosts_options(5) document. ngl this one supersedes the meaning of shell_command as described below, so keep that in mind ๐Ÿ‘€

quick definitions so we're on the same page:

  • daemon is the process name of a network daemon process ๐Ÿงš
  • client is the name and/or address of a host asking for service ๐Ÿ’œ

network daemon process names get specified in the inetd configuration file, so go check there if you're lost ๐Ÿ“

โœจ ACCESS CONTROL FILES โœจ

the access control software checks two files, and the search stops at the very first match ๐Ÿ’… the order goes like this:

  1. access is granted if a (daemon,client) pair matches an entry in the /etc/hosts.allow file ๐ŸŽ€
  2. otherwise, access is denied if a (daemon,client) pair matches an entry in the /etc/hosts.deny file ๐Ÿšซ
  3. otherwise, access is granted ๐ŸŒˆ

a non-existing access control file gets treated like it's an empty file ๐Ÿซ  so honestly? if you provide no access control files at all, access control is basically turned off ๐Ÿ™ˆ

๐Ÿฆ‹ ACCESS CONTROL RULES ๐Ÿฆ‹

each access control file is made of zero or more lines of text ๐Ÿ’– the lines get processed in order of appearance, and the search wraps up the second a match is found ๐Ÿ”ฅ

here's the lowkey important stuff about the lines:

  • a newline gets ignored if a backslash comes right before it ๐Ÿงต this lets you break up long lines so they're easier to edit
  • blank lines and lines that start with a #ยด character are ignored ๐Ÿ’œ so you can drop comments and extra whitespace in to make the tables easier to read
  • every other line should follow this format (anything in [] is optional):
daemon_list : client_list [ : shell_command ]

daemon_list is a list of one or more daemon process names (argv[0] values), server port numbers, or wildcards (more on those below) ๐Ÿงš

client_list is a list of one or more host names, host addresses, patterns, or wildcards (see below) that get matched against the client host name or address ๐Ÿ’…

the more complex forms daemon@host and user@host are explained in the sections on server endpoint patterns and client username lookups, respectively ๐Ÿซถ

list elements should be separated by blanks and/or commas, bestie ๐ŸŽ€

with the exception of NIS (YP) netgroup lookups, all access control checks are case insensitive, so HOST and host are the same tea โ˜•

๐ŸŒˆ PATTERNS ๐ŸŒˆ

the access control language gives you these patterns to play with:

  • .tue.nlยด โ€” a string that begins with a .ยด character ๐Ÿ’– a host name matches if the last components of its name match the pattern. so the pattern .tue.nlยด matches the host name wzv.win.tue.nlยด
  • 131.155. โ€” a string that ends with a .ยด character ๐ŸŒธ a host address matches if its first numeric fields match the given string. for example, the pattern 131.155.ยด matches the address of (almost) every host on the Eindhoven University network (131.155.x.x) ๐Ÿฆ‹
  • @netgroup โ€” a string that begins with an @ยด character gets treated as an NIS (formerly YP) netgroup name โœจ a host name matches if it's a host member of that netgroup. netgroup matches are not supported for daemon process names or for client user names ๐Ÿ™…
on Debian systems, support for NIS netgroups has been disabled since package version 7.6.q-33, so if your netgroup patterns aren't working, that's probably why ๐Ÿ’€
  • n.n.n.n/m.m.m.m โ€” an expression like this gets read as a net/maskยด pair ๐Ÿง an IPv4 host address matches if netยด equals the bitwise AND of the address and the maskยด ๐Ÿงฎ for example, the net/mask pattern 131.155.72.0/255.255.254.0ยด matches every address from 131.155.72.0ยด through 131.155.73.255ยด ๐Ÿ˜ญ also, 255.255.255.255ยด is not a valid mask value, so a single host can be matched just by its IP ๐Ÿซถ
  • n.n.n.n/mm โ€” an expression like this gets read as a net/masklengthยด pair, where mmยด is the number of consecutive 1ยด bits in the netmask applied to the n.n.n.nยด address ๐Ÿ”ข
  • [n:n:n:n:n:n:n:n]/m โ€” an expression like this gets read as a [net]/prefixlenยด pair ๐Ÿงš an IPv6 host address matches if the prefixlenยด bits of netยด equal the prefixlenยด bits of the address. for example, the [net]/prefixlen pattern [3ffe:505:2:1::]/64ยด matches every address from 3ffe:505:2:1::ยด through 3ffe:505:2:1:ffff:ffff:ffff:ffffยด ๐ŸŒŠ
  • /path/to/file โ€” a string that begins with a /ยด character is treated as a file name ๐Ÿ“ a host name or address matches if it matches any host name or address pattern listed in that named file. the file format is zero or more lines, each with zero or more host name or address patterns separated by whitespace ๐ŸŽ€ a file name pattern can be used anywhere a host name or address pattern can be used, so you can totally mix and match ๐Ÿ’…
  • * and ? โ€” wildcards can be used to match host names or IP addresses ๐ŸŒŸ this method of matching cannot be used in conjunction with net/maskยด matching, host name matching beginning with .ยด, or IP address matching ending with .ยด ๐Ÿ™ˆ

โœจ CLIENT USERNAME LOOKUP โœจ

okay so if the client host speaks RFC 931 or one of its descendants (TAP, IDENT, RFC 1413) ๐Ÿ•ต๏ธโ€โ™€๏ธ the wrapper programs can go digging for info about who actually owns the connection. Any username they find gets logged next to the client host name, and you can even match on it with patterns like:

daemon_list : ... user_pattern@host_pattern ...

The daemon wrappers can be set up at compile time to do rule-driven username lookups (that's the default ๐Ÿ’…) or to always poke the client host no matter what. With rule-driven lookups, the rule above only triggers a lookup when both the daemon_list and the host_pattern match. Iconic efficiency, honestly.

A user pattern works the same way as a daemon process pattern, so all the same wildcards apply. Just know that netgroup membership is not supported here ๐Ÿ™…โ€โ™€๏ธ. And bestie, don't get too carried away with username lookups, because there are some real gotchas:

  • The client username info can't be trusted when you need it most, aka when the client system has been compromised ๐Ÿ’€. Honestly, ALL and (UN)KNOWN are the only user name patterns that make sense.
  • Username lookups only work with TCP-based services, and only when the client host is running a suitable daemon. Everywhere else, the result is "unknown".
  • A well-known UNIX kernel bug can cause loss of service when a firewall blocks username lookups ๐Ÿ˜ญ. The wrapper README document walks you through how to check whether your kernel has this bug.
  • Username lookups can cause noticeable delays for non-UNIX users. The default timeout is 10 seconds, which is too short for slow networks but long enough to irritate PC users ๐Ÿ™„.

Selective lookups can totally fix that last one. For example, a rule like:

daemon_list : @pcnetgroup ALL@ALL

matches members of the pc netgroup without doing any username lookups, but still does them for every other system. Main character problem solved โœจ.


๐Ÿ•ต๏ธโ€โ™€๏ธ DETECTING ADDRESS SPOOFING ATTACKS ๐Ÿ•ต๏ธโ€โ™€๏ธ

Okay, this part is kind of scary. A flaw in the sequence number generator of many TCP/IP implementations lets intruders easily impersonate trusted hosts and break in through things like the remote shell service ๐Ÿ˜ฑ. The IDENT (RFC931 etc.) service can be used to catch this and other host address spoofing attacks.

Before accepting a client request, the wrappers can use the IDENT service to figure out that the client never actually sent the request at all. When the client host provides IDENT service, a negative IDENT lookup result (the client matches UNKNOWN@hostยด) is strong evidence of a host spoofing attack ๐Ÿšจ.

A positive IDENT lookup result (the client matches KNOWN@hostยด) is way less trustworthy ๐Ÿซค. An intruder can spoof both the client connection and the IDENT lookup, although that's much harder than spoofing just the client connection. It's also possible that the client's IDENT server is simply lying.

Note: IDENT lookups donยดt work with UDP services. No IDENT for you, UDP ๐Ÿ™ƒ.

๐ŸŽ€ EXAMPLES ๐ŸŽ€

The language is super flexible, so different kinds of access control policy can be written with minimal fuss ๐Ÿ’–. Even though it uses two access control tables, the most common policies work fine with one table being trivial or even empty.

When you read the examples below, keep these three things in mind ๐Ÿง : the allow table gets scanned before the deny table, the search stops as soon as a match is found, and access is granted when no match is found at all.

The examples use host and domain names. You can make them stronger by adding address and/or network/netmask information, which reduces the impact of temporary name server lookup failures ๐ŸŒธ.


๐Ÿ”’ MOSTLY CLOSED ๐Ÿ”’

In this setup, access is denied by default. Only explicitly authorized hosts get in ๐Ÿšช.

The default policy (no access) is set up with a trivial deny file:

/etc/hosts.deny:
   ALL: ALL

This denies all service to all hosts, unless they're permitted by entries in the allow file.

The explicitly authorized hosts go in the allow file. For example:

/etc/hosts.allow:
   ALL: LOCAL @some_netgroup
   ALL: .foobar.edu EXCEPT terminalserver.foobar.edu

The first rule lets in hosts from the local domain (no . in the host name) and members of the some_netgroup netgroup ๐Ÿซถ. The second rule lets in all hosts in the foobar.edu domain (notice the leading dot!), except for terminalserver.foobar.edu.


๐ŸŒˆ MOSTLY OPEN ๐ŸŒˆ

Here, access is granted by default, and only explicitly specified hosts get turned away ๐Ÿ™…โ€โ™€๏ธ.

Since the default policy (access granted) makes the allow file redundant, you can just leave it out ๐Ÿซ . The explicitly non-authorized hosts go in the deny file. For example:

/etc/hosts.deny:
   ALL: some.host.name, .some.domain
   ALL EXCEPT in.fingerd: other.host.name, .other.domain

The first rule denies some hosts and domains all services. The second rule still lets finger requests through from other hosts and domains ๐Ÿ”.


๐Ÿชค BOOBY TRAPS ๐Ÿชค

This one is giving sneaky genius ๐Ÿ˜ˆ. The next example permits tftp requests from hosts in the local domain (notice the leading dot). Requests from any other hosts get denied. Instead of the requested file, a finger probe gets sent to the offending host, and the result is mailed to the superuser ๐Ÿ“ฌ.

/etc/hosts.allow:
   in.tftpd: LOCAL, .my.domain

/etc/hosts.deny:
   in.tftpd: ALL: (/usr/sbin/safe_finger -l @%h | \
        /usr/bin/mail -s %d-%h root) &

The safe_finger command comes with the tcpd wrapper and should be installed somewhere sensible ๐Ÿงš. It limits the possible damage from data sent by the remote finger server, and it gives better protection than the standard finger command ๐Ÿ’….

The expansion of the %h (client host) and %d (service name) sequences is covered in the section on shell commands ๐Ÿค“.

Warning: do not booby-trap your finger daemon, unless you are prepared for infinite finger loops ๐ŸŒ€๐Ÿ’€.

On network firewall systems, this trick can go even further ๐Ÿ”ฅ. The typical network firewall only offers a limited set of services to the outer world, so all the other services can be "bugged" just like the tftp example above. The result is an excellent early-warning system ๐Ÿšจ๐Ÿฆ‹.


๐Ÿงฏ DIAGNOSTICS ๐Ÿงฏ

Errors get reported when any of these happen ๐Ÿ˜ฌ: a syntax error is found in a host access control rule; an access control rule is longer than the capacity of an internal buffer; an access control rule isn't terminated by a newline character; the result of a %<letter> expansion would overflow an internal buffer; or a system call fails when it really shouldnยดt. Everything gets reported via the syslog daemon ๐Ÿ“.


๐Ÿ“ FILES ๐Ÿ“

  • /etc/hosts.allow โ€” (daemon,client) pairs that are granted access โœ…
  • /etc/hosts.deny โ€” (daemon,client) pairs that are denied access ๐Ÿšซ

๐Ÿ‘€ SEE ALSO ๐Ÿ‘€


๐Ÿ› BUGS ๐Ÿ›

If a name server lookup times out, the host name won't be available to the access control software, even though the host is registered ๐Ÿ’”.

Domain name server lookups are case insensitive, but NIS (formerly YP) netgroup lookups are case sensitive ๐Ÿ™ƒ. Watch your capitalization, bestie.


๐Ÿง‘โ€๐Ÿ’ป AUTHOR ๐Ÿง‘โ€๐Ÿ’ป

Wietse Venema (wietse@wzv.win.tue.nl) Department of Mathematics and Computing Science Eindhoven University of Technology Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands


okay that's the whole page, bestie ๐Ÿ’–โœจ go be a legend with your access rules ๐Ÿ‘‘. Love you, mwah ๐Ÿซถ HOSTS_ACCESS(5) ๐Ÿฆ‹๐Ÿ’