2008-05-24

Wireless@home

Update: Más configuración por seguridad

Hoy configuré el modem ADSL/router/access point wireless (AKA: "el coso wireless") que me compré en la semana y lo hice andar completo (wireless con WAP2). Es un hermoso ZyXEL PRESTIGE 660R-61C.
Ahora les cuento que cosas tuve que hacer para hacerlo hacer andar.

Paso 1: conexión a speedy


Conecté una notebook con fluxbuntu al "coso wireless" con el cable ethernet que viene en la caja y enchufé el cable de teléfono (que también viene en la caja) entre el coso y la boca de teléfono. Configuré eth0 para que esté en 192.168.1.23 (creo que casi cualquier IP en la red 192.168.1.x debe andar) y me dirigí con un browser a 192.168.1.1. Por suerte le pegué (de re-pedo) y entré al menú de configuración del coso vía web.
Intenté setear de una la conexión pero no funcó :(. ¿Por qué? Los seteos de VPI y VCI correctos para speedy (8 y 35 respectivamente) no los aceptaba. Después de un rato de googleo, encontré la página de speedy donde explica como configurar el coso wireless. Lo único que hice distinto es que cómo ya había cambiado el password de administración desde la parte web, puse mi password nuevo. Seguí las instrucciones, setié como name servers a200.51.211.7 y 200.51.212.7 y ¡se conectó a speedy!

Paso 2: Compartir la conexión entre varias PCs


Con esto andando, el siguiente paso fue compartir la conexión entre 2 PCs. Esto fue re-fácil. Configuré mis 2 notebooks x DHCP y las enchufé al coso wireless con sendos cables ethernet. Una vez que las PCs estuvieron andando, ya tenía conexión a internet :D

Paso 3: El coso wireless es wireless (y se supone que yo sé de seguridad informática)


Bueno, esto ya estaba andando. Entonces me puse a configurar el acceso wireless. En cuanto miré, algún vecino "extra rápido" ya se había conectado a mi coso wireless y estaba leecheando internet. Así que empecé a cerrarlo. Mirando rápido el menú me pareció que había solo WEP, y "this is unacceptable" para un investigador en seguridad informática como yo (chiste). Así que apagué el wireless para que no leecheen más y empecé a mirar la configuración. Al final encontré la parte de WAP, que está en otro menú (parece que la amigabilidad no es parte de los objetivos de diseño del menú administrativo por web del coso wireless). Y empecé a probar.
Para hacer andar la parte wireless tuve un desafío extra, que es que lo hice andar en un Kubuntu Hardy (8.04). Por suerte, cuando compré mi notebook tuve la delicadeza de comprar una placa Intel, por lo que se me hizo más fácil. Después de varias vueltas descubrí que lo mejor era configurar el coso wireless en WPA2 con PSK (pre-shared key). Y solo queda explicar que hice para hacer que ande el Kubuntu. Probé un montón de cosas que no andaban hasta que encontré por internet (no tengo el link acá) que a veces reinstalando algunos paquetes la integración de las placas wireless. Así que hice
sudo aptitude reinstall knetworkmanager wpasupplicant network-manager
y santo remedio. Cargué el KNetwork Manager y cliquié el botón derecho, me conecté a mi red, puse el password que había configurado en el párrafo anterior y anduvo todo joya.

Paso 4: Ajustes finales


Por último, quiero seguir pudiendo conectarme a bit torrent bien para "bajar ISOs de Linux". Así que configuré que la MAC de mi notebook tenga IP fija (está en la parte de LAN del menú avanzado) y forwardié los puertos correspondientes (TCP y UDP) que tengo configurados en el KTorrent.
Y para que sea más seguro (mirando los ataques que postulan en GNU Citizen) le configuré distinto el SNMP. Me conecte x telnet al coso y cambié las opciones del menú 22, que quedó algo así:

SNMP:
Get Community= [passwd nuevo]
Set Community= [otro passwd nuevo]
Trusted Host= 0.0.0.0
Trap:
Community= [y otro pass más]
Destination= 0.0.0.0

En una mirada rápida, me pareció que el resto de los ataques requieren que el atacante esté conectado en la red interna, así que los dejo para después (supongo que requerirán un cambio de firmware).

Así llegué a la configuración que quería y me dediqué a escribir este post.
Happy hacking,
Aureliano.

2008-05-03

El último pelo

Este hilarante blog habla de los calvos. Sus problemas y soluciones. Envidias y resentimientos. Gracias y tristezas. Recomiendo ampliamente a este blog, que es el único que conozco que tiene su propia canción. En fin, tómense unos minutos y ríanse un rato. Yo, como buen calvo que soy, lo recomiendo.

Happy hacking,
Aureliano.

2008-05-02

Load balancer minimalista en ruby (parte 2)

En el post anterior mostré un load balancer que implementé en ruby. Ahora le agregué algo de manejo de errores y algo de fail-over para que sea más estable.

Este es el código nuevo:


#!/usr/bin/env ruby
require 'socket'

def usage
puts "Very simple balancer"
puts "balancer.rb port host1:port1 [host2:port2 ....]"
exit
end

def build_targets(argv)
argv.map do
|param|
result = param.split(":")
result[1] = result[1].to_i
result
end
end

class Balancer
def initialize(port, *targets)
@descriptors = []
@next_step = {}

@serverSocket = TCPServer.new( "", port )
@serverSocket.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
puts("Balancer started on port #{port}")

@descriptors << @serverSocket

@targets = targets
@current_out = 0
end

def next_out
out_socket = nil
until out_socket
begin
@current_out = (@current_out + 1) % @targets.length
descr = @targets[@current_out]
out_socket = TCPSocket.new(descr[0], descr[1])
rescue
# do nothing on purpose
end
end
out_socket
end

def accept_new_connection

incoming = @serverSocket.accept
outgoing = next_out

@next_step[incoming] = outgoing
@next_step[outgoing] = incoming

@descriptors += [ incoming, outgoing ]
end

def propagate(sock)
next_sock = @next_step[sock]
next_sock.write(sock.read_nonblock(1000 * 1000))
end

def finish_connection(sock)
next_sock = @next_step[sock]
[sock, next_sock].each do
|s|
begin
s.close
rescue Object => e
puts "Error closing socket: #{e.inspect}"
end
@descriptors.delete(s)
@next_step.delete(s)
end
end

def run
loop do
connections = select( @descriptors )
if connections
connections[0].each do
|sock|
if sock == @serverSocket then
accept_new_connection
else
begin
if sock.eof? then
finish_connection(sock)
else
propagate(sock)
end
rescue
finish_connection(sock)
end
end
end
end
end
end
end

trap("SIGINT") do
exit
end

usage if ARGV.length < 2
port = ARGV.shift.to_i
targets = build_targets(ARGV)

Balancer.new(port, *targets).run


Me parece que ahora pueden llegar a usarlo.

Happy hacking,
Aureliano.

2008-05-01

Load balancer minimalista en ruby

Update: Puse la versión más nueva en este post.

Ayer estuve inspirado y dediqué un poquito de mi tiempo a aprender un poco más sobre cómo manejar sockets. Hacía mucho tiempo que no programaba sockets en bajo nivel y nunca había necesitado usar select para manejar muchos al mismo tiempo. De hecho, la última vez que tuve que hacer algo parecido a un server que acepte muchas conexiones TCP lo hice en java 1.3, y en java 1.3 no hay select (agregaron algo parecido en java.nio, que apareció después).
Así que puse manos a la obra e hice un minicloncito de un load balancer en ruby.
Por supuesto que no hice todo. En particular, me comí el manejo de errores. Pero si hace round robin de conexiones y tiene menos de 100 líneas de código, lo que creo que lo hace un buen ejemplo de juguete sobre como manejar sockets en ruby.
Bueno, basta de cháchara, acá va el código completo:


#!/usr/bin/env ruby
require 'socket'

def usage
puts "Very simple balancer"
puts "balancer.rb port host1:port1 [host2:port2 ....]"
exit
end

def build_targets(argv)
argv.map do
|param|
result = param.split(":")
result[1] = result[1].to_i
result
end
end

class Balancer
def initialize(port, *targets)
@descriptors = []
@next_step = {}

@serverSocket = TCPServer.new( "", port )
@serverSocket.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
puts("Balancer started on port #{port}")

@descriptors << @serverSocket

@targets = targets
@current_out = 0
end

def next_out
@current_out = (@current_out + 1) % @targets.length
@targets[@current_out]
end

def accept_new_connection
out_descriptor = next_out

incoming = @serverSocket.accept
outgoing = TCPSocket.new(out_descriptor[0], out_descriptor[1])

@next_step[incoming] = outgoing
@next_step[outgoing] = incoming

@descriptors += [ incoming, outgoing ]
end

def propagate(sock)
next_sock = @next_step[sock]
next_sock.write(sock.read_nonblock(1000 * 1000))
end

def finish_connection(sock)
next_sock = @next_step[sock]
[sock, next_sock].each do
|s|
s.close
@descriptors.delete(s)
@next_step.delete(s)
end
end

def run
loop do
connections = select( @descriptors )
if connections
connections[0].each do
|sock|
if sock == @serverSocket then
accept_new_connection
else
if sock.eof? then
finish_connection(sock)
else
propagate(sock)
end
end
end
end
end
end
end

trap("SIGINT") do
exit
end

usage if ARGV.length < 2
port = ARGV.shift.to_i
targets = build_targets(ARGV)

Balancer.new(port, *targets).run

Para usarlo, copien todo el codigo a un archivo (como balancer.rb) y fijense en el cartel que explica los parámetros. El primer parámetro es el puerto donde escucha y los otros son pares host:port a los que tiene que conectarse alternativamente.

Bueno, eso es todo por ahora.

Happy hacking,
Aureliano.