Tabla de Contenidos

Configurando una VPN sobre ANCEL

2ª edición.

Introducción

Desde este paso se asume que tanto la computadora cliente como el servidor tienen algún sistema POSIX como por ejemplo GNU/Linux u OpenBSD. Todo el procedimiento fue realizado y probado única y exclusivamente en sistemas Debian GNU/Linux tanto en el servidor como en el cliente.

Para poder conectarse al proxy de ANCEL es necesario disponer de una conexión a internet en el celular, para esto se puede sin la necesidad de ningún contrato establecer conexiones pagando por cada minuto, dado que pagar por minuto es extremadamente caro1), termina siendo mucho más conveniente contratar la tarifa plana WAP/GPRS, que al día de hoy, está costando $70 por mes.

Mi celular es un sony ericsson J300i, y es el único celular que tengo, por lo tanto la información de este documento estará inevitablemente basada en este celular, aúnque en la medida de lo posible trataré de hacer las aportaciones lo más genericamente posible.

Asumo también, que desde este momento usted puede navegar desde su celular a páginas como www.google.com.uy sin problemas.

Por cierto, también es necesario tener algún el cable USB que conecta el celular con la computadora cliente.

1. Configurar la conexión ppp para poder conectarse al proxy de ANCEL

1.1. Cuentas de datos (Celular)

En los celulares (por lo menos en los que yo conozco) hay una lista de posibles conexiones, en el sony ericsson J300i esta lista se encuentra en: [Menú] → [Ajustes] → [Conectividad] → [Comunic. de datos] → [Cuentas de datos].

En la instalación por defecto de ANCEL vienen las siguientes cuentas:

  1. gprsANCEL
  2. wapANCEL
  3. mmsANCEL
  4. csdANCEL

Si se dispone de tarifa plana de WAP/GPRS la conexión que se deberá usar será wapANCEL, si se decide pagar por minuto, es csdANCEL la que deberá ser usada.

Es de suma importancia tener conocimiento del orden en el que están las conexiones en esta lista, la primer conexión, o sea la de más arriba es la que tiene asignada el número 1, por lo tanto para este ejemplo wapANCEL es la número 2, y csdANCEL es la número 4. Aclaro esto porque los números de las conexiones no aparecen en la lista.

En caso de que no estén presentes esas conexiones deberán ser creadas. Los datos para wapANCEL son los siguientes:

La configuración necesaria para csdANCEL es la siguiente:

gprsANCEL y mmsANCEL no son necesarias para lograr el objetivo de este documento que es crear un túnel entre dos computadoras usando ssh y una conexión por ANCEL del lado del cliente.

1.2. El peer "ancel" (Cliente)

El siguiente paso es crear el archivo de texto "/etc/ppp/peers/ancel", el cual deberá contener las siguientes líneas, o lo que usted desee, pero tomando en cuenta las siguientes aclaraciones:

connect /etc/chatscripts/ancel
crtscts
modem
noccp
# nodetach
lock
#debug
defaultroute
/dev/ttyUSB0
noauth
# usepeerdns
novj
230400
#460800
#ipcp-accept-remote
#ipcp-accept-local
# noipdefault
# user f
#mtu 600
#mru 600
maxfail 0
noipdefault

La opción "connect /etc/chatscripts/ancel" indica que para conectarse a internet ha de ejecutarse "/etc/chatscripts/ancel", digamos que es imprescindible, aunque hay otras formas alternativas más o menos similares para conectarse voy a explicar solo ésta para no confundir.

La opción "crtscts" habilita el control de flujo por hardware, y aunque ni USB ni bluetooth ni irda tienen control de flujo, agregar de todas formas esta opción no hace ningún mal.

La opción "modem" habilita las líneas de control de modem del puerto serial, y nuevamente, ni USB ni bluetooth ni irda tienen estas líneas. Pero por sí acaso agrego la opción.

Imprescindible es la opción "noccp", la cual deshabilita la compresión de todo tipo.

