En este post la idea es crear un portal cautivo para un esquema de este tipo:
en la eth2 incluimos 2 rutas estáticas: la de la red de interconexión gateway-portal y la de la red de clientes 192.168.2.x que gestiona el portal cautivo.
6. FIREWALL:
7. HTB
PORTAL CAUTIVO
1. Instalar distro (yo ubuntu 12.04 lts)
2. Interficies
la eth1:0 es una red /27 (32 hosts) que uso como red para administrar los puntos de acceso u otros dispositivos transparentes a los clientes.
3. Servidor DHCP:
3. Servidor Web: Apache
4. Servidor Base de datos: Postgresql
La manera por defecto de iniciar postgresql que tiene el instalador de ubuntu/debian no me gusta para tener bases de datos pequeñitas como las mías por lo que hago un script que inicio postgres tal y como pone el propio manual de postgresql.org.
Después pongo la base de datos en /home/postgres porque en la partición /home es donde tengo mucha mas espacio.
Finalmente creo el usuario y la base de datos para freeradius y configuro postgres para que solo acepte conexiones de localhost ya que el servidor freeradius está en la misma máquina.
5. Servidor Auth: Freeradius
6. Dialup Admin:
7. Firewall
8. Scripts para dejar pasar un cliente
La idea es guardar en /var/spool/wifi/taula una lista de las MAC autorizadas a passar. Este ficherito, chmod 600 para que solo pueda ser leido y modificado para root.
Los scripts solo ejecutables por root (chmod 700)
hostadd.sh
hostdel.sh
hosttest.sh
el hosttest.sh lo ponemos en el cron para que se ejecute cada 1,2 o 3 minutos para que vaya vea los dispositivos que estan activos en la red de clientes, y aquellos que no lo estén los quito.
9. SUDO
Problema: estos scripts los ejecutara un php desde el portal cautivo, es decir, como el usuario www-data (o el que sea). Este usuario no puede modificar el firewall, ni ejecutar estos scripts. Primero pense en chmod +s pero resulta que ubuntu tiene implementada una proteccion en el kernel que no aplica los setgid o setuid en scripts. Así que lo que tengo que hacer es que www-data pueda hacer sudo sin password para estos scripts
visudo
Cmnd_Alias HOSTADD = /usr/local/bin/hostadd.sh
Cmnd_Alias HOSTDEL = /usr/local/bin/hostdel.sh
www-data ALL = (root) NOPASSWD: HOSTADD
www-data ALL = (root) NOPASSWD: HOSTDEL
10. Portal Cautivo
(a) Se trata de hacer una web con un formulario que pida user y password y su submit ejecute un php.
(b) Como no se hacer webs, he instalado dokuwiki
(c) Plugins de dokuwiki: formular, wrap, note, columns, tabinclue.
(d) Poner una template que te guste.
(e) Crear la página:
(f) Crear otras páginas de OK, de NO OK, etc.
11. PHP para permitir acceder un cliente
Así pues se ejecutará el script /data/formplugin/test.php cuando un usuario ponga su user/password en la web. Este php lo único que tiene que hacer es autentificar contra radius y llamar (o no) a los scripts que hemos creado:
12. HTB
13. REDIRECCIONES
La diversíon está en que una modificación de una pagina implica hacerla en varios idiomas y en las versiones móviles de cada idioma, pero en principio, el portal cautivo, pocas modificaciones hay que hacerle.
Jarl!
. INTERNET | +---+---+ |gateway| +---------+ | linux +----------+ red mgmt| +---+---+ +---------+ | +---+-----+ |p.cautivo| | linux | +---+-----+ | +------+----+-----+---------+ | | | | AP AP AP PC
Usaremos:
- Iptables y tc tanto en el gateway como el portal cautivo para crear el firewall y el control de tráfico para una salida a Internet de 10 Mbps simétrico. Usaré HTB.
- ISC-Dhcp-server
- FreeRadius para la authentificación
- Dialup-Admin para la interfaz web a freeradius
- Postgresql como base de datos que usa freeradius.
- Apache como servidor web + php
- Dokuwiki como CMS simple, para aquellos como yo que de hacer webs desde 0 mal.
Nota: Existen otros software ya implementados para hacer esto, por ejemplo, coovachilli que me funcionó de coña, incluso usando los atributos ChilliSpot-Bandwidth-Max-Up, ChilliSpot-Bandwidth-Max-Down en freeradius (tabla radreply) limita el ancho de banda a usar por usuario.
Lo malo de coovachilli es que esa limitación del ancho de banda se hace justamente por eso, por usuario y no por grupos de usuarios. Lo que yo quiero hacer es tener 2 clases de usuarios, los free, que esos en su conjunto solo tengan 1 mbps y los vip, que esos, en su conjunto tengan 4 mpbs. El Coovachilli, al ser por usuario, como se me junten 10 free's, ya se me comen los 10x1=10mbps, cuando yo querría que el conjunto de los 10 tuvieran 1 mbps (usease, 1 mbps/10 = 100 kbps por usuario).
Además, me he encontrado que con coovachilli, sin poner limites de transferencia, por algún motivo la interficie tun que utiliza no puede enviar a mas de 1,5 Mbps así que no me sirve ya que la idea es ofrecer 4 Mbps a los vip.
Además, me he encontrado que con coovachilli, sin poner limites de transferencia, por algún motivo la interficie tun que utiliza no puede enviar a mas de 1,5 Mbps así que no me sirve ya que la idea es ofrecer 4 Mbps a los vip.
Así pues me lo he montado yo :)
GATEWAY LINUX
1. Instalar distribución (yo he usado ubuntu server 12.04 LTS)
2. En mi caso uso este server tb para openvpn y squid3 por lo que el script del firewall se complica un poquito.
3. Activar el forwarding en /proc/sys/net/ipv4/ip_forward o /etc/sysctl.conf
4. Interficies: eth0: acceso a Internet (ip pública)
eth1: red de management (ip 10.0.0.1/24). Red mía con servidores, etc
eth2: red de clientes (172.16.0.33/30). Red de conexión gateway-portal.
5. /etc/networking/interfaces:
1. Instalar distribución (yo he usado ubuntu server 12.04 LTS)
2. En mi caso uso este server tb para openvpn y squid3 por lo que el script del firewall se complica un poquito.
3. Activar el forwarding en /proc/sys/net/ipv4/ip_forward o /etc/sysctl.conf
4. Interficies: eth0: acceso a Internet (ip pública)
eth1: red de management (ip 10.0.0.1/24). Red mía con servidores, etc
eth2: red de clientes (172.16.0.33/30). Red de conexión gateway-portal.
5. /etc/networking/interfaces:
# The loopback network interface auto lo iface lo inet loopback # The primary network interface auto eth0 iface eth0 inet static address x.x.x.x netmask 255.255.255.252 gateway x.x.x.x # dns-* options are implemented by the resolvconf package, if installed dns-nameservers 8.8.8.8 auto eth1 iface eth1 inet static address 10.0.0.1 netmask 255.255.255.0 network 10.0.0.0 broadcast 10.0.0.255 auto eth2 iface eth2 inet static address 172.16.0.33 netmask 255.255.255.252 network 172.16.0.32 broadcast 172.16.0.35 post-up route add -net 172.16.0.0/27 gw 172.16.0.34 post-up route add -net 192.168.2.0/24 gw 172.16.0.34
en la eth2 incluimos 2 rutas estáticas: la de la red de interconexión gateway-portal y la de la red de clientes 192.168.2.x que gestiona el portal cautivo.
6. FIREWALL:
#!/bin/bash ######################################################## # FIREWALL ######################################################## # # CONFIGURACIO VARIABLES # INET_IFACE="eth0" INET_IP="x.x.x.x" HOTEL_IFACE="eth1" HOTEL_IP="10.0.0.1" HOTEL_IP_RANGE="10.0.0.0/24" LO_IFACE="lo" LO_IP="127.0.0.1" VPN_IFACE="tun+" CLIENT_IFACE="eth2" CLIENT_IP="172.16.0.33" CLIENT_RANGE="192.168.2.0/24" IPTABLES="/sbin/iptables" ####################################################### # FILTER ####################################################### # Politiques $IPTABLES -P INPUT DROP $IPTABLES -P FORWARD DROP $IPTABLES -P OUTPUT ACCEPT $IPTABLES -F $IPTABLES -t nat -F $IPTABLES -t mangle -F ############################################################################# # Input Chains ############################################################################# $IPTABLES -N bad_tcp_packets $IPTABLES -N icmp_packets # bad_tcp_paquets $IPTABLES -A bad_tcp_packets -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j DROP $IPTABLES -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP $IPTABLES -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP $IPTABLES -A bad_tcp_packets -p tcp --tcp-flags SYN,RST SYN,RST -j DROP $IPTABLES -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN,PSH SYN,FIN,PSH -j DROP $IPTABLES -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN,RST SYN,FIN,RST -j DROP $IPTABLES -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN,RST,PSH SYN,FIN,RST,PSH -j DROP $IPTABLES -A bad_tcp_packets -p tcp --tcp-flags ALL ALL -j DROP $IPTABLES -A bad_tcp_packets -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP $IPTABLES -A bad_tcp_packets -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP # icmp_paquets $IPTABLES -A icmp_packets -p icmp -i $CLIENT_IFACE -d 10.0.0.1 -j DROP $IPTABLES -A icmp_packets -p icmp -i $CLIENT_IFACE -d 172.16.0.1 -j DROP $IPTABLES -A icmp_packets -p icmp --icmp-type 8 -j ACCEPT $IPTABLES -A icmp_packets -p icmp --icmp-type 11 -j ACCEPT $IPTABLES -A icmp_packets -p icmp --icmp-type 0 -j ACCEPT $IPTABLES -A icmp_packets -p icmp --icmp-type 3 -j ACCEPT ############################################################################ # INPUT ############################################################################ $IPTABLES -A INPUT -p tcp -j bad_tcp_packets $IPTABLES -A INPUT -p icmp -j icmp_packets $IPTABLES -A INPUT -p ALL -m state --state ESTABLISHED,RELATED -j ACCEPT # desde red mgmnt acceder a ssh, squid y monit $IPTABLES -A INPUT -i $HOTEL_IFACE -s $HOTEL_IP_RANGE -p tcp --dport 22 -j ACCEPT $IPTABLES -A INPUT -i $HOTEL_IFACE -s $HOTEL_IP_RANGE -p tcp --dport 2812 -j ACCEPT $IPTABLES -A INPUT -i $HOTEL_IFACE -s $HOTEL_IP_RANGE -p tcp --dport 3128 -j ACCEPT # desde la vpn podem accedir al ssh $IPTABLES -A INPUT -i $VPN_IFACE -p tcp --dport 22 -j ACCEPT # desde internet: server openvpn $IPTABLES -A INPUT -i $INET_IFACE -p udp --dport xxxx -j ACCEPT # desde el localhost ok $IPTABLES -A INPUT -i $LO_IFACE -s $LO_IP -p ALL -j ACCEPT ############################################################################# # Forward Chains ############################################################################# $IPTABLES -N trafic_mgmnt $IPTABLES -A trafic_mgmnt -p tcp --dport 25 ! -s xxx -j LOG --log-prefix 'SPAM: ' --log-level 4 #al puerto 25 solo sale nuestro servidor de mail: xxxxx $IPTABLES -A trafic_mgmnt -p tcp --dport 25 ! -s xxxxx -j DROP # dejar pasar la red de management $IPTABLES -A trafic_mgmnt -o $INET_IFACE -j ACCEPT #vpn $IPTABLES -A trafic_mgmnt -o $VPN_IFACE -j ACCEPT # red gateway-cautivo (/24 para integrar 2 subredes) $IPTABLES -A trafic_mgmnt -d 172.16.0.0/24 -j ACCEPT $IPTABLES -N trafic_client # no conexions smtp (spam) $IPTABLES -A trafic_client -p tcp --dport 25 -j DROP # clients reals SI internet $IPTABLES -A trafic_client -s $CLIENT_RANGE -o $INET_IFACE -j ACCEPT # portal cautivo SI internet almenos por ahora $IPTABLES -A trafic_client -s 172.16.0.34 -o $INET_IFACE -j ACCEPT ############################################################################# # FORWARD ############################################################################# $IPTABLES -A FORWARD -p tcp -j bad_tcp_packets $IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # desde la vpn podemos acceder a la red de mgmnt y viceversa $IPTABLES -A FORWARD -i $VPN_IFACE -o $HOTEL_IFACE -j ACCEPT $IPTABLES -A FORWARD -i $VPN_IFACE -o $VPN_IFACE -j ACCEPT # trafic que viene de mgmnt $IPTABLES -A FORWARD -i $HOTEL_IFACE -s 10.0.0.0/24 -j trafic_mgmnt # trafic que ve dels clients $IPTABLES -A FORWARD -i $CLIENT_IFACE -j trafic_client # trafic de internet a nuestros servidores internos -> pasa lo dirigit a https, imaps, smtps $IPTABLES -A FORWARD -i $INET_IFACE -p tcp -d xxx --dport 443 -j ACCEPT $IPTABLES -A FORWARD -i $INET_IFACE -p tcp -d xxx --dport 993 -j ACCEPT $IPTABLES -A FORWARD -i $INET_IFACE -p tcp -d xxx --dport 587 -j ACCEPT ####################################################### # NAT ######################################################## $IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source $INET_IP $IPTABLES -t nat -A PREROUTING -p tcp -d $INET_IP --dport 443 -j DNAT --to-destination xxx:443 $IPTABLES -t nat -A PREROUTING -p tcp -d $INET_IP --dport 993 -j DNAT --to-destination xxx:993 $IPTABLES -t nat -A PREROUTING -p tcp -d $INET_IP --dport 587 -j DNAT --to-destination xxx:587 # politicas de trafico /root/htb.sh
7. HTB
Finalmente solo nos queda crear el control de tráfico con HTB. Lo que hago es simplemente dividir mis 10 Mbps para que la red de mgmnt tenga 5 Mbps garantizados y la red de clientes tenga los otros 5 Mbps, pero si uno de los 2 no los esta usando el otro los pueda aprovechar. Ademas, dentro de la clase de la red de management la divido para el trafico de la VPN y el resto de trafico.
# Limpiar qdiscs tc qdisc del dev eth0 root tc qdisc del dev eth1 root tc qdisc del dev eth2 root # instalar htb tc qdisc add dev eth0 root handle 1: htb default 30 # clases htb tc class add dev eth0 parent 1: classid 1:1 htb rate 10Mbit ceil 10Mbit tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5Mbit ceil 9Mbit tc class add dev eth0 parent 1:1 classid 1:20 htb rate 4500Kbit ceil 9Mbit tc class add dev eth0 parent 1:1 classid 1:30 htb rate 500Kbit ceil 3Mbit tc class add dev eth0 parent 1:10 classid 1:12 htb rate 3Mbit ceil 8Mbit tc class add dev eth0 parent 1:10 classid 1:13 htb rate 2Mbit ceil 8Mbit # Disciplinas de cola tc qdisc add dev eth0 parent 1:12 handle 12: sfq perturb 10 tc qdisc add dev eth0 parent 1:13 handle 13: sfq perturb 10 tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10 # marcamos los paquetes # eth0 -> internet # eth1 -> mgmnt # eth2 -> clients iptables -t mangle -F # trafico red hotel iptables -t mangle -A FORWARD -i eth1 -p ALL -s 10.0.0.0/24 -j MARK --set-mark 13 # squid iptables -t mangle -A OUTPUT -p tcp --dport 80 -j MARK --set-mark 13 iptables -t mangle -A OUTPUT -p tcp --dport 443 -j MARK --set-mark 13 # trafico VPN sale por el puerto xxx udp iptables -t mangle -A OUTPUT -p udp --sport xxx -j MARK --set-mark 12 # trafico clientes iptables -t mangle -A FORWARD -i eth2 -p ALL -s 192.168.2.0/24 -j MARK --set-mark 20 # classificacion de los paquetes marcados tc filter add dev eth0 protocol ip parent 1: handle 12 fw classid 1:12 tc filter add dev eth0 protocol ip parent 1: handle 13 fw classid 1:13 tc filter add dev eth0 protocol ip parent 1: handle 20 fw classid 1:20 # inspeccionar les regles #tc -s qdisc ls dev eth0 #tc -s class ls dev eth0 # LIMITAR DOWNLOAD RED CLIENTES
# mala idea porque entonces jodes la posible clasificacion que hace el
# portal cautivo #tc qdisc add dev eth2 root handle 1: htb default 1 #tc class add dev eth2 parent 1: classid 1:1 htb rate 4Mbit ceil 5Mbit
PORTAL CAUTIVO
1. Instalar distro (yo ubuntu 12.04 lts)
2. Interficies
# The loopback network interface auto lo iface lo inet loopback # The primary network interface auto eth0 iface eth0 inet static address 172.16.0.34 netmask 255.255.255.252 network 172.16.0.32 broadcast 172.16.0.35 gateway 172.16.0.33 dns-nameservers 8.8.8.8 auto eth1 iface eth1 inet static address 192.168.2.1 netmask 255.255.255.0 network 192.168.2.0 broadcast 192.168.2.255 auto eth1:0 iface eth1:0 inet static address 172.16.0.1 netmask 255.255.255.224 network 172.16.0.0 broadcast 172.16.0.31
la eth1:0 es una red /27 (32 hosts) que uso como red para administrar los puntos de acceso u otros dispositivos transparentes a los clientes.
3. Servidor DHCP:
apt-get install isc-dhcp-server joe /etc/dhcp/dhcpd.conf ddns-update-style none; option domain-name "client.local"; option domain-name-servers 8.8.8.8, 8.8.4.4; default-lease-time 600; max-lease-time 7200; # If this DHCP server is the official DHCP server for the local # network, the authoritative directive should be uncommented. authoritative; # Use this to send dhcp log messages to a different log file (you also # have to hack syslog.conf to complete the redirection). log-facility local7; subnet 192.168.2.0 netmask 255.255.255.0 { range 192.168.2.30 192.168.2.250; option routers 192.168.2.1; option subnet-mask 255.255.255.0; option broadcast-address 192.168.2.255; } joe /etc/default/isc-dhcp-server interfaces="eth1"
3. Servidor Web: Apache
apt-get install apache2 php5 php-pear openssl genrsa -out http.key openssl req -new -key http.key -out http.csr openssl x509 -req -days 3650 -in http.csr -signkey http.key -out http.crt chmod 400 *.key mkdir /etc/apache2/ssl cp http.* /etc/apache2/ssl/ ln -s /etc/apache2/mods-available/ssl.conf /etc/apache2/mods-enabled/ssl.conf ln -s /etc/apache2/mods-available/ssl.load /etc/apache2/mods-enabled/ssl.load cd sites-enabled/ joe 000-default /etc/init.d/apache2 restart
4. Servidor Base de datos: Postgresql
apt-get install postgresql /etc/init.d/postgresql stop mkdir /home/postgres chown postgres.postgres /home/postgres/ joe /etc/passwd cd /etc/init.d mv postgresql postgresql.orig joe postgresql -------------------- #!/bin/sh set -e RUNDIR="/var/run/postgresql" case "$1" in start) if [ ! -e $RUNDIR ] then mkdir $RUNDIR chown postgres.postgres $RUNDIR fi su - -c 'pg_ctl start -D /home/postgres/data' postgres ;; stop) su - -c 'pg_ctl stop -m f -D /home/postgres/data' postgres ;; restart) su - -c 'pg_ctl stop -m f -D /home/postgres/data' postgres su - -c 'pg_ctl start -D /home/postgres/data' postgres ;; *) echo "Usage: $0 {start|stop|restart|reload|force-reload|status} [version ..]" exit 1 ;; esac exit 0 ---------------------- cp .bashrc /home/postgres/ cp .profile /home/postgres/ chown postgres.postgres /home/postgres/.bash /home/postgres/.profile su - postgres añadir path al .profile de postgres PATH="/usr/lib/postgresql/9.1/bin/:$PATH" pg_ctl -D /home/postgres/data initdb exit /etc/init.d/postgresql start su - postgres createuser -D -E -R -S -W radiuser createdb -O radiususer radiusdb psql radiusdb cd data/ joe pg_hba.conf # TYPE DATABASE USER ADDRESS METHOD # "local" is for Unix domain socket connections only local all all trust host all all 127.0.0.1/32 trust host all all ::1/128 trust host all all 0.0.0.0/0 reject joe postgresql.conf -> listen = 'localhost'
La manera por defecto de iniciar postgresql que tiene el instalador de ubuntu/debian no me gusta para tener bases de datos pequeñitas como las mías por lo que hago un script que inicio postgres tal y como pone el propio manual de postgresql.org.
Después pongo la base de datos en /home/postgres porque en la partición /home es donde tengo mucha mas espacio.
Finalmente creo el usuario y la base de datos para freeradius y configuro postgres para que solo acepte conexiones de localhost ya que el servidor freeradius está en la misma máquina.
5. Servidor Auth: Freeradius
apt-get install freeradius freeradius-postgresql cd /etc/freeradius/ joe clients.conf client 127.0.0.1 { secret = test } joe sql.conf canviar a postgresql canviar readclients = yes joe radiusd.conf descomentar INCLUDE sql.conf descomentar INCLUDE sql/postgresl/counter.conf cd freeradius/sites-available/ joe default descomentar sql (linia 159) i comentar files (152) descomentar sql en Accounting (388) cp /etc/freeradius/sql/postgresl/schema.sql /.../nas.sql /home/postgres chmod 777 /home/postgres/*.sql su - postgres psql -U radiususer radiusdb \i schema.sql \i nas.sql \q exit
6. Dialup Admin:
apt-get install php5-pgsql apt-get install freeradius-dialupadmin joe /etc/freeradius-dialupadmin/admin.conf -> posar la info de postgresql -> comentar sql_debug para evitar que salgan las consultas -> la taula de groups es radusergroup i no usergroup ln -s /etc/freeradius-dialupadmin/apache2.conf /etc/apache2/sites-enables/001-radius (editar el alias por ejemplo) ejecutar /usr/share/freeradius-dialupadmin/sql/postgresql/*.sql como postgres para añadir tablas en la base de datos /etc/init.d/apache2 restart Creamos un par de usuarios testeamos login de usuarios sql en freeradius -> /etc/init.d/freeradius stop -> freeradius -X -> radtest user pass localhost 1812 <secret de clients.conf> me falla porque dialupadmin crea el usuario en la tabla radcheck con el Attribute User-Password := md5, si creamos un usuario a mano: insert into radcheck(username, attribute, value) values ('user','Password','pass'); entonces funciona bien el radtest Para que funcione bien en /etc/freeradius-dialupadmin/admin.conf cambiar: -> general_encryption_method: clear -> sql_password_attribute: Cleartext-Password
7. Firewall
#!/bin/bash ipt=/sbin/iptables clientes=192.168.2.0/24 mgmt=172.16.0.0/27 # limpieza $ipt -F $ipt -t nat -F # politicas $ipt -P INPUT DROP $ipt -P FORWARD DROP $ipt -P OUTPUT ACCEPT # paquetes kaka $ipt -N bad_tcp_packets $ipt -A bad_tcp_packets -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j DROP $ipt -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP $ipt -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP $ipt -A bad_tcp_packets -p tcp --tcp-flags SYN,RST SYN,RST -j DROP $ipt -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN,PSH SYN,FIN,PSH -j DROP $ipt -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN,RST SYN,FIN,RST -j DROP $ipt -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN,RST,PSH SYN,FIN,RST,PSH -j DROP $ipt -A bad_tcp_packets -p tcp --tcp-flags ALL ALL -j DROP $ipt -A bad_tcp_packets -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP $ipt -A bad_tcp_packets -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP # icmp_paquets $ipt -N icmp_packets $ipt -A icmp_packets -p icmp -i eth1 -d 172.16.0.0/24 -j DROP $ipt -A icmp_packets -p icmp -i eth1 -d 172.16.0.1 -j DROP $ipt -A icmp_packets -p icmp --icmp-type 8 -j ACCEPT $ipt -A icmp_packets -p icmp --icmp-type 11 -j ACCEPT $ipt -A icmp_packets -p icmp --icmp-type 0 -j ACCEPT $ipt -A icmp_packets -p icmp --icmp-type 3 -j ACCEPT ###################### # INPUT ###################### $ipt -A INPUT -p tcp -j bad_tcp_packets $ipt -A INPUT -p icmp -j icmp_packets $ipt -A INPUT -p ALL -m state --state ESTABLISHED,RELATED -j ACCEPT # por la eth0 dejamos entrar a la web i ssh $ipt -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT $ipt -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT # por la eth1 (clientes) dejamos web + dhcp $ipt -A INPUT -i eth1 -s $clientes -p tcp --dport 80 -j ACCEPT $ipt -A INPUT -i eth1 -p udp --dport 67:68 -j ACCEPT # desde el localhost ok $ipt -A INPUT -i lo -s 127.0.0.1 -p ALL -j ACCEPT ############################################################################# $ipt -N auth ############################################################################ # FORWARD ############################################################################ $ipt -A FORWARD -p tcp -j bad_tcp_packets $ipt -A FORWARD -p ALL -m state --state ESTABLISHED,RELATED -j ACCEPT # Desde red empresa dejar entrar a los puntos de acceso que estan en la red cliente $ipt -A FORWARD -i eth0 -p icmp -s 10.0.0.0/24 -d $mgmt -j ACCEPT $ipt -A FORWARD -i eth0 -p tcp -s 10.0.0.0/24 -d $mgmt --dport 80 -j ACCEPT # peticiones dns si $ipt -A FORWARD -i eth1 -p udp --dport 53 -j ACCEPT # necesario para evitar que los autentificados puedan acceder a los APs $ipt -A FORWARD -i eth1 -p ALL -d 172.16.0.0/24 -j DROP # usuarios authentificados si $ipt -A FORWARD -i eth1 -s $clientes -j auth ############################################################################## $ipt -t nat -N natauth ################### # NAT ################### # las peticiones web las redirigimos a la web local $ipt -t nat -A PREROUTING -i eth1 -s $clientes -p tcp --dport 80 -j natauth $ipt -t nat -A PREROUTING -i eth1 -s $clientes -p tcp --dport 80 -j REDIRECT --to-ports 80 # aplicamos politicas de control de trafico y reiniciamos nuestros ficheros de control /root/htb.sh /usr/local/bin/reiniciar.sh
8. Scripts para dejar pasar un cliente
La idea es guardar en /var/spool/wifi/taula una lista de las MAC autorizadas a passar. Este ficherito, chmod 600 para que solo pueda ser leido y modificado para root.
Los scripts solo ejecutables por root (chmod 700)
hostadd.sh
#!/bin/bash ########################### TAULA="/var/spool/wifi/taula" MACr="$3" TUSER="$1" IP="$2" ipt=/sbin/iptables function add_host() { echo "$MAC $IP" >> $TAULA $ipt -A auth -p ALL -m mac --mac-source $MAC -j ACCEPT $ipt -t nat -A natauth -m mac --mac-source $MAC -j ACCEPT case "$TUSER" in "free") $ipt -t mangle -A FORWARD -i eth1 -p ALL -m mac --mac-source $MAC -j MARK --set-mark 40 $ipt -t mangle -A FORWARD -o eth1 -p ALL -d $IP -j MARK --set-mark 41 ;; "vip") $ipt -t mangle -A FORWARD -i eth1 -p ALL -m mac --mac-source $MAC -j MARK --set-mark 45 $ipt -t mangle -A FORWARD -o eth1 -p ALL -d $IP -j MARK --set-mark 46 ;; esac } # 0. Pasamos la MACrecibida a mayusculas MAC=$(echo $MACr | tr '[:lower:]' '[:upper:]') # 1. Buscamos la MAC del pc en el archivo MAC_ARXIU=$(cat $TAULA | grep $MAC | awk '{print $1}') # si la mac NO existe if [ -z "$MAC_ARXIU" ]; then add_host # si SI existe else /usr/local/bin/hostdel.sh $MAC add_host fi
hostdel.sh
#!/bin/bash ########################### TAULA="/var/spool/wifi/taula" MACr="$1" ipt=/sbin/iptables # 0. Pasamos la mac a mayusculas MAC=$(echo $MACr | tr '[:lower:]' '[:upper:]') # 2. Eliminar pareja mac-ip de taula sed -i "/$MAC/d" $TAULA # 2. Eliminar controles al firewall $ipt -D auth -p ALL -m mac --mac-source $MAC -j ACCEPT $ipt -t nat -D natauth -m mac --mac-source $MAC -j ACCEPT num=$(iptables -t mangle -L FORWARD --line-numbers | grep $MAC | awk '{print $1}') $ipt -t mangle -D FORWARD $num $ipt -t mangle -D FORWARD $num # en la mangle se añaden a pares, por tanto las eliminamos a pares :)
hosttest.sh
#!/bin/bash ########################### TAULA="/var/spool/wifi/taula" VIUS="/tmp/alive" BORRAR="/tmp/dead" TAULAs="/tmp/taula" cat $TAULA | awk '{print $1}' | sort > $TAULAs nmap -sP -T5 192.168.2.0/24 | grep MAC | awk '{print $3}' | tr '[:lower:]' '[:upper:]' | sort > $VIUS comm -2 -3 $TAULAs $VIUS > $BORRAR while read mac ip do /usr/local/bin/hostdel.sh $mac done < $BORRAR
el hosttest.sh lo ponemos en el cron para que se ejecute cada 1,2 o 3 minutos para que vaya vea los dispositivos que estan activos en la red de clientes, y aquellos que no lo estén los quito.
9. SUDO
Problema: estos scripts los ejecutara un php desde el portal cautivo, es decir, como el usuario www-data (o el que sea). Este usuario no puede modificar el firewall, ni ejecutar estos scripts. Primero pense en chmod +s pero resulta que ubuntu tiene implementada una proteccion en el kernel que no aplica los setgid o setuid en scripts. Así que lo que tengo que hacer es que www-data pueda hacer sudo sin password para estos scripts
visudo
Cmnd_Alias HOSTADD = /usr/local/bin/hostadd.sh
Cmnd_Alias HOSTDEL = /usr/local/bin/hostdel.sh
www-data ALL = (root) NOPASSWD: HOSTADD
www-data ALL = (root) NOPASSWD: HOSTDEL
10. Portal Cautivo
(a) Se trata de hacer una web con un formulario que pida user y password y su submit ejecute un php.
(b) Como no se hacer webs, he instalado dokuwiki
(c) Plugins de dokuwiki: formular, wrap, note, columns, tabinclue.
(d) Poner una template que te guste.
(e) Crear la página:
<WRAP column 45%> <FORM "http://192.168.2.1/data/formplugin/test.php"> Textbox User "User: " 80; Passbox Pass "Password:" 80; Submit "Enviar" 90; </FORM> </WRAP> <WRAP column 45%> <WRAP help round left> Introduca un usuario y contraseña para acceder a Internet. </WRAP> </WRAP>
(f) Crear otras páginas de OK, de NO OK, etc.
11. PHP para permitir acceder un cliente
Así pues se ejecutará el script /data/formplugin/test.php cuando un usuario ponga su user/password en la web. Este php lo único que tiene que hacer es autentificar contra radius y llamar (o no) a los scripts que hemos creado:
<?php // variables usuario (solo 8 caracteres iniciales) $user = substr(trim($_POST['User']), 0, 8); $pass = substr($_POST['Pass'], 0, 8); if (strlen($user) <= 2) { exit("ERROR: Usuario no valido"); } if (strlen($pass) <= 2) { exit("ERROR: Password no entrado"); } //Auth per RADIUS $rad = radius_auth_open() or exit ("error radius"); if (! radius_add_server($rad, 'localhost', '1812', 'secret', 10, 3)) { exit("ERROR: radius_add_server"); } if (! radius_create_request($rad, RADIUS_ACCESS_REQUEST)) { exit("ERROR: radius_create_request"); } if (! radius_put_attr($rad, RADIUS_USER_NAME, $user)) { exit("ERROR: radius_put_attr USERNAME"); } if (! radius_put_attr($rad, RADIUS_USER_PASSWORD, $pass)) { exit("ERROR: radius_put_attr PASS"); } function allow($ip, $usuari) { exec("/bin/ping -c 1 $ip"); $mac=shell_exec("/usr/sbin/arp -n | grep $ip | awk '{print \$3}'"); if ( strlen($mac) > 0) { //ojo! ultimo parametro la mac, por algun motivo no recibe //mas parametros despues de la mac system(sprintf("%s %s %s %s", 'sudo /usr/local/bin/hostadd.sh', escapeshellcmd($usuari), $ip, $mac)); return 0; } else { return 3; } } switch (radius_send_request($rad)) { case RADIUS_ACCESS_ACCEPT: $res=allow($_SERVER['REMOTE_ADDR'], $user); switch ($res) { case 0: header('Location: http://192.168.2.1/doku.php/authok'); break; case 3: header('Location: http://192.168.2.1/doku.php/nomac'); break; } break; case RADIUS_ACCESS_REJECT: header('Location: http://192.168.2.1/doku.php/authnook'); break; case RADIUS_ACCESS_CHALLENGE: echo "CHALLENGE"; break; case 0: echo "error ". radius_strerror($rad); break; } radius_close($rad); ?>
12. HTB
<?php # Netejar qdiscs tc qdisc del dev eth0 root tc qdisc del dev eth1 root # instalem htb tc qdisc add dev eth0 root handle 1: htb default 30 # clases htb tc class add dev eth0 parent 1: classid 1:1 htb rate 4500Kbit ceil 7Mbit tc class add dev eth0 parent 1:1 classid 1:10 htb rate 500Kbit ceil 1Mbit tc class add dev eth0 parent 1:1 classid 1:20 htb rate 4Mbit ceil 5Mbit tc class add dev eth0 parent 1:1 classid 1:30 htb rate 250Kbit ceil 3Mbit # posem les disciplines de cua tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10 tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10 # marcamos los paquetes via iptables # eth0 -> inet # eth1 -> clients iptables -t mangle -F #los paquetes se marcan en los scripts cuando se autentifican # 40 = free # 45 = vip # classificacio de paquets del hotel tc filter add dev eth0 protocol ip parent 1: handle 40 fw classid 1:10 tc filter add dev eth0 protocol ip parent 1: handle 45 fw classid 1:20 #### CONTROL DE LO QUE RECIBEN LOS CLIENTES #### tc qdisc add dev eth1 root handle 2: htb default 30 tc class add dev eth1 parent 2: classid 2:1 htb rate 5Mbit ceil 5Mbit tc class add dev eth1 parent 2:1 classid 2:10 htb rate 500Kbit ceil 2Mbit tc class add dev eth1 parent 2:1 classid 2:20 htb rate 3750Kbit ceil 4250Kbit tc class add dev eth1 parent 2:1 classid 2:30 htb rate 250Kbit ceil 1Mbit tc qdisc add dev eth1 parent 2:10 handle 10: sfq perturb 10 tc qdisc add dev eth1 parent 2:20 handle 20: sfq perturb 10 tc filter add dev eth1 protocol ip parent 2: handle 41 fw classid 2:10 tc filter add dev eth1 protocol ip parent 2: handle 46 fw classid 2:20 ##################### INGRESS ######################### #modprobe ifb numifbs=1 #ip link set dev ifb0 up # neteja #tc qdisc del dev eth0 handle ffff: ingress #tc qdisc del dev ifb0 root # posem politca de ingress i redirigim trafic de eth0 -> ifb0 #tc qdisc add dev eth0 handle ffff: ingress #tc filter add dev eth0 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0 #tc qdisc add dev ifb0 root handle 2: htb default 30 #tc class add dev ifb0 parent 2: classid 2:1 htb rate 100Mbit #tc class add dev ifb0 parent 2:1 classid 2:10 htb rate 1Mbit ceil 1Mbit #tc class add dev ifb0 parent 2:1 classid 2:20 htb rate 4Mbit ceil 5Mbit #tc class add dev ifb0 parent 2:1 classid 2:30 htb rate 250Kbit ceil 1Mbit #tc filter add dev ifb0 protocol ip parent 2: prio 1 u32 match ip dst 192.168.2.31/32 flowid 2:20 # inspeccionar las reglas #tc -s qdisc ls dev eth0 #tc -s class ls dev eth0
Lo que se hace es limitar el ancho de banda que pueden transmitir los clientes:
- Free: hasta 1 Mbps de subida y 2 de bajada
- Vip: 4-5 Mbps de bajada y hasta 5 Mbps de subida.
Lo que me he encontrado es que si permito un ceil de bajada mas alto para los free, que esa era la idea para permitir que si no hay vips pues los free tengan mas ancho de banda, veo que los free se comen ancho de banda de los vips, es decir, la clase 2:20 no llega a su "garantizado" de 4Mbps porque la clase 2:10 empieza a pillar ancho de banda. Esto me ha jodido. Después de mirármelo un poco veo que esto ha sido debido a:
- el vip era un portátil viejo con windows xp. He visto que incluso con toda la Internet para el solito no pasaba de 3 Mbps de bajada. Evidentemente esto hacia que los demás free's pillen en ancho que este portátil no usaba. Solución: arrancar el portátil con una distro linux para hacer las pruebas :) (malditas ventanas tcp de windows xp!)
- el Gateway limitaba en ancho de banda de 5Mbps que enviaba por eth2 (interfaz de clientes). Esto hacia que realmente el tráfico llegase al portal cautivo ya "pseudo-clasificado" haciendo que el cautivo no pudiese reclasificar correctamente sus flujos de datos entrantes entre vip y free, por lo que a los vip no les llegaba un ancho de banda a 4 o 5 Mbps haciendo que los free's lo aprovechase, cosa que parecía como si los free's se comiesen el ancho de los vips. Solución: dejar que al portal cautivo le lleguen los flujos de Internet tal cual = hacer que el gateway no limitase el ancho de banda dirigido a la interfaz de los clientes (eth2)
Vemos que en el portal cautivo, via iptables, las mac's no autenficiadas les hace un -j REDIRECT a sus paquetes, de manera que van a parar al mismo servidor y asi el usuario va a parar al portal cautivo. Lo malo es que si el cliente intenta ir a www.google.com/search?q=holakease&noseque=nosecuantos ocurre que la redireccion hace que el cliente vaya a http://192.168.2.1/search?q=holakease&noseque=nosecuantos y hace que falle porque esa web no existe en nuestro servidor.
Vía htaccess podemos redirigir cualquier petición web a la home de nuestro server:
RewriteCond %{REQUEST_URI} !^(.*)/doku.php
RewriteCond %{REQUEST_URI} !^(.*)/lib/exe/indexer.php
RewriteCond %{REQUEST_URI} !^(.*)/lib/exe/css.php
RewriteCond %{REQUEST_URI} !^(.*)/lib/exe/js.php
RewriteCond %{REQUEST_URI} !^(.*)/lib/plugins/
RewriteCond %{REQUEST_URI} !^(.*)/lib/tpl/prsnl10
RewriteRule ^/?(.*) http://172.16.0.34/doku.php
Lo que hace es que las peticiones vayan a http://cautivo/doku.php (he usado dokuwiki) excepto las peticiones que ya sean de dokuwiki (para evitar loops infinitos y permitir la aplicación de los estilos, plantillas, etc).
De igual forma podemos crear webs para la versión móvil y redirigir segun el user_agent que visita el servidor:
RewriteCond %{HTTP_USER_AGENT} "android | blackberry | ipad | iphone | ipod | iemobile | opera mobile | palmos | webos | googlebot-mobile" [NC]
RewriteCond %{REQUEST_URI} !^(.*)/m/
RewriteCond %{DOCUMENT_ROOT}/$1 !-f
RewriteRule ^/?doku.php/([a-z]+)/(.*)$ http://172.16.0.34/doku.php/$1/m/$2 [L,R=302]
asi si eres un mobil iras a la web con /m/ por enmedio. Ojo, la rewrite rule hace un doku/$1/m/$2 porque el $1 es la marca del idioma, ya que en mi caso el dokuwiki tiene el plugin de translation para crear páginas para cada idioma. Una url en mi dokuwiki seria:
http://server/doku.php/idioma/pagina
http://server/doku.php/idioma/m/pagina (v. móvil).
La diversíon está en que una modificación de una pagina implica hacerla en varios idiomas y en las versiones móviles de cada idioma, pero en principio, el portal cautivo, pocas modificaciones hay que hacerle.
Jarl!
Comentarios
Si ubuntu te da problemas, usa otra distro con la que te sientas mas comod@.
Para este tema va bien saber un poquillo como van los temas de:
1.- IPTABLES (firewalls)
2.- HTML - montar servidores web (apache, ngingx, lighttp) e instalar programillas web (como dokuwiki, joomla o lo que sea)
3.- Algo de programación en php
FInalmente tengo que decir que el software que traen algunos frabricantes, como UNIFI de UBNT pos ya llevan el portal cautivo integrao con varias posibilidades chulas.
entonces la idea mas bien es si me explicas un poco la configuracion de las tarjetas como te decia ya que tienes repetida la info y pos no le entiendo mucho :(
GATEWAY
1.- la red que se connecta a internet con la eth0
2.- una red invisible para los usuarios de la wifi, la red 10.0.0.x via eth1
3.- una mini-red que connecta la eth2 del gateway con la eth0 del portal cautivo.
Esto se ve claro en el archivo de /etc/networking/interfaces del gateway que pastee en el post.
Ademas, en la eth2 del gateway pongo estas 2 lineas:
post-up route add -net 172.16.0.0/27 gw 172.16.0.34
post-up route add -net 192.168.2.0/24 gw 172.16.0.34
que sirve para que cree las rutas (los paquetes dirigidos a la red 172.16.0.0/27 (puntos de acceso) y los dirigidos a 192.168.2.0/24 (clientes wifi) se les pasa al portal cautivo (172.16.0.34 y este sabrá que hacer con ellos)
PORTAL CAUTIVO
Este tiene 2 tarjetas de red fisicas:
- eth0: enlace entre el portal cautivo y el gateway
- eth1: red de clientes
- eth1:0: alias para la red 172.16.0.0/27 de las antenas wifi.
Tb he posteado un copy&paste del /etc/network/interfaces del portal cautivo donde se ve todo esto.
El /etc/network/interfaces es el ficherito que usa ubuntu (y supongo que las distro basadas en debian) para configurar las interficies de red cuando arrancan. (A veces me he encontrado que el network-manager interfiere y jode un poco la marrana, sobretodo si arrancas en modo gráfico)
Otra nota "importante": La red de las antenas wifi es /27, porque tengo unas 15 antenas, con 5 bits puedo direccionar 32 direcciones -2 (broadcast y red) ergo un total de 30 direcciones, por ello hago una red /27, si tuviese mas pos pillaria una red mas extensa o a la inversa.
Pero si esto te lia puedes poner las antenas en el mismo rango de la red de clientes (192.168.2.x) y asi te ahorras un enrutamiento, crear el eth1:0 en el portal cautivo y solo tienes que asegurarte que tu dhcp no le assigne a un usuario wifi una ip que uses para una antena. Eso si, los wifi i las antenas estaran en la misma red fisica y logica con lo que se verán, no tiene porque pasar nada, pero a mi me gusta mas ponerlas en redes lógicas distintas.
En fin, no se si te he ayudado o no, pero el tema de las interficies es un tema de direccionamiento IP de las diferentes redes que he utilizado
Disculpa que no te habia contestado antes.
En fin, como ves mi idea? Que me recomendarías? Se puede? Que distro Linux me recomiendas?. Tengo conocimiento sobre PHP,HTML,MySQL,CSS pero no mucho sobre Redes. Saludos y espero tu pronta respuesta, Muchas-Gracias¡¡ Beavies.
Con este metodo que has publicado se puede solucionar este error???