Synopsis #
A service in a private Bastille jail needs three working layers: a listener inside the jail, routing and NAT for the jail address, and an explicit PF redirection from a host address and port. Publishing the port before verifying the first two layers makes failures harder to locate.
This guide uses a jail named web, HTTPS on jail port 443, and host port 8443. The default Bastille private-network setup and its rdr/* PF anchor must already exist. Review Choose a jail network model
first.
Verify the service without publishing it #
Confirm the jail address and listening socket:
# bastille list jail
# bastille cmd web sockstat -4 -6 -l
# bastille service web nginx status
The service should listen on the jail address or on all jail addresses, not only on 127.0.0.1. From the host, connect directly to the private address before adding redirection:
$ fetch -o /dev/null https://10.17.89.20/
Substitute the actual jail address. Certificate-name errors are expected when an IP address is used; a timeout or refused connection indicates a listener or local path problem that PF redirection will not repair.
Check the host boundary #
Identify the external address, confirm the Bastille anchors, and inspect existing mappings:
$ ifconfig -a
# pfctl -nf /etc/pf.conf
# pfctl -sr | grep anchor
# bastille rdr web list
The host rules must contain rdr-anchor "rdr/*" and the Bastille anchor expected by the installed release. A clean syntax check does not prove that the rules preserve remote access. Use the precautions in Change PF safely on a remote host
before loading a changed base ruleset.
Also check whether port 8443 is already occupied on the host:
# sockstat -4 -6 -l | grep ':8443'
Add the narrowest mapping #
To expose host TCP port 8443 to jail port 443 on the default external interface:
# bastille rdr web tcp 8443 443
# bastille rdr web list
When only a management network should connect, use a source restriction. Replace the documentation prefix before running this example:
# bastille rdr -t ipv4 -s 192.0.2.0/24 web tcp 8443 443
On a host with several addresses or interfaces, use Bastille’s --destination and --interface options rather than publishing on every address. Confirm the generated rule with bastille rdr web list; do not infer its scope from the command alone.
Test from outside the host #
Test from a system on the intended source network:
$ nc -vz host.example.net 8443
$ fetch -o /dev/null https://host.example.net:8443/
During the test, inspect states and rule counters on the host:
# pfctl -ss
# pfctl -vvsr
No matching state normally means that traffic did not reach the expected interface or did not match the rule. A state with no successful application response points toward the jail listener, return route, or service policy.
Remove the mapping #
List all rules before clearing them:
# bastille rdr web list
# bastille rdr web clear
clear removes the jail’s mappings, not only one guessed entry. Record the intended mappings as configuration and verify them after Bastille, PF, or host restarts. A dynamic rule that worked once is not an adequate deployment record.