Bot de Telegram para conectar a VPN usando openconnect con soporte completo de OTP, split tunneling y VPN-Slice.
# 1. Clonar y configurar
git clone <tu-repo>
cd vpn-bot
cp .env.example .env
# Editar .env con TOKEN, VPN_OTP_SECRET, ALLOWED_USERS
# 2. Instalar udev rule en el HOST para DNS de la VPN
cd resolvectl && sudo ./install.sh && cd ..
# 3. Build y correr
docker compose up -d
# 4. Comandos en Telegram
/connect # Conectar VPN
/disconnect # Desconectar
/status # Estado de conexión
/health # Verificar conectividad + DNS
/logs # Últimas líneas del log
/system # Info del sistema
/help # Ayuda
/connect, /disconnect, /status, /system, /logs, /help.env (variable VPN_OTP_SECRET)OKUXVSDFRDK24KNRXQYDPUGSJV5OIB3JQbin/tncc - 8.7MB)bin/tncc.sh) para portabilidadbin/vpn-slice compilado para rendimientobin/vpn-slice.sh para fácil ejecuciónconfig/vpn_profiles.yamlVPN_DEFAULT_PROFILE# 1. Clonar repositorio
git clone <tu-repositorio-vpn-bot>
cd vpn-bot
# 2. Instalar dependencias
./start.sh # o pip install -r requirements.txt
# 3. Configurar variables de entorno
cp .env.example .env
# Editar .env con:
# - TOKEN (token de Telegram Bot de @BotFather)
# - VPN_OTP_SECRET (clave base32 para OTP)
# - AUTHORIZED_USER_ID (tu ID de Telegram)
# - VPN_DEFAULT_PROFILE (opcional, ej: "arca")
# 4. Iniciar bot
./start.sh
.env (CRÍTICO)# Token del bot de Telegram (obtenido de @BotFather)
TOKEN=******tu_token_aqui******
# Secreto OTP base32 para generación de códigos
VPN_OTP_SECRET=******RXQYDPUGSJV5OI*******
# ID de usuario de Telegram autorizado
AUTHORIZED_USER_ID=123456
# Perfil VPN por defecto (opcional, usa el primero si no se define)
# VPN_DEFAULT_PROFILE=arca
config/vpn_profiles.yaml)profiles:
# Perfil principal para VPN Arca
arca:
display_name: "VPN Arca"
server: "as.arca.gob.ar/notebookArca"
host: "as.arca.gob.ar" # Host para TNCC
username: "****CUIL****"
auth_method: "password_otp"
# Configuración de TNCC
tncc:
binary: "bin/tncc"
wrapper: "bin/tncc.sh"
# Configuración de VPN-Slice (split tunneling)
slice:
enable: true
included_subnets:
- "10.0.0.0/8"
excluded_subnets:
- "10.204.147.0/24"
options:
dump: false
verbose: false
# Configuración DNS post-conexión
# En Docker: lo maneja la udev rule del host
# En host directo: lo ejecuta resolvectl automáticamente
dns:
enabled: true
interface: "tun0"
check: "intranet.afip.gob.ar" # Dominio para test de resolución
servers:
- "10.6.25.204"
domains:
- "~afip.gob.ar"
- "~arca.gob.ar"
# Healthcheck post-conexión
healthcheck:
enabled: true
target: "10.30.251.70" # Host interno a pinguear
timeout: 10
retries: 3
interval: 2
# Perfil VPN por defecto (opcional)
VPN_DEFAULT_PROFILE=arca
/start - Iniciar interacción con el bot
/connect - Conectar a VPN (perfil configurado)
/disconnect - Desconectar VPN
/status - Estado actual (con duración legible)
/health - Verificar conectividad (ping + DNS)
/logs [N] - Últimas N líneas del log del bot (default 30, max 200)
/system - Información del sistema y verificación
/help - Mostrar ayuda
# 1. Iniciar bot (ya debería estar corriendo)
# 2. Conectar VPN
/connect
# 3. VPN-Slice maneja automáticamente el split tunneling
# - Configura rutas según subredes definidas en YAML
# - Mantiene internet pública para Telegram
# 4. Verificar estado
/status
# 5. Desconectar cuando termines
/disconnect
bin/vpn-slice.shWrapper para el binario VPN-Slice que configura split tunneling automáticamente:
bin/vpn-slice con parámetros de configuraciónbin/vpn-sliceBinario compilado de VPN-Slice para split tunneling inteligente:
bin/fix_vpn_routes.shScript de respaldo para corrección manual de rutas (si VPN-Slice falla):
tun010.0.0.0/8 por VPN10.204.147.0/24 por red localbin/test_routes.shVerifica que las rutas estén configuradas correctamente.
bin/tncc.shWrapper para el binario TNCC que asegura rutas relativas.
Solución con VPN-Slice: Normalmente resuelto automáticamente.
Solución de respaldo: Ejecutar ./bin/fix_vpn_routes.sh después de conectar.
Verificar:
slice.enable: true en YAMLincluded_subnets y excluded_subnetsbin/vpn-slice y bin/vpn-slice.shVerificar:
VPN_OTP_SECRET en .envpyotp instaladaSolución: Configurar AUTHORIZED_USER_ID en .env con tu ID de Telegram.
Verificar:
config/vpn_profiles.yamlVPN_DEFAULT_PROFILE coincide con nombre de perfilvpn-bot/
├── bin/ # Binarios y scripts
│ ├── tncc # Binario TNCC (8.7MB)
│ ├── tncc.sh # Wrapper para tncc
│ ├── vpn-slice # Binario VPN-Slice (compilado)
│ ├── vpn-slice.sh # Wrapper para VPN-Slice
├── config/ # Configuración
│ └── vpn_profiles.yaml # Perfiles VPN (configurables)
├── resolvectl/ # DNS setup para el HOST (via udev)
│ ├── 99-vpn-dns.rules # Regla udev (tun0 aparece → ejecuta script)
│ ├── resolvectl-vpn.sh # Script que ejecuta resolvectl
│ ├── install.sh # Instalación
│ └── uninstall.sh # Desinstalación
├── logs/ # Logs persistentes (volume mount)
├── main.py # Bot principal de Telegram
├── vpn_manager.py # Gestor de conexiones VPN
├── start.sh # Script de inicio (host directo)
├── Dockerfile # Imagen Docker
├── docker-compose.yml # Orquestación Docker
├── requirements.txt # Dependencias Python
├── .env.example # Plantilla de variables
└── README.md # Esta documentación
Cuando el contenedor usa network_mode: host, comparte la pila de red del host.
El contenedor no tiene systemd-resolved adentro, por lo que la resolución DNS
para la interfaz VPN se delega al host mediante una regla udev.
Cuando tun0 aparece (conexión VPN), la regla 99-vpn-dns.rules dispara
automáticamente resolvectl-vpn.sh que configura systemd-resolved en el host.
resolvectl/
├── 99-vpn-dns.rules # Regla udev (dispara en cada tun0 add)
├── resolvectl-vpn.sh # Script que ejecuta resolvectl dns + domain
├── install.sh # Instalación (run con sudo)
└── uninstall.sh # Desinstalación
En el host (no dentro del contenedor):
cd resolvectl
sudo ./install.sh
Esto:
resolvectl-vpn.sh a /usr/local/bin/99-vpn-dns.rules a /etc/udev/rules.d/tun0 ya existe, corre el script inmediatamenteValores actuales (editables en resolvectl-vpn.sh):
| Parámetro | Valor |
|---|---|
| Interfaz | tun0 |
| DNS | 10.6.25.204 |
| Dominios | ~afip.gob.ar ~arca.gob.ar |
# Ver DNS aplicado a tun0
resolvectl status tun0
# Verificar que la regla udev está activa
udevadm info --query=all --name=tun0 2>/dev/null | grep -i rules
# Probar resolución DNS real
resolvectl query intranet.afip.gob.ar
Salida esperada de resolvectl status tun0:
Link XX (tun0)
Current Scopes: DNS
Protocols: -DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 10.6.25.204
DNS Servers: 10.6.25.204
DNS Domain: ~afip.gob.ar ~arca.gob.ar
Cada vez que la VPN reconecta, tun0 se destruye y recrea. La regla udev
detecta cada ACTION=="add" y aplica el DNS automáticamente — no requiere
intervención manual.
MIT License - Ver LICENSE file para detalles.
Las contribuciones son bienvenidas. Por favor, abre un issue o pull request.
Para problemas o preguntas, abre un issue en GitHub.
Content type
Image
Digest
sha256:b4da27d24…
Size
93.5 MB
Last updated
5 months ago
docker pull afreisinger/bot-vpn