Ana içeriğe atla

SSH Port Forwarding on Fedora with SELinux Enforcing

I wanted to access an Ollama server running on Fedora from another Linux machine without exposing Ollama directly to the network.

Ollama was listening only on:

127.0.0.1:11434

The obvious solution was an SSH local tunnel:

ssh -N -L 11434:127.0.0.1:11434 user@SERVER_IP

This should make the remote Ollama API available on the client at:

http://127.0.0.1:11434

However, SSH returned:

channel 2: open failed: connect failed: open failed

1. Verify the service

First, I confirmed that Ollama itself worked on the Fedora server:

curl http://127.0.0.1:11434/api/version

It returned:

{"version":"0.34.0"}

So Ollama was not the problem.

I also checked SSH forwarding:

sudo sshd -T | grep -E 'allowtcpforwarding|disableforwarding|permitopen'

The relevant settings allowed forwarding:

allowtcpforwarding yes
disableforwarding no
permitopen any

2. Check SELinux

Fedora runs SELinux in enforcing mode, so I checked recent denials:

sudo ausearch -m AVC -ts recent

The important part was:

avc: denied { name_connect }
comm="sshd-session"
dest=11434
scontext=...sshd_session_t...
tcontext=...unreserved_port_t...

So SSH forwarding was allowed by sshd, but SELinux was preventing the SSH session from connecting to port 11434.

3. Label the Ollama port

Because Ollama provides an HTTP API, I classified TCP port 11434 as http_port_t:

sudo dnf install policycoreutils-python-utils

sudo semanage port -a \
    -t http_port_t \
    -p tcp 11434

Verify it:

sudo semanage port -l | grep 11434

This changed the SELinux target from unreserved_port_t to http_port_t, but SSH was still denied.

4. Add a narrow SELinux rule

The missing permission was:

sshd_session_t → http_port_t → name_connect

Instead of disabling SELinux, I created a small local policy:

cat > ~/ssh-forward.te <<'EOF'
module ssh-forward 1.0;

require {
        type http_port_t;
        type sshd_session_t;
        class tcp_socket name_connect;
}

allow sshd_session_t http_port_t:tcp_socket name_connect;
EOF

Compile and install it:

sudo dnf install checkpolicy policycoreutils

cd ~

checkmodule -M -m \
    -o ssh-forward.mod ssh-forward.te

semodule_package \
    -o ssh-forward.pp \
    -m ssh-forward.mod

sudo semodule -i ssh-forward.pp

Verify:

sudo semodule -l | grep ssh-forward

Optionally, install sesearch:

sudo dnf install setools-console

and confirm the permission:

sudo sesearch -A \
    -s sshd_session_t \
    -t http_port_t \
    -c tcp_socket \
    -p name_connect

The result should include:

allow sshd_session_t http_port_t:tcp_socket name_connect;

5. Test the tunnel

Back on the client:

ssh -N -L 11434:127.0.0.1:11434 user@SERVER_IP

Then, from another client terminal:

curl http://127.0.0.1:11434/api/version

It now returned:

{"version":"0.34.0"}

The tunnel was working.

Why use this approach?

I could have configured Ollama to listen on 0.0.0.0:11434 and opened the firewall port, but that would expose its API to the local network.

Instead, the final setup is:

Client
127.0.0.1:11434
      │
      │ SSH tunnel
      ▼
Fedora Server
      │
      ▼
127.0.0.1:11434
      │
      ▼
Ollama

Ollama remains localhost-only, while authorized SSH users can access it securely.

Most importantly, SELinux remains in enforcing mode. There is no need to use setenforce 0 just to make SSH forwarding work.

If an SSH tunnel on Fedora gives:

channel N: open failed: connect failed: open failed

despite the destination service working locally, checking the SELinux AVC log with:

sudo ausearch -m AVC -ts recent

may reveal the actual cause.

Yorumlar

Bu blogdaki popüler yayınlar

An Awk feature

I was trying to use sub (or gsub) function in awk to delete an \r from the end of line. For that purpose I used dum=sub(/\r/,"",$0) and thought that the variable "dum" will be filled with the changed value of $0. But I realised that sub function only make the change and returns 0,1 accordingly. So I wrote like this sub(/r/,"") ; x=$0;

Centos 6 Postgresql 9.1 Install

Today I have changed my mind and decided to begin learning and using Postgresql. On a Centos 6 host there are some ways of installing Postgresql. I have chosen the easy one: use repos. Here http://yum.pgrpms.org/repopackages.php is the official Postgresql repos for Red Hat related distros. I have chosen the x86_64 rpm for Centos 6 and installed it. Later using yum install postgresql91-server I have installed three packages postgresql91,postgresql91-server and postgresql91-libs which is enough for now to start Postgresql 9.1. Using the instructions at /usr/share/doc/postgresql91-9.1.1/README.rpm-dist , I first did service postgresql-9.1 initdb and then service postgresql-9.1 start.Voila! Now let the journey begin! Edit:  Here is another place to look instructions http://www.postgresonline.com/journal/archives/203-postgresql90-yum.html

OpenBSD Nfsen install

I was  trying to find a solution for network monitoring as a friend's request. OpenBSD is the firewall. I saw the Nfsen packages and installed to a 5.2 server. After some effort trying to understand what is going on behind, I realised that Netflow is a protocol by Cisco designed to export router traffic to outside. And OpenBSD has a support of it with pflow interface. First I made a new pflow0 interface like ifconfig pflow0 flowdst 127.0.0.1:9998 flowsrc 127.0.0.1 up Then made some configuration changesto /etc/nfsen.conf and /var/www/htdocs/nfsen/conf.php. Because Apache in OpenBSD runs in chrooted by default, if you dont make the necessary changes in these pages you got an error stating  ERROR: nfsend connect() error: Permission denied!  ERROR: nfsend - connection failed!!  ERROR: Can not initialize globals! which is because apache cant reach the communication socket which is initially  located at $PIDDIR/nfsen.comm namely /var/db/nfsen/run direc...