Las opciones "nodetach" y "debug" son muy útiles para buscar errores, pero cuando todo anda bien no tiene sentido tenerlas habilitadas. El caracter numeral al principio de la línea indica que esa opción está comentada y por tanto es ignorada.

La opción "lock" se usa para que no puedan levantarse dos pppd por el mismo puerto serial simultáneamente, y por lo tanto es muy conveniente que esté presente.

La opción "defaultroute" hace que el pppd agregue una ruta por defecto al conectarse. Esto permite que todos los paquetes cuyo destino sea la internet salgan por el celular.

"/dev/ttyUSB0" es el puerto serial por el cual me conecto al celular, este puerto puede ser distinto en otra computadora, y de hecho, es muy probable de que sea distinto, así que cada cual deberá adaptar el puerto a su celular/computadora.

Es importante saber que el celular se comporta como un modem serial, así que una forma fácil de saber en que dispositivo está el celular es usando el programa minicom (del cual hay ya mucha documentación), y obviamente revisando los logs. El puerto debería ser por lo general "/dev/ttyUSBalgo" o de última "/dev/ttyalgo".

"noauth" es otra opción imprescindible. Ésta permite indicarle al pppd que NO deberá pedirle al servidor (o sea al señor ANCEL) que se autentifique.

"novj" permite deshabilitar un tipo de compresión en cuesitión, el tema es que en muchos howtos aparece mencionada esta opción, y de todas formas, aunque novj no esté presente los paquetes no terminan comprimiéndose.

"230400" es la velocidad en bits por segundo en la que deberá abrirse el puerto serial. Por ejemplo el cable de mi celular no soporta velocidades mayores a 230400. Siempre es conveniente usar la mayor velocidad posible.

"maxfail 0" le indica al pppd que en caso de perderse la conexión, deberá siempre intentar reconectarse infinitas veces si hiciera falta.

La opción "noipdefault" indica al pppd que no debe pedir una cierta dirección IP por omisión, en algunos sistemas esto es necesario.

Una vez creado este archivo, es conveniente ajustarle los permisos:

chmod 0640 /etc/ppp/peers/ancel
chown root:dip /etc/ppp/peers/ancel

1.3. El chatscript "ancel" (Cliente)

El siguiente paso es crear el archivo "/etc/chatscripts/ancel" el cual deberá necesariamente tener permisos de ejecución, y el siguiente contenido:

#!/bin/sh
/usr/sbin/chat -v "" ATZ OK AT+CGDATA=\"PPP\",2 CONNECT ""

La primer línea es "#!/bin/sh", y es imprescindible, porque le permite indicarle al sistema que este ejecutable se deberá interpretar usando /bin/sh.

En la segunda línea hay un número, que en este caso es un 2, en este ejemplo el 2 correspondía a wapANCEL. Deberá ser cambiado por el número de la conexión a usar, tal cual estaba aclarado en "1.1. Cuentas de datos"

Para darle permisos de ejecución hay que correr lo siguiente:

chmod +x /etc/chatscripts/ancel

1.4. Probando la conexión.

Para probar la conexión, o sea para conectarse, hay que correr lo siguiente desde un usuario que esté en el grupo dip.

pon ancel

Si todo funciona, debería aparecer asignada una dirección IP al celular y además ser posible conectarse con el proxy, para probar se puede ejecutar lo siguiente:

http_proxy=http://200.40.246.2:3128 w3m http://www.google.com.uy

En lugar de w3m se puede usar cualquier cliente de http de consola, como por ejemplo el lynx, o el wget.

O mejor aún, se puede configurar en el navegador a usar (como el konqueror, el mozilla o el opera) el proxy, usando la dirección IP: 200.40.246.2 y el puerto 3128.

2. Configurar el servidor SSH para escuchar en el puerto 443.

Según he visto, al día de hoy solo están habilitados los puertos 25, 80, 443 y 8080 para poder establecer conexiones. Tengo conocimiento de que hay otros puertos abiertos, pero solamente están abiertos para tráfico http, y las conexiones por ssh distan mucho de http.

