blog/_posts/2018-12-23-ssh-forwarding-b...

5.2 KiB

title date url layout category image description
SSH forwarding between host and container for Gitea 2018-12-23 ssh-forwarding-between-host-and-container-for-gitea post Security /img/blog/ssh-forwarding-between-host-and-container-for-gitea.png How to use only one SSH server instance between host and unprivileged LXC container for Gitea ?

A missing blog post image

Introduction

Let's say you wanna deploy a Gitea instance within an unprivileged LXC container, and use the SSH functionality (pretty handy with Git, isn't it ?).

With a classic configuration, you'll face an "issue" : The presence of two SSH servers (one for your host, one for the container, mainly used by Gitea).
So let's see if we could set up an architecture allowing us to forward specific SSH queries to the Gitea container from the SSH server running on the host.

This would let us achieve these objectives :

  • Keep only one instance of SSHd open on Internet (sysadmin laziness) ;

  • Keep only the 22 port open for both use cases (KISS) ;

  • Configure only one instance of Fail2Ban (sysadmin laziness++) ;

  • Keep only one SSHd to harden (Internet is still an untrusted entity for wandering connections).

The procedure

First, in your Gitea container

Just follow the regular Gitea install guide, and add an SSH key to your account once it's done (Settings > SSH / GPG Keys > Manage SSH Keys).

Now you have two options here :

  • Enable the built-in SSH server of Gitea on a port > 1024 if your instance is running with a regular user (something I really invite you to consider, for security purposes)

  • Use the SSH server shipped within your container (give a try to the ssh.service systemd unit)

Next, on the host

As root :

{% highlight bash %}

Port of the SSH server running within your Gitea container

SSH_PORT="2222"

IP address of your Gitea container, within your local network

IP_ADDRESS="192.168.1.2"

Prepare the Git system user for remote SSH connections (before forwarding)

adduser --system --shell /bin/bash --gecos "Git Version Control" --disabled-password --home /home/git git mkdir /home/git/.ssh chown -R git:nogroup /home/git/.ssh

Add to the known_hosts the public key of the SSH server running within the Gitea container

su - git -c "ssh-keyscan -H -p $SSH_PORT $IP_ADDRESS > /home/git/.ssh/known_hosts 2> /dev/null"

Generate a keys pair to authenticate the host git session on your Gitea container

su - git -c "ssh-keygen" su - git -c "cat ~/.ssh/id_*.pub"

--> Copy the public key generated !

Mock a fake /usr/local/bin/gitea program, forwarding SSH commands to your Gitea container

(Sorry for this series of ugly shell escapes...)

echo -e "#\041/usr/bin/env bash\nssh -p $SSH_PORT git@$IP_ADDRESS "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"" > /usr/local/bin/gitea chmod +x /usr/local/bin/gitea

If your system users have to be within the ssh group to attempt connections

(see : https://samuel.forestier.app/blog/security/hardening-openssh-all-in-one-place)

usermod -a -G ssh git {% endhighlight %}

Before going back in the Gitea container to polish up the setup, we have to make the host keep the Gitea public identities synchronized within the fake git session (to accept incoming connections).
For this, we cron a specific task (Proxmox 5 example) :

{% highlight bash %}

Replace XXX by the id of your container running Gitea

CONTAINER_ID="XXX" test "$(/usr/sbin/pct status $CONTAINER_ID)" = "status: running" && /usr/sbin/pct pull $CONTAINER_ID --user git --group nogroup /home/git/.ssh/authorized_keys /home/git/.ssh/authorized_keys {% endhighlight %}

Pro tip : You can even deny password authentication for the git user on your host, see below :

{% highlight bash %} echo -e "Match User git\n\tPasswordAuthentication no" >> /etc/ssh/sshd_config systemctl reload ssh {% endhighlight %}

Finally, back in your Gitea container

Whatever the SSH server you chose before, you only have to add the public key of the host git session (the one you copied previously) to /home/git/.ssh/authorized_keys, as done below :

{% highlight bash %}

Host's git session public key to allow SSH forwarding

ssh-rsa AAAA... git@host

gitea public key

command="/usr/local/bin/gitea serv key-3 --config='/etc/gitea/app.ini'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAA... gitea-user@user-host

...

{% endhighlight %}

The idea is to allow SSH connections from your host git session to the container git one.

Conclusion

This post has been mainly inspired from this guide, where the author detailed an interesting setup, with Docker and mounted volumes.
Unfortunately, I couldn't manage to get something similar working with LXC, mainly due to the difficult aspect of {u,g}ids mapping for mounted endpoints within unprivileged containers...

As always, tell me what you think about this setup, and how it could be improved if you experience(d) a similar situation on your side.