You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Gateproxy is a modular ecosystem for the administration and management of LAN environments in small and medium-sized businesses, comprising independent projects and components that can be used autonomously but are designed to interoperate within the same environment. Its architecture integrates tools and services such as Proxymon, pydhcp, smbstack, uhm, Apache2, iptables/ipset, suricata, unbound, among others, providing proxy, firewall, DHCP, traffic control and management, web services, and other resources required for network operation. The installation and configuration script automates the deployment of these components and can be adapted to the needs of the administrator or organization, requiring minimal interaction during the process. Some projects are included as part of the base configuration, while others are offered as optional installations. Gateproxy can be deployed on both physical servers and virtual machines, providing flexibility and portability for different infrastructure environments.
Gateproxy es un ecosistema modular para la administración y gestión de redes LAN de pequeñas y medianas empresas, compuesto por proyectos y componentes independientes que pueden utilizarse de forma autónoma, pero que pueden interoperar dentro de un mismo entorno. Su arquitectura integra herramientas y servicios como Proxymon, pydhcp, smbstack, uhm, Apache2, iptables/ipset, suricata, unbound, entre otros, proporcionando funciones de proxy, firewall, DHCP, control y administración del tráfico, servicios web y otros recursos necesarios para la operación de la red. El script de instalación y configuración automatiza el despliegue de estos componentes y puede adaptarse a las necesidades del administrador u organización, procurando una interacción mínima durante el proceso. Algunos proyectos forman parte de la configuración base, mientras que otros se ofrecen como instalaciones opcionales. Puede implementarse tanto en servidores físicos como en máquinas virtuales, proporcionando flexibilidad y portabilidad para diferentes escenarios de infraestructura.
Requirements
⚠️ WARNING: Only tested on Ubuntu 24.04 LTS. Other versions or distros not tested, use at your own risk.
CPU
NIC
RAM
Storage
4+ cores (≥ 3.0 GHz)
2 (WAN & LAN)
12+ GB (4 GB cache_mem)
100 GB SSD (cache_dir rock)
HOW TO USE
Run the following command on a fresh installation. The script must be executed as root or with sudo. It will self-delete after completion and reboot the system automatically.
Ejecute el siguiente comando en una instalación limpia. El script debe ejecutarse como root o con sudo. Se eliminará automáticamente al finalizar y reiniciará el sistema.
Before installing anything, the script checks for conflicting software already on the system: isc-dhcp-server/dnsmasq (DHCP), squid/squid3/tinyproxy/privoxy/3proxy (proxy), nginx/lighttpd/caddy (web server), bind9/pdns-recursor (DNS server), syslog-ng, firewalld, snort, or an active ufw. If any of these are present, the installer aborts with instructions to remove them first.
Antes de instalar nada, el script verifica que no haya software en conflicto ya presente: isc-dhcp-server/dnsmasq (DHCP), squid/squid3/tinyproxy/privoxy/3proxy (proxy), nginx/lighttpd/caddy (servidor web), bind9/pdns-recursor (servidor DNS), syslog-ng, firewalld, snort, o un ufw activo. Si detecta alguno, el instalador aborta con instrucciones para removerlo primero.
SETUP PARAMETERS
During installation, the script will detect your network interfaces and ask you to confirm or replace the following default values. All parameters are applied across configuration files automatically via sed replacement.
Durante la instalación, el script detectará sus interfaces de red y le pedirá confirmar o reemplazar los siguientes valores por defecto. Todos los parámetros se aplican automáticamente en los archivos de configuración mediante reemplazo con sed.
Parameter
Default
Description / Descripción
WAN Interface
none (required)
Chosen from a numbered list of detected interfaces, with explicit y/n confirmation before continuing -- no typing, no silent default / Se elige de una lista numerada de interfaces detectadas, con confirmación explícita y/n antes de continuar -- no se escribe, no hay default silencioso
LAN Interface
none (required)
Same numbered-list + confirmation flow as WAN Interface; cannot be the same interface already assigned to WAN / Mismo flujo de lista numerada + confirmación que WAN Interface; no puede ser la misma interfaz ya asignada a WAN
Server IP
192.168.0.10
Gateway IP assigned to this server / IP del servidor en la LAN
Netmask
255.255.255.0
Subnet mask; CIDR prefix (/24) is derived from this automatically, not asked separately / Máscara de subred; el prefijo CIDR (/24) se calcula automáticamente a partir de esto, no se pregunta por separado
DNS Primary
1.1.1.2
Primary DNS server / DNS primario
DNS Secondary
1.0.0.2
Secondary DNS server / DNS secundario
Proxy Port
3128
Squid proxy port / Puerto del proxy Squid
Localnet (192.168.0.0) is derived automatically from the Server IP and Netmask together, not asked separately / Localnet (192.168.0.0) se deriva automáticamente del Server IP y la Netmask en conjunto, no se pregunta por separado.
DNS Primary/Secondary above only configure Unbound's own forwarders (conf/unbound/forward.conf) — where Unbound sends queries it can't answer locally. They do not control which DNS server LAN clients are allowed to query directly; that is pydhcp's own SERV_DNS key in pydhcp.env (the same value pydhcp hands out via DHCP), which iptables.sh reads to open the matching firewall access — no separate gateproxy key to keep in sync by hand. It defaults to the Server IP (Unbound); leaving it unset or empty falls back to the Server IP as well, never to 1.1.1.2/1.0.0.2. To have clients use and reach external DNS directly instead of Unbound, edit SERV_DNS in pydhcp.env by hand, regenerate pydhcpd.conf with pydhcp's pyleases.sh, restart pydhcpd, and re-run iptables.sh.
Los DNS Primario/Secundario de arriba sólo configuran los reenviadores propios de Unbound (conf/unbound/forward.conf) — a dónde manda Unbound las consultas que no puede resolver localmente. No controlan a qué servidor DNS pueden consultar directamente los clientes de la LAN; eso lo controla la propia clave SERV_DNS de pydhcp en pydhcp.env (el mismo valor que pydhcp entrega por DHCP), que iptables.sh lee para abrir el acceso correspondiente en el firewall — no hay una clave aparte de gateproxy que sincronizar a mano. Por defecto es el Server IP (Unbound); dejarla sin definir o vacía también cae en el Server IP, nunca en 1.1.1.2/1.0.0.2. Para que los clientes usen y puedan alcanzar DNS externo en vez de Unbound, hay que editar SERV_DNS a mano en pydhcp.env, regenerar pydhcpd.conf con pyleases.sh de pydhcp, reiniciar pydhcpd, y volver a correr iptables.sh.
Once pydhcp is installed, the script substitutes its own values (WAN interface, proxy port) into conf/ with sed before deploying, so they end up written into the firewall script itself. It never writes into pydhcp.env, which belongs to pydhcp. LAN interface, IP, netmask and DNS are written instead by pydhcp's own pysetup.sh, from the values gateproxy passes it via expect. iptables.sh reads that same file at any time afterward. There is no "reuse previous answers" step — each run asks fresh.
Una vez instalado pydhcp, el script sustituye sus propios valores (interfaz WAN, puerto del proxy) dentro de conf/ con sed antes de desplegar, así que quedan escritos en el propio script del firewall. Nunca escribe en pydhcp.env, que pertenece a pydhcp. La interfaz LAN, la IP, la máscara y el DNS los escribe en cambio el propio pysetup.sh de pydhcp, con los valores que gateproxy le pasa por expect. iptables.sh lee ese mismo archivo en cualquier momento después. No existe un paso de "reusar respuestas anteriores" — cada corrida pregunta de nuevo.
To identify the correct interface names before running the installer, use:
Para identificar los nombres correctos de interfaces antes de ejecutar el instalador, use:
join <(ip -o -br link | sort)<(ip -o -br addr | sort)| awk '$2=="UP" {print $1,$6,$3}'| sed -Ee 's./[0-9]+..'
COMPONENTS
Gateproxy installs and configures the following components automatically.
Gateproxy instala y configura los siguientes componentes automáticamente.
Proxy
Component
Port
Notes
Squid (squid-openssl)
3128
Explicit proxy with rock/ufs cache
Squid (squid-openssl)
3129
Intercept port — catches captive-portal probes and any client not using the PAC, filtered by the same ACLs as the explicit proxy
WPAD/PAC (Apache2)
18100
Proxy auto-config served via wpad.pac
Proxymon
18080
Bandwidth monitoring dashboard
Proxymon
18081
Bandwidth quota warning page (bandata redirect)
Web / Admin
Component
Port
Notes
Apache2
80
Web server with PHP support; hosts WPAD and admin pages
Webmin
10000
Server administration panel (https://localhost:10000)
Webmin is installed with the following modules / Webmin se instala con los siguientes módulos:
Text Editor — edit ACL files directly from the browser / editar archivos ACL desde el navegador
Service Monitor (servicemon) — watch and restart services / monitorear y reiniciar servicios
Netplan Manager (netplanmgr) — manage network configuration / gestionar configuración de red
DHCP
Component
Config
Notes
pydhcp
/etc/pydhcp/core/pydhcpd.conf
Python-based DHCP server; default pool range 220–235
Pool range and other DHCP settings can be changed in /etc/pydhcp/pydhcp.env after installation / El rango del pool y otros parámetros DHCP pueden modificarse en /etc/pydhcp/pydhcp.env luego de la instalación.
DNS
Component
Config
Notes
Unbound
/etc/unbound/unbound.conf.d/forward.conf
Forwarding resolver (not recursive/iterative); listens on 127.0.0.1 and the server IP; forwards to 1.1.1.2/1.0.0.2. DHCP clients receive the server IP as their DNS server.
Firewall
Component
Config
Notes
iptables + ipset
/etc/scr/iptables.sh
Stateful firewall with MAC-based access control
ulogd2
/var/log/ulog/syslogemu.log
Kernel-level packet logging via NFLOG
Backup
Component
Notes
Timeshift
System snapshots
FreeFileSync
File mirror sync; auto-updated weekly via /etc/scr/ffsupdate.sh
All access control lists are stored under /etc/acl/, organized by service. Files are deployed from the repository only if missing (an existing file, from a previous install or from another project sharing this path, is never overwritten) and managed by Webmin's Text Editor module.
Todas las listas de control de acceso se almacenan en /etc/acl/, organizadas por servicio. Los archivos se despliegan desde el repositorio solo si faltan (uno ya existente, de una instalación previa o de otro proyecto que comparte esta ruta, nunca se sobreescribe) y se administran con el módulo Text Editor de Webmin.
/etc/acl/
├── mac/ # MAC address lists for iptables ipsets
│ ├── mac-limited.txt # MACs routed through Squid (port 3128)
│ └── mac-unlimited.txt # MACs with unrestricted access (APs, switches)
├── squid/ # Squid proxy ACLs
│ ├── aipextra.txt # Additional allowed IPs (bypass blacklist)
│ ├── allowdomains.txt # Allowed domains (whitelist)
│ ├── blockdomains.txt # Blocked domains (blacklist)
│ ├── blockext.txt # Blocked file extensions
│ ├── blockmime.txt # Blocked MIME types
│ └── blockpatterns.txt # Blocked URL patterns (BitTorrent, scrapers…)
└── ipt/ # iptables ACLs
├── blockports.txt # Blocked port ranges (VPN, P2P, cryptomining…)
├── bogons.txt # Bogon/unroutable IP ranges
├── dhcp_ip.txt # IP list derived from DHCP leases (auto-generated by iptables.sh)
└── dhcp_mac.txt # MAC list derived from DHCP leases (auto-generated by iptables.sh)
Suricata's blocklist (suridata.txt) is not under /etc/acl/: it lives in /etc/suricata/suridata.txt, generated by suridata.sh. MACs blocked from a DHCP lease (blockdhcp.txt) belong to a different project (pydhcp) and live at /etc/pydhcp/acl/blockdhcp.txt, outside gateproxy's /etc/acl/.
MAC list files use pydhcp's own entry format: a;MAC;IP;HOSTNAME;. The leading a marks an active entry — iptables.sh only reads lines starting with a; and a non-empty MAC field; anything else (including a different leading character or a commented-out #a;... line) is ignored.
Los archivos de listas MAC usan el mismo formato de entrada que pydhcp: a;MAC;IP;HOSTNAME;. La `a` inicial marca una entrada activa — iptables.sh sólo lee líneas que empiecen con a; y tengan el campo MAC no vacío; cualquier otra cosa (incluido un carácter inicial distinto o una línea comentada #a;...) se ignora.
FIREWALL
The firewall (iptables.sh) uses an O(1) ipset-based architecture. Every LAN device is identified by MAC+IP binding derived from the DHCP server config. Global IPv4 policy is permissive with explicit drops; IPv6 is closed by default on LAN.
El firewall (iptables.sh) usa una arquitectura basada en ipset O(1). Cada dispositivo LAN es identificado por enlace MAC+IP derivado de la configuración del servidor DHCP. La política IPv4 global es permisiva con drops explícitos; IPv6 está cerrado por defecto en LAN.
ipsets
ipset
Type
Purpose
macunlimited
hash:mac
Full bypass — APs, managed switches, and similar infrastructure devices. Requires a matching static reservation in pydhcpd.conf in addition to being listed here — MACCHECK (see below) checks macip, not this list directly. Run pydhcp's pyleases.sh after editing this file, or add the reservation by hand
maclimited
hash:mac
Routed through Squid: explicit via PAC (port 3128, served on port 18100) for compliant clients, or intercepted (port 3129) for direct/non-PAC HTTP. Same pydhcpd.conf reservation requirement as macunlimited above
macports
hash:mac
Registered devices with controlled port access (DNS, printing, email, STUN, etc.). Same pydhcpd.conf reservation requirement as macunlimited above
macip
hash:ip,mac
MAC+IP binding, parsed from pydhcpd.conf. Gatekeeper for every other list below — a device not in macip is dropped before macunlimited/maclimited/macports are ever evaluated
blockports
bitmap:port
Blocked port ranges (VPN tunnels, P2P, cryptomining, legacy protocols)
suridata
hash:ip
Dest IPs flagged by Suricata alerts matching a drop.conf signature — silent DROP, see below
bandata
hash:ip
IPs over bandwidth quota — DNS and port 80 only, redirected to warning page. Created and populated by Proxymon, not by iptables.sh — Proxymon is installed by gateproxy.sh as a bundled optional component (see Optional Packages); iptables.sh only opens the warning-page port (18081) for it
macip is built from pydhcpd.conf's static host {} blocks, not from mac-*.txt directly. Adding a MAC to mac-unlimited.txt/mac-limited.txt classifies it, but does not by itself grant it network access — it still needs a matching static reservation in pydhcpd.conf, or the firewall's MACCHECK step drops its traffic regardless of classification. pydhcp ships an optional tool, tools/pyleases.sh, that generates those reservations from the same mac-*.txt files — run it after editing any of them (it is not scheduled automatically by any installer, see the Scripts section below).
Blocked Ports (blockports.txt)
The following categories are blocked outbound from LAN by default.
Las siguientes categorías están bloqueadas por defecto en tráfico saliente desde la LAN.
Suricata runs passive (AF-PACKET, IDS mode) — it can never block traffic on its own, regardless of what drop.conf says. suridata.sh (cron, every 5 minutes) is what turns a drop.conf match into a real block: it reads the SIDs suricata-update already resolved to drop action in suricata.rules (covers both literal SIDs and re: message-regex entries in drop.conf), tails only the new lines of eve.json since its last run, and for every alert whose signature_id matches, appends the flow's dest_ip to suridata.txt. iptables.sh loads that file into the suridata ipset and drops matching destinations at mangle PREROUTING — silently, no warning page (unlike bandata, this blocks a destination, not a client). No expiry: entries are removed by hand, same model as blockports.txt. macunlimited members (APs, switches) are exempt, same as blockports.
Editing drop.conf / disable.conf:suricataupdate.sh is the only script that reads these files and applies them to suricata.rules; it only runs once a day via cron (2 AM). A SID you just added to drop.conf stays as plain alert (not blocked) until that cron runs. To apply the change immediately, run both in order: sudo /etc/suricata/suricataupdate.sh && sudo /etc/suricata/suridata.sh — on that first suridata.sh run after the SID becomes drop, it also does a one-time full eve.json rescan for that SID (tracked via suridata.sids), so alerts that already fired earlier that day get backfilled into suridata.txt too, not just alerts from that point forward.
Suricata corre en modo pasivo (AF-PACKET, IDS) — nunca puede bloquear tráfico por sí solo, sin importar lo que diga drop.conf. suridata.sh (cron, cada 5 minutos) es lo que convierte un match de drop.conf en un bloqueo real: lee los SIDs que suricata-update ya resolvió a acción drop en suricata.rules (cubre tanto SIDs literales como entradas re: de regex de mensaje en drop.conf), lee solo las líneas nuevas de eve.json desde su última corrida, y por cada alerta cuyo signature_id coincide, agrega el dest_ip del flujo a suridata.txt. iptables.sh carga ese archivo al ipset suridata y bloquea los destinos que coincidan en mangle PREROUTING — de forma silenciosa, sin página de aviso (a diferencia de bandata, esto bloquea un destino, no un cliente). Sin expiración: las entradas se retiran a mano, mismo modelo que blockports.txt. Los miembros de macunlimited (APs, switches) quedan exentos, igual que con blockports.
Al editar drop.conf / disable.conf:suricataupdate.sh es el único script que lee estos archivos y los aplica a suricata.rules; corre una sola vez al día por cron (2 AM). Una SID recién agregada a drop.conf queda como alert plano (sin bloquear) hasta que corra ese cron. Para aplicar el cambio de inmediato, corre ambos en orden: sudo /etc/suricata/suricataupdate.sh && sudo /etc/suricata/suridata.sh — en esa primera corrida de suridata.sh después de que la SID pasa a drop, también hace un escaneo completo único de eve.json para esa SID (rastreado vía suridata.sids), así que las alertas que ya habían ocurrido ese mismo día también quedan agregadas a suridata.txt, no solo las de ahí en adelante.
Security Rules
SYN flood protection via rate-limited syn_flood chain
TCP scan / malformed packet drops (SYN+FIN, SYN+RST, NEW with SYN+ACK)
Bittorrent/Tor and other protocol-level detection is handled by Suricata (see Optional Packages below), not by hex-string matching in iptables.sh
GRE (protocol 47) and 6to4 (protocol 41) blocked from LAN
Windows ICS network range (192.168.137.0/24) blocked
Bogon/reserved-range filtering (RFC1918, link-local, test-nets, etc.) is available in iptables.sh but disabled by default — enabling it blindly can lock the LAN out of its own network if the server's subnet falls inside a blocked RFC1918 range; see the comment above the BOGONS block before enabling it
Allowed LAN Services (macports)
Devices registered in macports have access to the following / Los dispositivos registrados en macports tienen acceso a los siguientes servicios:
DNS (UDP/TCP 53) is a global rule applied to all LAN traffic, not a macports-specific privilege — see SERV_DNS above / DNS (UDP/TCP 53) es una regla global aplicada a todo el tráfico LAN, no un privilegio específico de macports — ver SERV_DNS arriba.
OPTIONAL PACKAGES
The installer offers three optional installation prompts at the end of the base setup.
El instalador ofrece tres prompts de instalación opcionales al final de la configuración base.
Installs smbstack — a Samba server with a shared folder, Recycle Bin, and audit logging configured out of the box. smbstack manages its own veto list for common unwanted file types (/etc/samba/acl/commonveto.txt, active by default) — not gateproxy's responsibility.
Instala smbstack — un servidor Samba con carpeta compartida, Papelera de Reciclaje y registro de auditoría configurados de fábrica. smbstack gestiona su propia lista veto de tipos de archivo comunes no deseados (/etc/samba/acl/commonveto.txt, activa por defecto) — no es responsabilidad de gateproxy.
Optional Pack: UHM
This prompt only appears if a local UniFi Network controller is detected first — classic (dpkg package unifi) or unifi-os (/var/lib/uosserver/server.conf, podman-based). If neither is found, the prompt is skipped entirely — gateproxy does not install UniFi or podman itself. To install UniFi Network self-hosted / UniFi OS Server first, use unifisetup.sh, then re-run gateproxy (or run uhmsetup.sh from the uhm repo directly). Installs uhm (UniFi Hotspot Manager), which requires pydhcp already installed and running — a requirement gateproxy's own base setup already satisfies. uhm runs its own interactive installer (uhmsetup.sh): it reads pydhcp's network values from pydhcp.env automatically, then prompts for its own UniFi-specific settings (controller credentials, SSID, etc.) directly.
Este prompt sólo aparece si primero se detecta un controlador UniFi Network local — classic (paquete dpkgunifi) o unifi-os (/var/lib/uosserver/server.conf, basado en podman). Si no se detecta ninguno, el prompt se omite por completo — gateproxy no instala UniFi ni podman por sí mismo. Para instalar primero UniFi Network self-hosted / UniFi OS Server, use unifisetup.sh, y luego vuelva a ejecutar gateproxy (o ejecute uhmsetup.sh directamente desde el repo de uhm). Instala uhm (UniFi Hotspot Manager), que requiere tener pydhcp ya instalado y corriendo — requisito que la configuración base de gateproxy ya satisface. uhm ejecuta su propio instalador interactivo (uhmsetup.sh): lee automáticamente los valores de red de pydhcp desde pydhcp.env, y luego pregunta directamente por sus propios parámetros específicos de UniFi (credenciales del controlador, SSID, etc.).
POST-INSTALL
Scripts (/etc/scr/)
The following scripts from scr/ are copied to /etc/scr/ during installation / Los siguientes scripts de scr/ se copian a /etc/scr/ durante la instalación:
Script
Trigger
Purpose
iptables.sh
manual
Load firewall rules and ipsets
serverboot.sh
manual (alias server)
Start/restart all server services
serviceswatch.sh
every 5 min
Restart failed services
killswitch.sh
manual
Block all traffic in emergency
bkconf.sh
manual
Backup configuration files
Some deployed tools — iptables.sh here, and pydhcp's own pyleases.sh — are never added to cron automatically by any installer. Scheduling them (or not) is entirely up to the operator, based on their own needs.
Algunas herramientas desplegadas — iptables.sh aquí, y pyleases.sh de pydhcp — nunca se agregan al cron automáticamente por ningún instalador. Programarlas (o no) queda enteramente a criterio del operador, según sus necesidades.
The installer also downloads the following scripts from external repositories / El instalador también descarga los siguientes scripts de repositorios externos:
Script
Trigger
Purpose
hwclock.sh
@reboot
Sync hardware clock
blackusb.sh
@reboot
USB device access control
cleaner.sh
@weekly
System cleanup
ffsupdate.sh
@weekly
Update FreeFileSync
filereport.sh
manual
Generate file system report
Shell Aliases
Added to ~/.bashrc for the local user / Agregados al ~/.bashrc del usuario local:
alias upgrade # full system upgrade (nala + aptitude + snap)alias server # run /etc/scr/serverboot.shalias cleaner # run /etc/scr/cleaner.sh
Gateproxy is a script designed for very specific network environments (see Requirements above for the supported OS/version). It is not intended for general or production use. Using it outside the environment for which it was designed may cause unexpected behavior or system misconfiguration. Use at your own risk.
Gateproxy es un script diseñado para entornos de red muy específicos (ver Requirements arriba para el SO/versión soportada). No está destinado para uso general ni en producción. Usarlo fuera del entorno para el que fue diseñado puede causar comportamientos inesperados o una mala configuración del sistema. Úselo bajo su propio riesgo.
DISCLAIMER
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.