Por lo tanto hay que tomar la decisión de que puerto usar para el ssh. Lógicamente el servidor de SSH (OpenSSH) permite escuchar en más de un puerto, así que no es necesario dejar de escuchar en el puerto predeterminado del ssh (o sea el 22).

El archivo de configuración del servidor que aloja esta opción se encuentra en "/etc/ssh/sshd_config", y tiene una línea que dice:

Port 22

Pues, bien, abajo de esta línea hay que agregar otra línea similar pero que diga:

Port 443

Hay que reiniciar el ssh, para lo cual se deberá ejecutar en el servidor:

/etc/init.d/ssh restart

o el comando necesario (dependiendo de la distribución del servidor) para reiniciar el daemon.

Para asegurarse de que el ssh está escuchando en el puerto en cuestión se puede ejecutar y probar de que funciona:

ssh -p 443 root@localhost

3. Configurar el cliente (~/.ssh/config) de SSH para poder conectarse sobre el proxy

Por ejemplo supongamos de ahora en más que para acceder al servidor de SSH en internet se llama servidor.org2), y se puede entrar desde una computadora con un acceso normal a internet ejecutando:

ssh -p 443 root@servidor.org

3.1. Modificando el archivo configuración (cliente)

Y como no siempre que queremos conectarnos al servidor.org queremos pasar a través del proxy de ancel, es conveniente definir en la configuración del cliente de ssh, un host al estilo "servidor.org.ancel" que en realidad conecte a "servidor.org".

Para hacer esto agregamos a nuestro "~/.ssh/config" las siguientes líneas:

Host servidor.org.ancel
   HostName servidor.org
   Port 443
   ProxyCommand /usr/local/bin/nproxy %h %p
   Compression yes
   CompressionLevel 9

3.2. Creando nproxy

En la siguiente dirección se puede encontrar el nproxy, y las instrucciones para poder descargarlo, compilarlo y todo eso:

http://fideo.no-ip.info/nproxy/

Aclaro que el nproxy se encuentra licenciado dualmente bajo la GPL y la licencia BSD.

Para bajar y compilar el nproxy hay que ejecutar en la consola desde un usuario normal lo siguiente:

cvs -d :pserver:anonymous@fideo.no-ip.info/repos checkout nproxy
cd nproxy
make

Para instalar el nproxy, se deberá ejecutar como root, estando ubicado en ese mismo directorio:

make install

Y después hay que agregar en el archivo "/etc/hosts" una línea diciendo:

200.40.246.2    ancel

3.2.1. Alternativas al nproxy

Si no se dispone de nproxy, o sencillamente se desea no usar, es posible usar sinó una versión especial del netcat que si soporta el método connect del proxy de http, en caso de disponer de esa versión se puede cambiar el nproxy y en usar en su lugar:

   ProxyCommand /usr/bin/nc -X connect -x 200.40.246.2:3128 %h %p

Obviamente me gusta más nproxy por una sencilla razón: Porque lo hice yo.

4. Permitir y configurar autenticación por medio de clave pública (OPCIONAL)

El sentido de tener autenticación por clave pública es poder entrar por ssh sin tener que escribir el password cada vez que se quiera establecer una conexión, y aunque no sea necesario todo esto, es claramente conveniente, y permite automatizar muchas tareas.

Para esto es necesario generar (o tener previamente generadas) un par de claves, una clave pública y una privada, con la cual se podrán establecer conexiones hacia el servidor.

La forma de saber si ya hay un par de claves creadas en la computadora cliente es fijarse si en la carpeta ~/.ssh existen archivos como id_rsa, id_dsa o identity, si ya existen, hay que pasar al punto 4.2. Instalando la clave.

4.1. Creando la clave.

En caso de haya que crear el par de claves, el comando es "ssh-keygen", ejecútelo como un usuario normal y presione 3 veces la tecla Return (también conocida como Enter en algunas PC).

Después de hacer esto deberían aparecer alguno de esos archivos antes mencionados.

Copie estas claves a la carpeta .ssh de root, ejecutando como root algo similar a lo siguiente:

