Gitea SSL con Apache como proxy inverso

Para usar el registro de contenedores en k8s, se necesita utilizarlo a través de SSL.

Índice

Queremos alojar un registro de contenedores seguro y agradable - para empujar imágenes de docker allí y nuestro clúster de kubernetes las extraería de este registro. Así surgió la idea de usar gitea sobre ssl.

  1. Gitea ya tiene registro de contenedores
  2. Apache como proxy terminador de TLS añadirá HTTPS a nuestro Gitea.
  3. Así es como empezó… CA rot, certificados autofirmados…

Cada registro tiene sus propios secretos

Cuando necesitamos el registro en k8s

Desafortunadamente el registro en el clúster de kubernetes creado por kubespray no funciona para mí.

  • para empujar a él necesitamos crear un túnel temporal a través de kube-proxy
  • después de empujar a él mi versión actual del nuevo clúster no puede extraer imágenes de este registro interno

Después de pasar algunas noches increíbles intentando arreglarlo, he decidido simplemente usar el registro de contenedores interno de Gitea, solo necesito configurar el acceso HTTPS a él.

Lo haré público de todos modos, así que docker y k8s no tienen que hacer ningún login de docker. Quizás. Vamos a ver cómo nos va.

Probando si funciona

Para probar si el registro de contenedores nos sirve queremos poder

  • empujar una imagen allí y
  • crear un despliegue en k8s desde esa imagen
sudo docker pull alpine:3.12.0
sudo docker images
sudo docker tag a24bb4013296 localhost:5000/rg/alpine:version.3.12.0
sudo docker push localhost:5000/rg/alpine:version.3.12.0

Ahora xed alp1.yaml o nano alp1.yaml dependiendo de qué estado de ánimo estés teniendo y

apiVersion: apps/v1
kind: Deployment
metadata:
  name: alp-registry-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: alp-registry-test
  template:
    metadata:
      labels:
        app: alp-registry-test
    spec:
      containers:
        - name: alpine-test
          image: localhost:5000/rg/lpine:version.3.12.0
      imagePullSecrets:
      - name: registry-secret

Aquí está este archivo disponible para descarga Luego creando este despliegue

kubectl create -f alp1.yaml
kubectl get pods

kubectl describe po alp-registry-test-5f5cb94b97-njsp2
# o lo que sea que pod se haya creado o no se haya creado

Sí, sé sobre este fragmento

      imagePullSecrets:
      - name: registry-secret 

registry-secret es el nombre del secreto que kubespray creó.

Limpieza

kubectl delete -f alp1.yaml

Cómo

Un montón de documentación está disponible en sitio de Gitea: https-setup

Y en esa página: https://docs.gitea.com/administration/reverse-proxies

Paso 1 - Instalar Apache y crear un sitio de prueba simple

Instalar Apache

sudo apt install apache2

Verificar qué tenemos en el firewall

sudo ufw status

Si el firewall está activo, piensa en qué puerto quieres exponer a través de https y permítelo. Configuraciones estándar de apache son

sudo ufw app list

Podríamos ver algo como

Aplicaciones disponibles:
  Apache
  Apache Full
  Apache Secure
  OpenSSH

y para habilitar solo el puerto 443 ejecutamos

sudo ufw allow 'Apache Secure'

bueno. ahora verificar el estado del servicio

sudo systemctl status apache2

A continuación, crear un servidor virtual simple para probar Apache

sudo mkdir /var/www/reg.homelab
sudo chown -R $USER:$USER /var/www/reg.homelab
sudo chmod -R 755 /var/www/reg.homelab
sudo nano /var/www/reg.homelab/index.html

Poner allí

<html>
    <head>
        <title>Bienvenido a reg.homelab!</title>
    </head>
    <body>
        <h1>¡Éxito! El host virtual reg.homelab está funcionando!</h1>
    </body>
</html>

luego

sudo nano /etc/apache2/sites-available/reg.homelab.conf

y poner allí

<VirtualHost *:3080>
    ServerAdmin webmaster@localhost
    ServerName reg.homelab
    ServerAlias www.reg.homelab
    DocumentRoot /var/www/reg.homelab
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

luego deshabilitar el sitio por defecto, habilitar este y verificar cómo vamos

sudo a2ensite reg.homelab.conf
sudo a2dissite 000-default.conf
sudo apache2ctl configtest

ver algo como esto?

AH00558: apache2: No se pudo determinar con fiabilidad el nombre de dominio completo del servidor, usando 127.0.1.1. Establezca la directiva 'ServerName' globalmente para suprimir este mensaje

luego

sudo nano /etc/apache2/apache2.conf

añadir al final:

ServerName reg.homelab

Y esto aún no es el final! ahora necesitamos eliminar el intento de enlace del puerto 80

sudo nano /etc/apache2/ports.conf

poner allí

Listen 3030
...
Listen 443

Y ahora

sudo systemctl restart apache2
sudo systemctl status apache2
journalctl -xeu apache2.service
curl localhost:3080

¡BIEN! Ahora navega a <tu-dirección-ip-del-servidor>:3080

Paso 2 - Convertir este sitio en un proxy inverso inseguro :) hacia Gitea

sudo nano /etc/apache2/sites-available/reg.homelab.conf

poniendo allí

<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    ServerName reg.homelab
    ServerAlias www.reg.homelab
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    ProxyPreserveHost On
    ProxyRequests off
    AllowEncodedSlashes NoDecode
    ProxyPass / http://localhost:3000/ nocanon
</VirtualHost>

Hacer algunas pruebas de configuración

sudo apache2ctl configtest

Añadir algunos módulos de apache y reiniciar Apache

sudo a2enmod proxy proxy_http ssl
sudo systemctl restart apache2
sudo systemctl status apache2

OK, ahora navega a o curl

# Sí, aún es http, pero en el puerto 443
curl http://localhost:443
http://<Dirección_IP_del_Servidor>:443/

Paso 3 - CA raíz autofirmada y certificado del sitio

SweetHome-RootCA.

CANAME=MostImportant-RootCA

# opcional, crear un directorio
mkdir $CANAME
cd $CANAME

# generar clave privada encriptada con aes
openssl genrsa -aes256 -out $CANAME.key 4096

# crear certificado, 1826 días = 5 años
openssl req -x509 -new -nodes -key $CANAME.key -sha256 -days 1826 -out $CANAME.crt -subj '/CN=My Root CA/C=AT/ST=Vienna/L=Vienna/O=MyOrganisation'

# crear certificado para el servicio
MYCERT=reg.homelab
openssl req -new -nodes -out $MYCERT.csr -newkey rsa:4096 -keyout $MYCERT.key -subj '/CN=My Firewall/C=AT/ST=Vienna/L=Vienna/O=MyOrganisation'

# crear un archivo v3 ext para propiedades de SAN
cat > $MYCERT.v3.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = reg.homelablab
DNS.2 = gitea.homelablab
IP.1 = 192.168.0.10
IP.2 = 192.168.0.11
EOF

openssl x509 -req -in $MYCERT.csr -CA $CANAME.crt -CAkey $CANAME.key -CAcreateserial -out $MYCERT.crt -days 730 -sha256 -extfile $MYCERT.v3.ext
En máquinas conectándose a gitea / registro

Registrar el certificado raíz en Linux:

sudo cp MostImportant-RootCA.crt /usr/local/share/ca-certificates
sudo update-ca-certificates

Registrar el certificado raíz en Windows:

  • Doble clic en el archivo MostImportant-RootCA.crt
  • Importar a usuario local
  • Seleccionar CA raíz de confianza.
  • Cuando se le pregunte sobre importar un certificado no confiable - hacer clic en sí

Cuando git pull en Windows diga sobre

No se puede resolver "unable to get local issuer certificate...

puedes decirle a git que use la capa de red de Windows mediante

