En entornos empresariales que gestionan múltiples aplicaciones internas o microservicios, la tendencia común es desplegar soluciones complejas como NGINX, Traefik o balanceadores basados en contenedores pesados. Sin embargo, en arquitecturas donde la estabilidad, la simplicidad y la seguridad de kernel son primordiales, relayd(8) de OpenBSD ofrece una solución nativa, segura y extremadamente ligera.
En este artículo analizaremos un caso de estudio real para la empresa XYZ Corp, que necesita centralizar el acceso HTTPS público hacia tres aplicaciones internas con nombres de dominio distintos, terminación TLS segura y verificación continua del estado de los servidores de backend.
1. Escenario y Requerimientos de Empresa XYZ
La infraestructura interna de XYZ Corp cuenta con 3 servicios diferenciados alojados en servidores locales o jaulas de red:
app.xyz.corp: Aplicación web principal de clientes (Backend en Go escuchando en10.0.1.10:3000).api.xyz.corp: API REST de alta disponibilidad (Balanceada entre dos instancias backend:10.0.1.20:8000y10.0.1.21:8000).portal.xyz.corp: Portal estático corporativo y documentación (Servido por OpenBSDhttpd(8)en127.0.0.1:8080).
Objetivos:
- Terminación TLS centralizada: Un solo punto de borde en OpenBSD gestiona los certificados Let’s Encrypt de los tres dominios.
- Ruteo HTTP por cabecera
Host: Redirigir el tráfico entrante al backend correspondiente según el subdominio solicitado. - Health Checks activos: Si una instancia de la API cae,
relaydla retira automáticamente del pool en tiempo real. - Inyección de cabeceras de seguridad: Forzar HSTS,
X-Forwarded-Fory sanitizar cabeceras maliciosas.
2. Diagrama de Flujo y Topología de Red
[ INTERNET / Clientes HTTPS:443 ]
|
v
+-------------------+
| OpenBSD Edge |
| - PF Firewall |
| - relayd(8) TLS | (IP Pública: 198.51.100.1)
+-------------------+
|
+-----------------------+-----------------------+
| Host: app.xyz.corp | Host: api.xyz.corp | Host: portal.xyz.corp
v v v
+---------------+ +------------------+ +------------------+
| Backend APP | | Cluster API REST | | Portal Estático |
| 10.0.1.10:3000| | .20:8000 .21:8000| | 127.0.0.1:8080 |
+---------------+ +------------------+ +------------------+
3. Configuración Completa de /etc/relayd.conf
A continuación se muestra el archivo /etc/relayd.conf estructurado y comentado:
# /etc/relayd.conf - Configuración Multi-Tenant para Empresa XYZ
# 1. Definición de Tablas de Backend con Health Checks
table <backend_app> {
10.0.1.10
}
table <cluster_api> {
10.0.1.20
10.0.1.21
}
table <backend_portal> {
127.0.0.1
}
# 2. Definición del Protocolo HTTP y Políticas de Seguridad
http protocol "https_corporate_filter" {
# Terminar conexiones inactivas (Anti Slowloris)
tcp { nodelay, sack, socket buffer 65536 }
# Inyectar cabeceras proxy estándar
match request header append "X-Forwarded-For" value "$REMOTE_ADDR"
match request header append "X-Forwarded-By" value "$SERVER_ADDR:$SERVER_PORT"
match request header set "X-Forwarded-Proto" value "https"
# Cabeceras de seguridad globales en la respuesta
match response header set "Strict-Transport-Security" value "max-age=31536000; includeSubDomains; preload"
match response header set "X-Content-Type-Options" value "nosniff"
match response header set "X-Frame-Options" value "DENY"
match response header set "Referrer-Policy" value "strict-origin-when-cross-origin"
# Ruteo L7 basado en la cabecera "Host"
match request header "Host" value "app.xyz.corp" forward to <backend_app>
match request header "Host" value "api.xyz.corp" forward to <cluster_api>
match request header "Host" value "portal.xyz.corp" forward to <backend_portal>
}
# 3. Definición del Relay Público (Entrada HTTPS)
relay "tls_gateway" {
# Escuchar en la interfaz pública puerto 443
listen on 198.51.100.1 port 443 tls
# Protocolo de inspección L7
protocol "https_corporate_filter"
# Forward por defecto hacia el portal
forward to <backend_portal> port 8080 check http "/healthz" code 200
# Forwards específicos con puertos de backend y verificación activa
forward to <backend_app> port 3000 check http "/status" code 200
forward to <cluster_api> port 8000 check http "/v1/health" code 200
}
4. Integración con Packet Filter (/etc/pf.conf)
Para que relayd gestione el tráfico y pueda redirigir conexiones de forma transparente, agregamos las reglas en /etc/pf.conf:
# /etc/pf.conf
ext_if = "vio0"
# Permitir entrada TLS al relay
pass in quick on $ext_if proto tcp to 198.51.100.1 port { 80, 443 } keep state
# Permitir a relayd comunicarse con las subredes internas de backend
pass out quick on $ext_if proto tcp to { 10.0.1.10, 10.0.1.20, 10.0.1.21 } keep state
Cargar la configuración con:
doas pfctl -f /etc/pf.conf
5. Operación, Validación y Monitoreo
Validar Sintaxis
Antes de iniciar el servicio, verifica que el archivo no contenga errores:
doas relayd -n
# Salida esperada: configuration OK
Iniciar y Habilitar el Demonio
doas rcctl enable relayd
doas rcctl start relayd
Inspeccionar el Estado de los Backends en Tiempo Real
Con relayctl(8) puedes auditar el estado de los servidores y el balanceo:
doas relayctl show summary
Salida típica de diagnóstico:
Id Type Name Avlblty Status
1 relay tls_gateway active
1 table backend_app:3000 active
1 host 10.0.1.10 100.00% up
2 table cluster_api:8000 active
2 host 10.0.1.20 100.00% up
3 host 10.0.1.21 100.00% up
3 table backend_portal:8080 active
4 host 127.0.0.1 100.00% up
6. Conclusiones
Con menos de 60 líneas de configuración y sin necesidad de instalar paquetes externos ni entornos de ejecución pesados, OpenBSD relayd(8) proporciona:
- Aislamiento absoluto: Corre bajo usuario sin privilegios
_relaydconpledgeyunveil. - Alta disponibilidad determinista: Retiro automático de nodos con fallos en milisegundos.
- Mantenimiento cero: Cero dependencias rotas por actualizaciones de paquetes de terceros.