cd ~/.ssh
cp ~pepito/.ssh/id_rsa* .
chmod 0600 id_rsa
chmod 0644 id_rsa.pub
chown root:root id_rsa*

O sea, la idea es que las mismas claves privada y pública estén en el usuario normal que usted usa todos los días y también en root. Nada más que eso.

4.2. Copiando la clave

Al crear la clave (o al tenerla previamente creada) deberían aparecer archivos como id_rsa, id_dsa o identity, junto otros archivos con el mismo nombre pero con ".pub" añadido, o sea por ejemplo si aparece "id_dsa" también debería aparecer "id_dsa.pub".

Estos archivos terminados en ".pub" tienen claves públicas, la cual hay que copiar al servidor:

Un ejemplo de clave es el siguiente:

ssh-dss AAAAB3NzaC1kc3MAAACBANHJAJx/GB6bJ84CDgFNcsSZ9gTI2Xik3ZqGFDYrCadL5
ABM3Rtszyuy0qTUcQvggXo3XIXosM4F6SoffAtIhkGNxt6ERX39jcGe/cDvtcFbureoYLPpXB
adborO70Rd7dyFq0ShHVhwhHuZI5AR/302oPUs0Rw6CjPEFc3VjYWhAAAAFQDmkdJrMKi0MIG
5gdlqgYn+eNBPjwAAAIBt7Z3GN+zJj3zPWlCDnhM1SXKYXLkByhZPuBdDGMhP7FDOhL/vX07k
mBwjntfCvPBxj8wPMDgt94IiH2S/0JydyOCYrRDylurdn1ZQ8XQUp30/9cqNEDI14t4Uo5LJo
RVrKlZS0TURGFivltUxaI2A6WLFLHVzjz1IqgnVnKBkpgAAAIEAof8IFnGNhPsGmwLsuJeCea
na25E//CcZb7wgmFcCWyBiHywWBGDBkK2R/2YTMNY0f+gaMB3LRNRs1cGzLtnKncTOe/+z2nC
kxRxdUkHH/lmRMHulT98P8RbsIMOJ2gaxqwLeejFhYVww6GOS0D9DwZxCcaVx1gbQ7GANC08e
RMo=

Como ya se habrán dado cuenta, publicar la clave pública no presenta un riesgo de seguridad, sin embargo, LA CLAVE PRIVADA NUNCA DEBERÁ SER PUBLICADA… (por eso se llama privada, porque es privada), y la pública se llama pública porque es pública

La clave pública es una sola línea, sí, aunque en la pantalla ocupe muchos renglones, la clave pública es 1 (una) sola línea, y por lo tanto no lleva saltos de línea entre medio.

Una forma fácil de copiar la clave pública al servidor es corriendo el siguiente comando:

scp ~/.ssh/id_rsa.pub root@servidor.org.ancel:/etc/ssh/MiClavePublica

Una vez copiada la clave pública en el servidor hay que meterla adentro del archivo "/etc/ssh/authorized_keys", una forma fácil de hacer esto es corriendo en el servidor como root lo siguiente:

cd /etc/ssh
cat MiClavePublica >> authorized_keys

4.3. Probando

Si todo funciona bien, entonces al hacer desde el usuario normal y desde el usuario root de la computadora cliente:

ssh root@servidor.org.ancel

debería poderse entrar al servidor sin pedir password.

5. Habilitar los túneles por ssh en el servidor

En el servidor hay que agregar una línea al archivo "/etc/ssh/sshd_config" diciendo algo así como:

   PermitTunnel ethernet

Y le damos un restart al sshd del servidor ejecutando:

/etc/init.d/ssh restart

6. Crear el script de configuración del túnel en el servidor

Supongamos de ahora en más que servidor.org está conectado a internet por eth0 y conectado a una red local eth1.

Supongamos también que interfaz1 tiene la IPv4: 192.168.0.1, y que las máquinas de la red local tienen direcciones de la forma 192.168.0.x

Ahora bien, desde este punto hay dos alternativas:

  1. Hacer que el túnel por celular se una a la red 192.168.0.x
  2. O hacer que el túnel quede con una dirección en otro rango, del tipo 192.168.1.x

