SELinux blocks SSH local port forwarding
Topics: Secure Shell, SELinux
This note explains how SELinux policy can prevent SSH local port forwarding and describes a policy-based fix.
Subtopics
Symptoms
An SSH local forward accepts a connection locally, then OpenSSH reports:
channel 2: open failed: connect failed: open failed
For example:
ssh -N -L 3000:127.0.0.1:3000 user@host
The target service can still be reached from an interactive SSH shell on the host. This rules out the service and its loopback listener, but not SELinux: the forwarding connection is opened by sshd-session, not by the shell process.
Diagnosis
Look for an SELinux access-vector-cache denial for sshd-session:
comm="sshd-session" ... denied { name_connect } ... scontext=...:sshd_session_t:... tcontext=...:ntop_port_t:... tclass=tcp_socket
The target port type depends on the port. On Fedora, TCP port 3000 is labelled ntop_port_t.
This failure appeared after a dnf upgrade that updated both openssh-server and selinux-policy-targeted. SELinux had remained enabled and enforcing; the updated policy changed what the SSH session domain could connect to.
Fix for development hosts
When a development host needs forwards to several local services, add one local policy that permits the SSH session domain to open TCP connections to ports. It is preferable to making SELinux permissive or adding a new exception for every development port.
mkdir -p ~/selinux/ssh-local-forward
cd ~/selinux/ssh-local-forward
cat > ssh_local_forward.te <<'EOF'
module ssh_local_forward 1.0;
require {
type sshd_session_t;
attribute port_type;
class tcp_socket name_connect;
}
allow sshd_session_t port_type:tcp_socket name_connect;
EOF
checkmodule -M -m -o ssh_local_forward.mod ssh_local_forward.te
semodule_package -o ssh_local_forward.pp -m ssh_local_forward.mod
sudo semodule -i ssh_local_forward.pp
The policy permits only TCP name_connect from sshd_session_t. It does not grant listening, binding, UDP, file, process, or raw-network permissions. It does allow an SSH account that OpenSSH permits to use local forwarding to connect to any TCP destination reachable from the host. Use PermitOpen in sshd_config if that needs to be restricted.
For a single service, replace port_type with the target type shown in the denial, such as ntop_port_t. That is more restrictive, but becomes tedious when a development machine uses multiple ports.
Permissive mode on a development host
SELinux permissive mode is a simpler alternative on a private, disposable development host. It removes enforcement for every domain, not only SSH forwarding.
Verification
Start a temporary forward on an unused local port, then request it from another terminal:
ssh -N -L 3005:127.0.0.1:3000 user@host
curl -I http://127.0.0.1:3005/
The request should return the target service’s HTTP status rather than another direct-tcpip connection failure.
Bookmarks
- SELinux Reference Policy: SSH
- SELinux Reference Policy: network interfaces
- SELinux Notebook: network support