hosts.allow and hosts.deny can close a wrapped service to everyone except a short list, or lock you out of your own server if the order is wrong. This builds a mostly closed TCP-wrapper policy: named client hosts are allowed, every other wrapped service request is denied, and you check the rule order before it bites. Allow about 15 minutes for a simple policy, plus a maintenance window if the files protect a production service.
This only applies to programs that actually use the TCP wrappers library: installing libwrap0 does not make every listening daemon read these files. The local package is libwrap0 7.6.q-33, and the installed hosts.allow(5) page documents the behaviour used here.
Find the daemon process name that the wrapper will actually see, such as sshd or in.ftpd: normally the daemon's argv[0], though the manual also permits server port numbers in a daemon list. Check the listener and package before editing anything:
$ ss -ltnp
$ dpkg-query -W -f='${Package} ${Version}\n' libwrap0:amd64
libwrap0 7.6.q-33
Keep an existing root shell or console session open while you test. A new login can be refused by a bad rule, and these files may affect more than one service at once.
Checkpoint: You know the service to protect, the client address or network to allow, and you have a way back in that does not depend on the rule you are about to change.
Read both files first. A missing file is treated as empty, so either one may simply be absent on a lightly configured host:
$ sudo sh -c 'for f in /etc/hosts.allow /etc/hosts.deny; do
> if test -e "$f"; then echo "--- $f"; sed -n "1,160p" "$f"; else echo "--- $f (missing)"; fi
> done'
$ sudo install -m 600 /etc/hosts.allow /etc/hosts.allow.bak 2>/dev/null || true
$ sudo install -m 600 /etc/hosts.deny /etc/hosts.deny.bak 2>/dev/null || true
The backup commands can print nothing when a source file is missing; the || true only absorbs that expected case, it does not hide a later rule error. Do not paste an example over an existing policy without reading it first: the lines already there may protect monitoring, backups or console-managed access.
Put the smallest useful rule in /etc/hosts.allow, replacing 192.0.2.44 with a real client address and sshd with the daemon name from step 1:
$ sudo sh -c 'printf "%s\n" "sshd: 192.0.2.44" >> /etc/hosts.allow'
192.0.2.0/255.255.255.0, or with a prefix length such as 192.0.2.0/24. Prefer addresses or explicit networks when DNS instability would make a hostname unreliable..example.test matches every host in that domain; a bare hostname is not the same as the whole domain.ALL in the allow file unless you genuinely mean to allow every client for that daemon.Only once the allow rule is correct, create the default deny policy:
$ sudo sh -c 'printf "%s\n" "ALL: ALL" > /etc/hosts.deny'
This is the ordering detail that matters: the wrapper scans hosts.allow first, then hosts.deny, and stops at the first match. The allow entry therefore grants the approved client before the catch-all deny entry ever gets a look. If no rule matches in either file, access is granted, which is why an empty deny file is not a closed policy on its own.
There is no reload command for these text files. A wrapper reads the tables when it checks a request. The service still has to use TCP wrappers, and a daemon may layer its own firewall, authentication and authorisation rules on top.
Check the final text, including the newline at the end of each rule:
$ sudo sed -n '1,160p' /etc/hosts.allow /etc/hosts.deny
sshd: 192.0.2.44
ALL: ALL
From the approved client, make a normal connection and confirm it reaches the daemon's own authentication stage. From a deliberately unapproved test client, confirm the connection is refused or closed. The exact client-side message varies by daemon and network path, so it is not proof by itself.
Use the daemon's logs and system logging to investigate a denial. The manual says syntax errors, oversized or unterminated rules, failed system calls and expansion overflows are reported through the syslog daemon, and a name-service timeout can make a hostname unavailable even when the host exists. If the system has tcpdchk or tcpdmatch, use those local test programs; do not assume they are installed alongside the runtime library.
Checkpoint: The approved client reaches the service, the denied test is blocked, and the logs show the expected daemon and client information. If any result is unclear, stop before adding more rules.
ALL EXCEPT in.fingerd: 192.0.2.0/24, but the syntax applies to lists, not to arbitrary parenthesised expressions, so review it carefully./bin/sh: use absolute paths, and avoid logging untrusted expansion data until you have a clear reason to.If legitimate access is blocked, use the preserved console or root session and restore the last known-good files. This changes access policy immediately for every subsequent wrapper check:
$ sudo cp --preserve=mode,ownership /etc/hosts.allow.bak /etc/hosts.allow
$ sudo cp --preserve=mode,ownership /etc/hosts.deny.bak /etc/hosts.deny
If a backup did not exist, remove only the file you created, after checking its contents, or edit it back to the previous rule set. Do not delete both files as a quick fix: with no access-control files at all, the wrapper grants access by default.
libwrap0 version./etc/hosts.allow.ALL: ALL is in /etc/hosts.deny only after the allow rule was checked.