Prefiero la primer opción porque nos permite unir al túnel de forma más transparente.

Sea cual fuese la opción elegida, hay que probablemente modificar la configuración del firewall, y ese aspecto no lo voy a tocar, porque hay tantas configuraciones posibles y tantas formas de configurarlo, que se hace imposible dar una solución genérica.

6.1. Uniéndose a la red local.

Si se desea la opción de unirse a la red local (192.168.0.0/24), lo que hay que hacer en el servidor es crear un BRIDGE, y para esto hay mucha información en internet.

La idea detrás de crear el bridge, es crear una intefaz que sería una especie de switch, en donde enchufaríamos a eth1 a una de las bocas del switch, y el túnel a otra de las bocas del switch. El servidor se comunicará con ese switch usando la interfaz br0.

El procedimiento para crear el bridge (manualmente [no recomendado]) es:

brctl addbr br0
ifconfig eth1 0
brctl addif br0 eth1
ifconfig br0 192.168.0.1

En debian, sin embargo configurar el bridge es sencillo (también lo es en otras distribuciones, pero no tengo a mano otras distribuciones para poder indicar el procedimiento)

Por ejemplo, si parte de la configuración anterior era:

auto eth1
iface eth1 inet static
	address 192.168.0.1
	netmask 255.255.255.0

Seguramente pasaría a ser:

auto br0
iface br0 inet static
	bridge_ports eth1
	address 192.168.0.1
	netmask 255.255.255.0

Después hay que hacer ifdown eth1, e ifup br0.

Y bueno, ¡a reconfigurar el firewall! (suerte en pila)

Finalmente y ya con el bridge creado, creamos un script "/usr/local/sbin/server-tunnel" y le damos permiso de ejecución, el código del script debería ser algo así:

#!/bin/sh
brctl addif br0 tap0
ifconfig tap0 up

6.2. Entrando en una red aparte

Lo que hay que hacer es asegurarse de que ip_forward esté habilitado, para esto:

cat /proc/sys/net/ipv4/ip_forward

tiene que tirar por la salida estándar una línea con nada más que un 1.

Si tira 0, hay que habilitarlo, y aunque la forma genérica de hacerlo es:

echo 1 > /proc/sys/net/ipv4/ip_forward

cuando reiniciemos este cambio va a desaparecer, por lo cual, lo mejor es buscar según la distribución en cuestión, como hacer para que este cambio quede fijo.

Una forma relativamente genérica de que este cambio quede fijo es modificando el archivo /etc/sysctl.conf.

Después creamos un script "/usr/local/sbin/server-tunnel" y le damos permiso de ejecución, el código del script debería ser algo así:

#!/bin/sh
ifconfig tap0 192.168.1.1
ifconfig tap0 up

7. Crear los scripts de configuración del túnel en el cliente

En esta sección se asume que se eligió en el paso anterior la primer opción (la de usar un bridge), sin embargo aparecen mencionados en esta sección todos los cambios necesarios para poder usar la segunda opción.

Antes que nada: Para crear el túnel es necesario ser root. Por lo tanto en el /root/.ssh/config se deberá agregar lo siguiente:

Host servidor.org.ancel.tunnel
   HostName servidor.org
   Port 443
   ProxyCommand /usr/local/bin/nproxy %h %p
   Compression yes
   CompressionLevel 9
   Tunnel ethernet
   PermitLocalCommand yes
   LocalCommand /usr/local/sbin/client-tunnel

(además del ya agregado servidor.org.ancel)

Y se deberá crear otro script en "/usr/local/sbin/client-tunnel" (pero de la máquina cliente), al cual también se le deberá dar permiso de ejecución y deberá contener lo siguiente:

#!/bin/bash
ifconfig | grep -q ppp0 || exit
if [ "$1" == "run" ]
then
  while ! ifconfig -a | grep -v -q tap0; do
    sleep 1
  done
  route add -host ancel dev ppp0
  route del default
  while ! ifconfig | grep -q tap0; do
    sleep 1
    ifconfig tap0 192.168.0.800
    route add default gw 192.168.0.1
  done
