feat: agregar scripts DNS/SSH y reorganizar repo
- scripts/mdns-resolve: resolver .local via multicast UDP puro - scripts/ssh-mdns-proxy: ProxyCommand con mDNS + Tailscale + cache - scripts/ssh-fallback: ProxyCommand Tailscale + LAN - scripts/mdns-publish.py: movido a scripts/ - smb.conf: actualizado shares (Almacenamiento + Termux) - install.sh: instala los 4 scripts de red - README.md: documentacion completa de todos los scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
af232a3568
commit
66a9b4afbf
263
README.md
263
README.md
|
|
@ -1,6 +1,8 @@
|
||||||
# Samba en Termux - Documentacion
|
# Termux Network Toolkit: Samba + mDNS + SSH
|
||||||
|
|
||||||
> Actualizado: 2026-03-24
|
> Actualizado: 2026-03-25
|
||||||
|
|
||||||
|
Samba + descubrimiento mDNS + scripts de resolucion DNS para Termux (Android). Compatible con Windows 11, Kubuntu 24 y macOS.
|
||||||
|
|
||||||
## Instalacion rapida
|
## Instalacion rapida
|
||||||
|
|
||||||
|
|
@ -13,59 +15,62 @@ bash install.sh
|
||||||
El instalador:
|
El instalador:
|
||||||
1. Instala `samba` y `python-zeroconf`
|
1. Instala `samba` y `python-zeroconf`
|
||||||
2. Crea directorios de config
|
2. Crea directorios de config
|
||||||
3. Copia `smb.conf` y `mdns-publish.py`
|
3. Copia `smb.conf` y los 4 scripts de red a `~/.local/bin/`
|
||||||
4. Crea usuario Samba (pide usuario y contrasena)
|
4. Crea usuario Samba (pide usuario y contrasena)
|
||||||
5. Agrega autostart y aliases a `.bashrc`
|
5. Agrega autostart y aliases a `.bashrc`
|
||||||
6. Inicia ambos servicios
|
6. Inicia Samba + mDNS
|
||||||
|
|
||||||
## Archivos del repo
|
## Estructura del repo
|
||||||
|
|
||||||
| Archivo | Proposito |
|
```
|
||||||
|---------|-----------|
|
termux-samba/
|
||||||
| `smb.conf` | Config principal de Samba |
|
├── smb.conf # Config Samba (SMB3, puerto 4450)
|
||||||
| `mdns-publish.py` | Script de descubrimiento en red (SSH + SMB) |
|
├── install.sh # Instalador automatico
|
||||||
| `install.sh` | Instalador automatico |
|
├── bashrc-snippet.sh # Autostart + aliases para .bashrc
|
||||||
| `bashrc-snippet.sh` | Autostart + aliases para .bashrc |
|
├── .gitignore # Excluye datos runtime
|
||||||
| `.gitignore` | Excluye datos runtime (logs, pids, private) |
|
└── scripts/
|
||||||
|
├── mdns-publish.py # Publica SSH + SMB via mDNS (Zeroconf)
|
||||||
|
├── mdns-resolve # Resuelve hostnames .local (multicast UDP)
|
||||||
|
├── ssh-mdns-proxy # ProxyCommand SSH: mDNS → Tailscale → cache
|
||||||
|
└── ssh-fallback # ProxyCommand SSH: Tailscale → LAN
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Resumen
|
## Samba
|
||||||
|
|
||||||
Samba 4.20.8 corriendo en Termux (Android) con descubrimiento automatico en red local via mDNS. Compatible con Windows 11, Kubuntu 24 y macOS.
|
### Resumen
|
||||||
|
|
||||||
- **Nombre en red:** MOVIL
|
- **Nombre en red:** MOVIL
|
||||||
- **Puerto:** 4450 (445 requiere root, no disponible en Termux)
|
- **Puerto:** 4450 (445 requiere root, no disponible en Termux)
|
||||||
- **Protocolo:** SMB2/SMB3 con cifrado y signing
|
- **Protocolo:** SMB2/SMB3 con cifrado y signing
|
||||||
- **Usuario:** andres
|
|
||||||
- **Autostart:** Via `.bashrc` al abrir Termux
|
- **Autostart:** Via `.bashrc` al abrir Termux
|
||||||
|
|
||||||
---
|
### Shares
|
||||||
|
|
||||||
## Archivos de configuracion
|
| Share | Ruta | Contenido |
|
||||||
|
|-------|------|-----------|
|
||||||
|
| Almacenamiento | `/storage/emulated/0` | Toda la memoria interna Android |
|
||||||
|
| Termux | `$HOME` | Home de Termux (configs, scripts, desarrollo) |
|
||||||
|
|
||||||
|
### Archivos en disco
|
||||||
|
|
||||||
| Archivo | Proposito |
|
| Archivo | Proposito |
|
||||||
|---------|-----------|
|
|---------|-----------|
|
||||||
| `~/.config/samba/smb.conf` | Config principal de Samba |
|
| `~/.config/samba/smb.conf` | Config principal |
|
||||||
| `~/.config/samba/private/` | Base de datos de usuarios (tdbsam) |
|
| `~/.config/samba/private/` | Base de datos de usuarios (tdbsam) |
|
||||||
| `~/.config/samba/samba.log` | Log de actividad |
|
| `~/.config/samba/samba.log` | Log de actividad |
|
||||||
| `~/.config/samba/lock/` | Lock files para browsing |
|
|
||||||
| `~/.config/samba/state/` | Estado interno |
|
|
||||||
| `~/.config/samba/cache/` | Cache |
|
|
||||||
| `~/.local/bin/mdns-publish.py` | Script que publica SSH + SMB via mDNS |
|
|
||||||
|
|
||||||
---
|
### Parametros de compatibilidad
|
||||||
|
|
||||||
## Shares disponibles
|
| Parametro | Valor | Motivo |
|
||||||
|
|-----------|-------|--------|
|
||||||
| Share | Ruta Android | Contenido |
|
| `server min protocol` | SMB2 | Win11 y Kubuntu 24 ya no usan SMB1 |
|
||||||
|-------|-------------|-----------|
|
| `server max protocol` | SMB3 | Maximo rendimiento y cifrado |
|
||||||
| Archivos | `/storage/emulated/0/Archivos` | Desarrollo, documentos de trabajo |
|
| `smb encrypt` | desired | Win11 lo prefiere, negocia automaticamente |
|
||||||
| Home | `$HOME` | Home de Termux (configs, scripts) |
|
| `server signing` | desired | Win11 lo exige desde 2024 |
|
||||||
| Downloads | `/storage/emulated/0/Download` | Descargas del navegador/apps |
|
| `unix charset` | UTF-8 | Acentos en nombres de archivo |
|
||||||
| Documents | `/storage/emulated/0/Documents` | Documentos Android |
|
| `dos charset` | CP850 | Compatibilidad Windows |
|
||||||
| DCIM | `/storage/emulated/0/DCIM` | Fotos y videos de camara |
|
|
||||||
| Movies | `/storage/emulated/0/Movies` | Peliculas |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -75,15 +80,13 @@ Samba 4.20.8 corriendo en Termux (Android) con descubrimiento automatico en red
|
||||||
|
|
||||||
El dispositivo aparece automaticamente en **Red** del panel lateral como **"movil"** gracias al servicio mDNS `_smb._tcp`.
|
El dispositivo aparece automaticamente en **Red** del panel lateral como **"movil"** gracias al servicio mDNS `_smb._tcp`.
|
||||||
|
|
||||||
Tambien se puede acceder manualmente:
|
Acceso manual en barra de direcciones:
|
||||||
|
|
||||||
```
|
```
|
||||||
smb://movil.local:4450/
|
smb://movil.local:4450/
|
||||||
smb://movil.local:4450/Archivos
|
smb://movil.local:4450/Almacenamiento
|
||||||
```
|
```
|
||||||
|
|
||||||
Credenciales: `andres` / `asde71.4`
|
|
||||||
|
|
||||||
### Kubuntu 24 / Terminal
|
### Kubuntu 24 / Terminal
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -94,59 +97,61 @@ avahi-browse -rt _smb._tcp
|
||||||
smbclient -L movil.local -p 4450 -U andres
|
smbclient -L movil.local -p 4450 -U andres
|
||||||
|
|
||||||
# Acceder a un share
|
# Acceder a un share
|
||||||
smbclient //movil.local/Archivos -p 4450 -U andres
|
smbclient //movil.local/Almacenamiento -p 4450 -U andres
|
||||||
|
|
||||||
# Montar como filesystem
|
# Montar como filesystem
|
||||||
sudo mount -t cifs //movil.local/Archivos /mnt/movil \
|
sudo mount -t cifs //movil.local/Almacenamiento /mnt/movil \
|
||||||
-o port=4450,username=andres,password=asde71.4,vers=3.0
|
-o port=4450,username=andres,password=PASS,vers=3.0
|
||||||
```
|
```
|
||||||
|
|
||||||
### Windows 11
|
### Windows 11
|
||||||
|
|
||||||
Windows no soporta puertos SMB alternativos de forma nativa. Opciones:
|
Windows no soporta puertos SMB alternativos de forma nativa. Opciones:
|
||||||
|
|
||||||
**Opcion A - Mapear con netsh (requiere admin):**
|
**Opcion A - Port proxy (requiere admin):**
|
||||||
```cmd
|
```cmd
|
||||||
netsh interface portproxy add v4tov4 listenport=445 listenaddress=127.0.0.1 connectport=4450 connectaddress=192.168.1.108
|
netsh interface portproxy add v4tov4 listenport=445 listenaddress=127.0.0.1 connectport=4450 connectaddress=IP_MOVIL
|
||||||
net use Z: \\127.0.0.1\Archivos /user:andres asde71.4
|
net use Z: \\127.0.0.1\Almacenamiento /user:andres
|
||||||
```
|
```
|
||||||
|
|
||||||
**Opcion B - Usar la IP directa desde Explorador:**
|
**Opcion B - Desde Explorador (algunos builds):**
|
||||||
```
|
```
|
||||||
\\192.168.1.108:4450\Archivos
|
\\IP_MOVIL:4450\Almacenamiento
|
||||||
```
|
```
|
||||||
(Nota: no todos los builds de Win11 soportan esta sintaxis)
|
|
||||||
|
### Android (mismo dispositivo)
|
||||||
|
|
||||||
|
Instalar [SambaLite](https://play.google.com/store/apps/details?id=de.schliweb.sambalite) (open source, sin ads).
|
||||||
|
Conectar a `127.0.0.1:4450` con usuario y contrasena.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Descubrimiento en red (mDNS / DNS-SD)
|
## Scripts de red (mDNS / DNS)
|
||||||
|
|
||||||
### Como funciona
|
Todos se instalan en `~/.local/bin/`. Requieren `PATH="$HOME/.local/bin:$PATH"`.
|
||||||
|
|
||||||
El script `~/.local/bin/mdns-publish.py` publica dos servicios via Zeroconf (mDNS):
|
### mdns-publish.py — Publicar servicios en la red
|
||||||
|
|
||||||
| Servicio | Tipo DNS-SD | Puerto | Proposito |
|
Publica el dispositivo como `movil.local` via mDNS multicast (Zeroconf).
|
||||||
|----------|------------|--------|-----------|
|
|
||||||
| SSH | `_ssh._tcp.local.` | 8022 | Acceso remoto por SSH |
|
|
||||||
| Samba | `_smb._tcp.local.` | 4450 | Compartir archivos SMB |
|
|
||||||
|
|
||||||
Ambos se publican bajo el hostname **movil.local**.
|
**Servicios publicados:**
|
||||||
|
|
||||||
### Script: mdns-publish.py
|
| Servicio | Tipo DNS-SD | Puerto |
|
||||||
|
|----------|------------|--------|
|
||||||
|
| SSH | `_ssh._tcp.local.` | 8022 |
|
||||||
|
| Samba | `_smb._tcp.local.` | 4450 |
|
||||||
|
|
||||||
**Ubicacion:** `~/.local/bin/mdns-publish.py`
|
|
||||||
**Dependencia:** `pip install zeroconf`
|
**Dependencia:** `pip install zeroconf`
|
||||||
**Autostart:** Via `.bashrc` (lineas 34-37)
|
|
||||||
|
|
||||||
El script:
|
**Uso:** Se ejecuta como daemon en background (autostart via `.bashrc`).
|
||||||
1. Detecta la IP local del dispositivo
|
|
||||||
2. Registra los servicios SSH y SMB en la red multicast mDNS
|
|
||||||
3. Se mantiene corriendo en background (daemon)
|
|
||||||
4. Limpia los registros al recibir SIGINT/SIGTERM
|
|
||||||
|
|
||||||
### Verificar que esta publicando
|
**Verificar desde Kubuntu:**
|
||||||
|
```bash
|
||||||
|
avahi-browse -rt _smb._tcp
|
||||||
|
# Debe mostrar: movil → movil.local → IP:4450
|
||||||
|
```
|
||||||
|
|
||||||
Desde Termux:
|
**Verificar desde Termux:**
|
||||||
```bash
|
```bash
|
||||||
python3 -c "
|
python3 -c "
|
||||||
from zeroconf import Zeroconf, ServiceBrowser
|
from zeroconf import Zeroconf, ServiceBrowser
|
||||||
|
|
@ -167,40 +172,86 @@ zc.close()
|
||||||
"
|
"
|
||||||
```
|
```
|
||||||
|
|
||||||
Desde Kubuntu:
|
### mdns-resolve — Resolver hostnames .local
|
||||||
|
|
||||||
|
Resuelve hostnames `.local` via multicast UDP puro (sin Avahi, sin dependencias externas).
|
||||||
|
|
||||||
|
**Por que existe:** Termux no puede resolver `.local` nativamente (usa su propia libc, no la de Android).
|
||||||
|
|
||||||
|
**Uso:**
|
||||||
```bash
|
```bash
|
||||||
avahi-browse -rt _smb._tcp
|
# Resolver un hostname
|
||||||
|
mdns-resolve lenovo-ideapad.local
|
||||||
|
# Output: 192.168.1.112
|
||||||
|
|
||||||
|
# Con timeout personalizado (segundos)
|
||||||
|
mdns-resolve hp62a.local 5
|
||||||
```
|
```
|
||||||
|
|
||||||
Resultado esperado:
|
**Como funciona:**
|
||||||
|
1. Construye query DNS tipo A para el hostname
|
||||||
|
2. Envia al grupo multicast 224.0.0.251:5353
|
||||||
|
3. Parsea la respuesta y extrae la IP
|
||||||
|
4. Exit 0 con IP en stdout, o exit 1 si no resuelve
|
||||||
|
|
||||||
|
**Sin dependencias externas** — usa solo stdlib de Python (socket, struct, select).
|
||||||
|
|
||||||
|
### ssh-mdns-proxy — ProxyCommand SSH inteligente
|
||||||
|
|
||||||
|
ProxyCommand para `~/.ssh/config` que resuelve hostnames con fallback en cascada.
|
||||||
|
|
||||||
|
**Cadena de resolucion:**
|
||||||
|
1. mDNS (via `mdns-resolve`) — red local
|
||||||
|
2. Tailscale DNS (`*.tailb0bb74.ts.net`) — fuera de LAN
|
||||||
|
3. Cache local (`~/.ssh/mdns-cache`) — si todo falla
|
||||||
|
|
||||||
|
**Aliases soportados:**
|
||||||
|
- `dell` → `dell-latitude3400`
|
||||||
|
- `lenovo` → `lenovo-ideapad`
|
||||||
|
|
||||||
|
**Uso en `~/.ssh/config`:**
|
||||||
```
|
```
|
||||||
movil → movil.local → 192.168.1.x:4450
|
Host lenovo-ideapad
|
||||||
|
User andres
|
||||||
|
ProxyCommand ~/.local/bin/ssh-mdns-proxy %h %p
|
||||||
|
|
||||||
|
Host dell
|
||||||
|
User andres
|
||||||
|
ProxyCommand ~/.local/bin/ssh-mdns-proxy %h %p
|
||||||
|
|
||||||
|
Host hp62a
|
||||||
|
User andres
|
||||||
|
ProxyCommand ~/.local/bin/ssh-mdns-proxy %h %p
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Cache:** Guarda la ultima IP resuelta en `~/.ssh/mdns-cache` para reconexion rapida si mDNS y Tailscale fallan.
|
||||||
|
|
||||||
|
### ssh-fallback — ProxyCommand Tailscale + LAN
|
||||||
|
|
||||||
|
ProxyCommand simple con fallback de Tailscale a IP LAN.
|
||||||
|
|
||||||
|
**Cadena de resolucion:**
|
||||||
|
1. Ping al host Tailscale (1s timeout)
|
||||||
|
2. Si falla, ping a IP LAN (1s timeout)
|
||||||
|
3. Si ambos fallan, intenta Tailscale sin verificar
|
||||||
|
|
||||||
|
**Uso en `~/.ssh/config`:**
|
||||||
|
```
|
||||||
|
Host hp62a
|
||||||
|
ProxyCommand ~/.local/bin/ssh-fallback hp62a.tailb0bb74.ts.net 192.168.1.16 %p
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nota:** `ssh-mdns-proxy` es mas completo (mDNS + Tailscale + cache). `ssh-fallback` es mas simple (solo Tailscale + LAN con IPs fijas).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Autostart en .bashrc
|
## Autostart en .bashrc
|
||||||
|
|
||||||
Samba y mDNS se inician automaticamente al abrir Termux. Extracto relevante de `~/.bashrc`:
|
Samba y mDNS se inician al abrir Termux. Ver `bashrc-snippet.sh` para el codigo exacto.
|
||||||
|
|
||||||
```bash
|
No se usa Termux:Boot (no funciona en este dispositivo).
|
||||||
# Iniciar Samba si no esta corriendo
|
|
||||||
if ! pgrep -x smbd > /dev/null; then
|
|
||||||
smbd -D -s ~/.config/samba/smb.conf 2>/dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Iniciar mDNS (movil.local) si no esta corriendo
|
### Aliases de gestion
|
||||||
if ! pgrep -f mdns-publish.py > /dev/null; then
|
|
||||||
nohup python ~/.local/bin/mdns-publish.py > /dev/null 2>&1 &
|
|
||||||
disown
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
No se usa Termux:Boot (no funciona). Se inicia al abrir la primera sesion de Termux.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Aliases de gestion
|
|
||||||
|
|
||||||
| Alias | Accion |
|
| Alias | Accion |
|
||||||
|-------|--------|
|
|-------|--------|
|
||||||
|
|
@ -215,43 +266,37 @@ No se usa Termux:Boot (no funciona). Se inicia al abrir la primera sesion de Ter
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Parametros de compatibilidad
|
|
||||||
|
|
||||||
| Parametro | Valor | Motivo |
|
|
||||||
|-----------|-------|--------|
|
|
||||||
| `server min protocol` | SMB2 | Win11 y Kubuntu 24 ya no usan SMB1 |
|
|
||||||
| `server max protocol` | SMB3 | Maximo rendimiento y cifrado |
|
|
||||||
| `smb encrypt` | desired | Win11 lo prefiere, negocia automaticamente |
|
|
||||||
| `server signing` | desired | Win11 lo exige desde 2024 |
|
|
||||||
| `unix charset` | UTF-8 | Acentos en nombres de archivo |
|
|
||||||
| `dos charset` | CP850 | Compatibilidad Windows |
|
|
||||||
| `use sendfile` | yes | Rendimiento en transferencias |
|
|
||||||
| `aio read/write size` | 16384 | I/O asincrono para archivos grandes |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### "Connection refused" desde otro equipo
|
### "Connection refused" desde otro equipo
|
||||||
|
|
||||||
1. Verificar que smbd corre: `smb-status`
|
1. Verificar que smbd corre: `smb-status`
|
||||||
2. Verificar puerto: `ss -tlnp | grep 4450`
|
2. Verificar puerto: `ss -tlnp | grep 4450`
|
||||||
3. Verificar firewall Android: Abrir ajustes WiFi, verificar que no hay restricciones
|
3. Verificar firewall Android: Ajustes WiFi, sin restricciones
|
||||||
|
|
||||||
### No aparece en Dolphin (Red)
|
### No aparece en Dolphin (Red)
|
||||||
|
|
||||||
1. Verificar mDNS: `mdns-status`
|
1. Verificar mDNS: `mdns-status`
|
||||||
2. Desde Kubuntu: `avahi-browse -rt _smb._tcp` (debe mostrar "movil")
|
2. Desde Kubuntu: `avahi-browse -rt _smb._tcp`
|
||||||
3. Si no aparece, reiniciar: `mdns-restart`
|
3. Si no aparece: `mdns-restart`
|
||||||
4. Acceso manual: `smb://movil.local:4450/` en barra de Dolphin
|
4. Acceso manual: `smb://movil.local:4450/`
|
||||||
|
|
||||||
### "NT_STATUS_LOGON_FAILURE"
|
### "NT_STATUS_LOGON_FAILURE"
|
||||||
|
|
||||||
Resetear password:
|
|
||||||
```bash
|
```bash
|
||||||
printf 'asde71.4\nasde71.4\n' | smbpasswd -L -s -c ~/.config/samba/smb.conf andres
|
printf 'PASS\nPASS\n' | smbpasswd -L -s -c ~/.config/samba/smb.conf USUARIO
|
||||||
```
|
```
|
||||||
|
|
||||||
### Acentos se ven mal
|
### mDNS no resuelve .local en Termux
|
||||||
|
|
||||||
Verificar que `unix charset = UTF-8` esta en `smb.conf` seccion `[global]`.
|
Termux usa su propia libc, no la de Android. Por eso `.local` no resuelve con `ping` o `getent`. Usar `mdns-resolve` en su lugar:
|
||||||
|
```bash
|
||||||
|
mdns-resolve hostname.local
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSH no conecta por nombre
|
||||||
|
|
||||||
|
Verificar que `~/.ssh/config` usa `ProxyCommand` con `ssh-mdns-proxy`:
|
||||||
|
```bash
|
||||||
|
ssh -v hostname # Ver que proxy se usa
|
||||||
|
```
|
||||||
|
|
|
||||||
33
install.sh
33
install.sh
|
|
@ -1,5 +1,5 @@
|
||||||
#!/data/data/com.termux/files/usr/bin/bash
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
# Instalador de Samba + mDNS para Termux
|
# Instalador de Samba + mDNS + scripts de red para Termux
|
||||||
# Uso: bash install.sh
|
# Uso: bash install.sh
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
|
@ -9,6 +9,7 @@ YELLOW='\033[1;33m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
|
|
||||||
SAMBA_DIR="$HOME/.config/samba"
|
SAMBA_DIR="$HOME/.config/samba"
|
||||||
|
BIN_DIR="$HOME/.local/bin"
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
|
||||||
info() { echo -e "${GREEN}[+]${NC} $1"; }
|
info() { echo -e "${GREEN}[+]${NC} $1"; }
|
||||||
|
|
@ -27,16 +28,22 @@ pip install -q zeroconf 2>/dev/null
|
||||||
info "Creando directorios..."
|
info "Creando directorios..."
|
||||||
mkdir -p "$SAMBA_DIR"/{private,lock,state,cache}
|
mkdir -p "$SAMBA_DIR"/{private,lock,state,cache}
|
||||||
chmod 0755 "$SAMBA_DIR"/{lock,state,cache}
|
chmod 0755 "$SAMBA_DIR"/{lock,state,cache}
|
||||||
|
mkdir -p "$BIN_DIR"
|
||||||
|
|
||||||
# 4. Copiar config
|
# 4. Copiar config Samba
|
||||||
info "Copiando smb.conf..."
|
info "Copiando smb.conf..."
|
||||||
cp "$SCRIPT_DIR/smb.conf" "$SAMBA_DIR/smb.conf"
|
cp "$SCRIPT_DIR/smb.conf" "$SAMBA_DIR/smb.conf"
|
||||||
|
|
||||||
# 5. Copiar script mDNS
|
# 5. Copiar scripts de red
|
||||||
info "Instalando mdns-publish.py..."
|
info "Instalando scripts de red..."
|
||||||
mkdir -p "$HOME/.local/bin"
|
for script in mdns-publish.py mdns-resolve ssh-mdns-proxy ssh-fallback; do
|
||||||
cp "$SCRIPT_DIR/mdns-publish.py" "$HOME/.local/bin/mdns-publish.py"
|
cp "$SCRIPT_DIR/scripts/$script" "$BIN_DIR/$script"
|
||||||
chmod +x "$HOME/.local/bin/mdns-publish.py"
|
chmod +x "$BIN_DIR/$script"
|
||||||
|
done
|
||||||
|
info " mdns-publish.py - Publica SSH + SMB via mDNS"
|
||||||
|
info " mdns-resolve - Resuelve hostnames .local"
|
||||||
|
info " ssh-mdns-proxy - ProxyCommand SSH con mDNS + fallback"
|
||||||
|
info " ssh-fallback - ProxyCommand SSH Tailscale + LAN"
|
||||||
|
|
||||||
# 6. Crear usuario Samba
|
# 6. Crear usuario Samba
|
||||||
info "Configurando usuario Samba..."
|
info "Configurando usuario Samba..."
|
||||||
|
|
@ -62,7 +69,13 @@ else
|
||||||
warn "Autostart ya existe en .bashrc, no se modifica"
|
warn "Autostart ya existe en .bashrc, no se modifica"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 9. Iniciar servicios
|
# 9. Verificar PATH
|
||||||
|
if ! echo "$PATH" | grep -q "$BIN_DIR"; then
|
||||||
|
warn "Agrega esto a tu .bashrc si no esta:"
|
||||||
|
echo " export PATH=\"\$HOME/.local/bin:\$PATH\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 10. Iniciar servicios
|
||||||
info "Iniciando Samba..."
|
info "Iniciando Samba..."
|
||||||
pkill smbd 2>/dev/null || true
|
pkill smbd 2>/dev/null || true
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
@ -71,10 +84,10 @@ smbd -D -s "$SAMBA_DIR/smb.conf"
|
||||||
info "Iniciando mDNS..."
|
info "Iniciando mDNS..."
|
||||||
pkill -f mdns-publish.py 2>/dev/null || true
|
pkill -f mdns-publish.py 2>/dev/null || true
|
||||||
sleep 1
|
sleep 1
|
||||||
nohup python "$HOME/.local/bin/mdns-publish.py" > /dev/null 2>&1 &
|
nohup python "$BIN_DIR/mdns-publish.py" > /dev/null 2>&1 &
|
||||||
disown
|
disown
|
||||||
|
|
||||||
# 10. Verificar
|
# 11. Verificar
|
||||||
sleep 2
|
sleep 2
|
||||||
if pgrep -x smbd > /dev/null && pgrep -f mdns-publish > /dev/null; then
|
if pgrep -x smbd > /dev/null && pgrep -f mdns-publish > /dev/null; then
|
||||||
info "Todo corriendo."
|
info "Todo corriendo."
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
#!/data/data/com.termux/files/usr/bin/python3
|
||||||
|
"""
|
||||||
|
Resuelve hostname.local via mDNS multicast.
|
||||||
|
Uso: mdns-resolve <hostname.local>
|
||||||
|
Retorna: IP address o exit 1
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import select
|
||||||
|
|
||||||
|
def build_mdns_query(hostname: str) -> bytes:
|
||||||
|
"""Construye query DNS para hostname."""
|
||||||
|
# Header: ID=0, Flags=0, QDCOUNT=1, ANCOUNT=0, NSCOUNT=0, ARCOUNT=0
|
||||||
|
header = struct.pack('>HHHHHH', 0, 0, 1, 0, 0, 0)
|
||||||
|
|
||||||
|
# Question section
|
||||||
|
question = b''
|
||||||
|
for part in hostname.rstrip('.').split('.'):
|
||||||
|
question += bytes([len(part)]) + part.encode()
|
||||||
|
question += b'\x00' # End of name
|
||||||
|
question += struct.pack('>HH', 1, 1) # Type A, Class IN
|
||||||
|
|
||||||
|
return header + question
|
||||||
|
|
||||||
|
def parse_mdns_response(data: bytes, hostname: str) -> str | None:
|
||||||
|
"""Parsea respuesta mDNS y extrae IP."""
|
||||||
|
if len(data) < 12:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Skip header, find answers
|
||||||
|
qdcount = struct.unpack('>H', data[4:6])[0]
|
||||||
|
ancount = struct.unpack('>H', data[6:8])[0]
|
||||||
|
|
||||||
|
if ancount == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Skip questions
|
||||||
|
offset = 12
|
||||||
|
for _ in range(qdcount):
|
||||||
|
while offset < len(data) and data[offset] != 0:
|
||||||
|
if data[offset] & 0xc0 == 0xc0: # Compression
|
||||||
|
offset += 2
|
||||||
|
break
|
||||||
|
offset += data[offset] + 1
|
||||||
|
else:
|
||||||
|
offset += 1
|
||||||
|
offset += 4 # Type + Class
|
||||||
|
|
||||||
|
# Parse answers
|
||||||
|
for _ in range(ancount):
|
||||||
|
# Skip name (handle compression)
|
||||||
|
while offset < len(data):
|
||||||
|
if data[offset] & 0xc0 == 0xc0:
|
||||||
|
offset += 2
|
||||||
|
break
|
||||||
|
elif data[offset] == 0:
|
||||||
|
offset += 1
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
offset += data[offset] + 1
|
||||||
|
|
||||||
|
if offset + 10 > len(data):
|
||||||
|
break
|
||||||
|
|
||||||
|
rtype, rclass, ttl, rdlength = struct.unpack('>HHIH', data[offset:offset+10])
|
||||||
|
offset += 10
|
||||||
|
|
||||||
|
# Type A (1) = IPv4 address
|
||||||
|
if rtype == 1 and rdlength == 4 and offset + 4 <= len(data):
|
||||||
|
ip = socket.inet_ntoa(data[offset:offset+4])
|
||||||
|
return ip
|
||||||
|
|
||||||
|
offset += rdlength
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_mdns(hostname: str, timeout: float = 2.0) -> str | None:
|
||||||
|
"""Resuelve hostname via mDNS multicast."""
|
||||||
|
if not hostname.endswith('.local'):
|
||||||
|
hostname += '.local'
|
||||||
|
|
||||||
|
MDNS_ADDR = '224.0.0.251'
|
||||||
|
MDNS_PORT = 5353
|
||||||
|
|
||||||
|
try:
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
sock.setblocking(False)
|
||||||
|
|
||||||
|
# Enviar query
|
||||||
|
query = build_mdns_query(hostname)
|
||||||
|
sock.sendto(query, (MDNS_ADDR, MDNS_PORT))
|
||||||
|
|
||||||
|
# Esperar respuesta
|
||||||
|
end_time = __import__('time').time() + timeout
|
||||||
|
while __import__('time').time() < end_time:
|
||||||
|
ready, _, _ = select.select([sock], [], [], 0.1)
|
||||||
|
if ready:
|
||||||
|
try:
|
||||||
|
data, addr = sock.recvfrom(4096)
|
||||||
|
ip = parse_mdns_response(data, hostname)
|
||||||
|
if ip:
|
||||||
|
sock.close()
|
||||||
|
return ip
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
sock.close()
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Uso: mdns-resolve <hostname.local>", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
hostname = sys.argv[1]
|
||||||
|
timeout = float(sys.argv[2]) if len(sys.argv) > 2 else 2.0
|
||||||
|
|
||||||
|
ip = resolve_mdns(hostname, timeout)
|
||||||
|
if ip:
|
||||||
|
print(ip)
|
||||||
|
sys.exit(0)
|
||||||
|
else:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
#
|
||||||
|
# ssh-fallback: Proxy para SSH con fallback automático
|
||||||
|
# Usado como ProxyCommand en ~/.ssh/config
|
||||||
|
#
|
||||||
|
# Uso: ssh-fallback <tailscale_host> <lan_ip> <port>
|
||||||
|
|
||||||
|
TAILSCALE_HOST="$1"
|
||||||
|
LAN_IP="$2"
|
||||||
|
PORT="${3:-22}"
|
||||||
|
|
||||||
|
# Intentar Tailscale primero (1 segundo timeout)
|
||||||
|
if ping -c 1 -W 1 "$TAILSCALE_HOST" &>/dev/null 2>&1; then
|
||||||
|
exec nc -w 5 "$TAILSCALE_HOST" "$PORT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback a IP LAN
|
||||||
|
if ping -c 1 -W 1 "$LAN_IP" &>/dev/null 2>&1; then
|
||||||
|
exec nc -w 5 "$LAN_IP" "$PORT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Último intento: Tailscale sin verificar
|
||||||
|
exec nc -w 10 "$TAILSCALE_HOST" "$PORT"
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
#\!/data/data/com.termux/files/usr/bin/bash
|
||||||
|
# ssh-mdns-proxy: Resolve .local via mDNS with fallbacks, then connect
|
||||||
|
HOST="$1"
|
||||||
|
PORT="${2:-22}"
|
||||||
|
CACHE="$HOME/.ssh/mdns-cache"
|
||||||
|
QUERY="${HOST%.local}"
|
||||||
|
|
||||||
|
# Alias mapping (short name → mDNS hostname)
|
||||||
|
declare -A ALIASES=(
|
||||||
|
[dell]="dell-latitude3400"
|
||||||
|
[lenovo]="lenovo-ideapad"
|
||||||
|
)
|
||||||
|
[[ -n "${ALIASES[$QUERY]}" ]] && QUERY="${ALIASES[$QUERY]}"
|
||||||
|
|
||||||
|
# 1. mDNS resolution
|
||||||
|
IP=$("$HOME/.local/bin/mdns-resolve" "${QUERY}.local" 2 2>/dev/null)
|
||||||
|
|
||||||
|
# 2. Fallback: Tailscale DNS
|
||||||
|
if [[ -z "$IP" ]]; then
|
||||||
|
IP=$(getent hosts "${QUERY}.tailb0bb74.ts.net" 2>/dev/null | awk "{print \$1}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Fallback: cached IP
|
||||||
|
if [[ -z "$IP" && -f "$CACHE" ]]; then
|
||||||
|
IP=$(grep "^${QUERY} " "$CACHE" 2>/dev/null | awk "{print \$2}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$IP" ]]; then
|
||||||
|
echo "Error: cannot resolve ${HOST}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Save to cache
|
||||||
|
mkdir -p "$(dirname "$CACHE")"
|
||||||
|
grep -v "^${QUERY} " "$CACHE" > "${CACHE}.tmp" 2>/dev/null || true
|
||||||
|
echo "${QUERY} ${IP}" >> "${CACHE}.tmp"
|
||||||
|
mv "${CACHE}.tmp" "$CACHE"
|
||||||
|
|
||||||
|
exec nc "$IP" "$PORT"
|
||||||
44
smb.conf
44
smb.conf
|
|
@ -56,16 +56,16 @@
|
||||||
server multi channel support = yes
|
server multi channel support = yes
|
||||||
mdns name = mdns
|
mdns name = mdns
|
||||||
|
|
||||||
[Archivos]
|
[Almacenamiento]
|
||||||
comment = Archivos de trabajo
|
comment = Memoria interna Android
|
||||||
path = /storage/emulated/0/Archivos
|
path = /storage/emulated/0
|
||||||
browseable = yes
|
browseable = yes
|
||||||
writable = yes
|
writable = yes
|
||||||
valid users = andres
|
valid users = andres
|
||||||
create mask = 0644
|
create mask = 0644
|
||||||
directory mask = 0755
|
directory mask = 0755
|
||||||
|
|
||||||
[Home]
|
[Termux]
|
||||||
comment = Home Termux
|
comment = Home Termux
|
||||||
path = /data/data/com.termux/files/home
|
path = /data/data/com.termux/files/home
|
||||||
browseable = yes
|
browseable = yes
|
||||||
|
|
@ -73,39 +73,3 @@
|
||||||
valid users = andres
|
valid users = andres
|
||||||
create mask = 0644
|
create mask = 0644
|
||||||
directory mask = 0755
|
directory mask = 0755
|
||||||
|
|
||||||
[Downloads]
|
|
||||||
comment = Descargas Android
|
|
||||||
path = /storage/emulated/0/Download
|
|
||||||
browseable = yes
|
|
||||||
writable = yes
|
|
||||||
valid users = andres
|
|
||||||
create mask = 0644
|
|
||||||
directory mask = 0755
|
|
||||||
|
|
||||||
[Documents]
|
|
||||||
comment = Documentos Android
|
|
||||||
path = /storage/emulated/0/Documents
|
|
||||||
browseable = yes
|
|
||||||
writable = yes
|
|
||||||
valid users = andres
|
|
||||||
create mask = 0644
|
|
||||||
directory mask = 0755
|
|
||||||
|
|
||||||
[DCIM]
|
|
||||||
comment = Fotos y Videos
|
|
||||||
path = /storage/emulated/0/DCIM
|
|
||||||
browseable = yes
|
|
||||||
writable = yes
|
|
||||||
valid users = andres
|
|
||||||
create mask = 0644
|
|
||||||
directory mask = 0755
|
|
||||||
|
|
||||||
[Movies]
|
|
||||||
comment = Peliculas
|
|
||||||
path = /storage/emulated/0/Movies
|
|
||||||
browseable = yes
|
|
||||||
writable = yes
|
|
||||||
valid users = andres
|
|
||||||
create mask = 0644
|
|
||||||
directory mask = 0755
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue