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

111 lines
5.2 KiB
Markdown

---
title: "SSH forwarding between host and container for Gitea"
date: 2018-12-23
url: ssh-forwarding-between-host-and-container-for-gitea
layout: post
category: Security
image: /img/blog/ssh-forwarding-between-host-and-container-for-gitea.png
description: "How to use only one SSH server instance between host and unprivileged LXC container for Gitea ?"
---
[![A missing blog post image](/img/blog/ssh-forwarding-between-host-and-container-for-gitea.png)](/img/blog/ssh-forwarding-between-host-and-container-for-gitea.png)
### Introduction
Let's say you wanna deploy a [Gitea](https://gitea.io/) 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](https://www.fail2ban.org/wiki/index.php/Main_Page) (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](https://docs.gitea.io/), 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](https://blog.sakuragawa.moe/gitea-in-docker-container-and-sharing-ssh-with-host/), 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.