else
  "$0" run &
fi

En el script recién mencionado se deberá cambiar 192.168.0.800 (la cual es una IPv4 inválida) por la IPv4 que se le desea asignar al lado del celular del túnel.

Si se eligió poner el túnel en una red aparte, hay que cambiar donde dice 192.168.0.1 por el IPv4 del lado del servidor del túnel, en los ejemplos dados en este documento esa IPv4 era 192.168.1.1.

De todas formas deberá cambiar las IPs de los ejemplos, a menos que por pura coincidencia usted use esas mismas direcciones en su servidor.

Finalmente solo hay que ejecutar el comando para crear el túnel; el cual debería ser el siguiente:

ssh -w 0:0 root@servidor.org.ancel.tunnel /usr/local/sbin/server-tunnel

Es conveniente crear un script o un alias para el comando anterior, principalmente porque es extremadamente difícil acordarse del comando.

Un script (/usr/local/sbin/ssh-tunnel) adecuado para ejecutar el comando anterior es el siguiente:

#!/bin/bash
# ssh-tunnel: Script para iniciar el túnel de ssh.
# Copyright (C) 2007 Francisco Castro <fcr@adinet.com.uy>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

# Modifique los siguientes valores por omisión de acuerdo a su configuración:
CFG_VHOST=servidor.org.ancel.tunnel
CFG_SERVSCRIPT=/usr/local/sbin/server-tunnel

muestra_ayuda(){
  echo "Sintaxis: $1 "'[-destino VHOST] [-serverscript SERVSCRIPT]'
  exit
}

while [ "$1" ]
do
  case "$1" in
    -destino)
      CFG_VHOST="$2"
      shift 2;;
    -serverscript)
      CFG_SERVSCRIPT="$2"
      shift 2;;
    -h) muestra_ayuda "$0";;
    -help) muestra_ayuda "$0";;
    --help) muestra_ayuda "$0";;
    *)
      echo "Opción \"$1\" inválida."
      exit;;
  esac
done

exec ssh -w any:any "root@$CFG_VHOST" $CFG_SERVSCRIPT

8. Conclusiones

El proxy de ANCEL sólo permite limitar a sus usuarios, aparte es el culpable de tornar las conexiones (que podrían tener buena velocidad y buen rendimiento) en algo que es prácticamente insoportable.

Tras el transcurso de 2 meses de probar y probar como hacer para poder sacar el mayor provecho de un servicio que estoy pagando, sin hacerle ningún daño a ANCEL, ni colaborando en una denegación de servicio a los otros usuarios, busqué varias alternativas. Finalmente encontré que creando un túnel es posible sin mayores dificultades pasar a tener una conexión medianamente estable, y sin ninguna de las ilógicas limitaciones que ANCEL pone a sus usuarios.

Acerca de las limitaciones, considero que ANCEL está abusando de los clientes. Considero que deberían simplemente poner un simple servidor para hacer NAT o mejor aún un router dando una IP pública a cada celular que lo solicite, sin embargo tengo entendido que no hacen eso por lo siguiente:

En estos momentos, en los que el proxy funciona de manera pésima, podría considerarse una tercer razón: Motivar a los usuarios que deseen tarifa plana a que coloquen ADSL.

Este documento no explica la única forma de sacar provecho (de forma totalmente legal) del servicio, sino que entiende y motiva a que los usuarios encuentren también otras maneras legales de aprovechar al máximo algo que los clientes pagamos.

Sin más que aportar, y esperando sus comentarios constructivos, saluda;

Francisco Castro 2007/07/25 19:18


http://creativecommons.org/licenses/by-nc-sa/2.5/ar/

1) Al momento en que escribí este texto, el acceso a internet sin contrato costaba un tercio del precio del minuto de hablar por celular.
2) obviamente que su servidor no se llama servidor.org, así que deberá cambiar cada ocurrencia de servidor.org, por un nombre de dominio accesible desde internet (tener un subdominio en no-ip puede resultar una opción atractiva).