git config --global http.sslbackend schannel

Paso 4 - Seguridad del proxy con certificado autofirmado

https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html

Crear un certificado autofirmado SI no lo hiciste en el paso 3

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -subj "/CN=reg.homelab" \
  -addext "subjectAltName = DNS:reg.homelab" \
  -keyout /etc/ssl/private/apache-selfsigned-reg.homelab.key \
  -out /etc/ssl/certs/apache-selfsigned-reg.homelab.crt

O simplemente tomarlo del paso anterior

sudo cp reg.homelab.crt /etc/ssl/certs/apache-selfsigned-reg.homelab.crt
sudo cp reg.homelab.key /etc/ssl/private/apache-selfsigned-reg.homelab.key

De nuevo, abrir la configuración del host virtual

sudo nano /etc/apache2/sites-available/reg.homelab.conf

Añadir allí al final la sección SSL con los certificados

<VirtualHost *:443>
   ServerAdmin webmaster@localhost
   ServerName reg.homelab
   ServerAlias www.reg.homelab
   ErrorLog ${APACHE_LOG_DIR}/error.log
   CustomLog ${APACHE_LOG_DIR}/access.log combined
   ProxyPreserveHost On
   ProxyRequests off
   AllowEncodedSlashes NoDecode
   ProxyPass / http://localhost:3000/ nocanon
    
   SSLEngine on
   SSLCertificateFile /etc/ssl/certs/apache-selfsigned-reg.homelab.crt
   SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned-reg.homelab.key
</VirtualHost>

Verificar la configuración, reiniciar el servidor, verificar el estado y navegar a nuestro Gitea sobre SSL

sudo apache2ctl configtest
sudo systemctl restart apache2
sudo systemctl status apache2

# ir a: http://<Dirección_IP_del_Servidor>:443/
# o
curl -k -v https://localhost

el navegador advertirá sobre el certificado autofirmado

Tu conexión no es privada
Los atacantes podrían estar tratando de robar tu información de reg.homelab (por ejemplo, contraseñas, mensajes o tarjetas de crédito). Aprende más
NET::ERR_CERT_AUTHORITY_INVALID

Pero lo ignoraremos, por ahora, hasta que usemos Let’s Encrypt.

Ahora prueba con k8s

Hacer algunas cosas de DNS…

En cada nodo de k8s:

sudo nano /etc/hosts

y añadir allí

192.168.18.200 gitea.homelab
192.168.18.200 reg.homelab

CA raíz

En cada nodo de k8s:

sudo cp SweetHome-RootCA.crt /usr/local/share/ca-certificates
sudo update-ca-certificates

Y reiniciar ahora

Crear secreto con credenciales del registro

https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/

sudo docker login reg.homelab
kubectl create secret generic regcred --from-file=.dockerconfigjson=/home/rg/.docker/config.json --type=kubernetes.io/dockerconfigjson

o

kubectl create secret docker-registry regcred --docker-server=your-registry-server --docker-username=your-name --docker-password=your-pword --docker-email=your-email

Nueva imagen docker y despliegue de k8s

sudo docker pull alpine:3.12.0
sudo docker images
sudo docker tag a24bb4013296 reg.homelab/rg/alpine:version.3.12.0
sudo docker push reg.homelab/rg/alpine:version.3.12.0

Ahora nano alp2.yaml, el archivo está [disponible]disponible

apiVersion: apps/v1
kind: Deployment
metadata:
  name: alp-registry-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: alp-registry-test
  template:
    metadata:
      labels:
        app: alp-registry-test
    spec:
      containers:
        - name: alpine-test
          image: reg.homelab/rg/alpine:version.3.12.0
      imagePullSecrets:
      - name: regcred

Aquí está este archivo disponible para descarga: Luego creando este despliegue

kubectl create -f alp2.yaml
kubectl get pods
kubectl describe po alp...

Limpieza

kubectl delete -f alp2.yaml

Enlaces útiles