viernes, 25 de julio de 2014

Configurando la red para máquinas virtuales

Siguiendo con la configuración de máquinas virtuales, es hora de configurar la red.

Quiero que mis máquinas virtuales atiendan servicios, así que necesito que tengan direcciones IP visibles desde la red física, a las que mi enrutador pueda dirigirse.

Ha sido muy difícil encontrar la documentación, y al final en realidad he tenido que recurrir a métodos de prueba y error, pero finalmente lo tengo.

En el servidor, hay que configurar un puente. Eso quiere decir que pasamos de esto:

#/etc/network/interfaces

# The primary network interface
allow-hotplug eth0
auto eth0
iface eth0 inet static
      address 192.168.2.25
      netmask 255.255.255.0
      network 192.168.2.0
      broadcast 192.168.2.255
      gateway 192.168.2.1
      dns-nameservers 127.0.0.1
      dns-domain rolamasao.org

a esto:

#/etc/network/interfaces

# The primary network interface
auto br0
iface br0 inet static
        bridge_ports eth0
        address 192.168.2.25
        netmask 255.255.255.0
        network 192.168.2.0
        broadcast 192.168.2.255
        gateway 192.168.2.1
        dns-nameservers 127.0.0.1
        dns-domain rolamasao.org

Es importante notar que a partir de ese momento debemos considerar que la interfaz de red de nuestro servidor físico es br0, y no eth0.

Claro que de nada sirve tener un puente si los paquetes que llegan al puente no son retransmitidos hacia Internet. Por eso hay que modificar un parámetro del kernel:

# /etc/sysctl.conf - Configuration file for setting system variables

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

Para que estos cambios tengan efecto es necesario reiniciar, pero siempre se pueden ejecutar a mano con un poquito de brctl, ifconfig, route y echo.

En las máquinas virtuales la configuración debe indicar que utilizan el puente br0, lo cual es bastante sencillo de hacer desde virt-manager. Ya dentro de la máquina virtual, tenemos una configuración bastante estándar. Simplemente hay que indicar que el enrutador por defecto es la máquina física, no el enrutador de la red:

#/etc/network/interfaces VIRTUAL

# The primary network interface
allow-hotplug eth0
iface eth0 inet static
        address 192.168.2.80
        netmask 255.255.255.0
        network 192.168.2.0
        broadcast 192.168.2.255
        gateway 192.168.2.25
        # dns-* options are implemented by the resolvconf package, if installed
        dns-nameservers 192.168.2.25

sábado, 19 de julio de 2014

Identificando máquinas virtuales

Últimamente me estoy metiendo a configurar máquinas virtuales en casa. Más adelante hablaré sobre todos los pasos necesarios, pero de momento me voy a referir al importante detalle de identificar la máquina en la que se trabaja.

Claro que todas las máquinas tienen nombre, pero ¿realmente leemos el nombre de máquina que aparece en el prompt de la shell?

root@vmserver:~#

¿Qué máquina es esa? Hay que fijarse mucho para ver que se trata de una máquina llamada vmserver. Y si tenemos varias máquinas abiertas en distintas pestañas de nuestro programa de terminal, es fácil confundirse. A mí me ha pasado ejecutar un poweroff en la máquina física pensando en apagar una máquina virtual. Y duele.

Así que me decidí a identificarlas por colores.

Las instrucciones de debajo son bastante generales pero has sido comprobadas en una máquina Debian. En otras distribuciones de Linux puede ser ligeramente diferente y en otros Unix muy diferente.

Toda sesión de shell de una máquina comienza ejecutando el fichero /etc/profile. Y este fichero a su vez llama a /etc/bash.bashrc (en el caso de que la shell en uso sea bash y el acceso sea interactivo).

Este segundo fichero define la variable PS1 de esta manera:

# set a fancy prompt (non-color, overwrite the one in /etc/profile)
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '

Esto prepara el bonito prompt al que estamos acostumbrados, con user@host:directorio$ .

root@vmserver:~#

Pero decidí que las máquinas virtuales tuvieran el prompt azul para distinguirlas de la máquina física, así que lo modifiqué de esta manera:

set a fancy prompt (non-color, overwrite the one in /etc/profile)
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
# extra color for real/virtual machine differentiation
MACHINECOLOR=34
STARTCOLOR="\e[0;${MACHINECOLOR}m";
ENDCOLOR="\e[0m"
export PS1="$STARTCOLOR$PS1$ENDCOLOR"

Aparte de un detalle para controlar si estamos en un chroot e indicárnoslo, obtenemos el bonito resultado de

root@vmserver:~#

STARTCOLOR se encarga de iniciar el azul, y ENDCOLOR de finalizarlo, lo que es muy importante para evitar que todo el texto quede azul:

root@vmserver:~# ls
root@vmserver:~# echo 1
1
root@vmserver:~#

34 es el código para el azul. Hay otros:

Black 0;30
Red 0;31
Green 0;32
Brown 0;33
Blue 0;34
Purple 0;35
Cyan 0;36
Light Gray 0;37
Dark Gray 1;30
Light Red 1;31
Light Green 1;32
Yellow 1;33
Light Blue 1;34
Light Purple 1;35
Light Cyan 1;36
White 1;37


Lo importante es que estos no son códigos de bash sino secuencias de escape ANSI/VT-100, porque no las interpreta la shell sino la terminal.

Así, podemos usar otros códigos ANSI/VT100 para conseguir otros efectos. Como los que necesito en la máquina física.

# set a fancy prompt (non-color, overwrite the one in /etc/profile)
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
# extra color for real/virtual machine differentiation
MACHINECOLOR=31
# root differentiation
if [ $(id -u) -eq 0 ] ; then
    MACHINECOLOR="7;$MACHINECOLOR"
fi
STARTCOLOR="\e[0;${MACHINECOLOR}m";
ENDCOLOR="\e[0m"
export PS1="$STARTCOLOR$PS1$ENDCOLOR"

Aquí utilizo el código 31 que corresponde al rojo, color universal de aviso, que en este caso me indica que estoy en la máquina real, para evitar meter la pata. Pero hay un detalle más: se comprueba si el usuario es root y si es así, se utiliza el código 7 para invertir los colores:

user@realserver:~$ ls
user@realserver:~$ echo 1
1
user@realserver:~$ su -
Contraseña: 
root@realserver:~# ls
root@realserver:~# echo 1
1
root@realserver:~# 

Con lo cual ahora es bastante más difícil equivocarse de máquina o no recordar que uno es root.

El pequeño problema es que normalmente PS1 es posteriormente redefinido en el fichero ~/.bashrc que es llamado desde ~/.profile:

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

Así que en el fichero ~/.bashrc de cada usuario, y en el fichero /etc/skel/.bashrc para los nuevos usuarios que se creen, hay que modificarlo a esto:

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    #PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
    PS1=$PS1
fi
unset color_prompt force_color_prompt

Y ya tenemos nuestras terminales perfectamente coloreadas.

    Referencias:
  1. http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html
  2. http://misc.flogisoft.com/bash/tip_colors_and_formatting
  3. https://wiki.archlinux.org/index.php/Color_Bash_Prompt_(Espa%C3%B1ol)
  4. http://www.termsys.demon.co.uk/vtansi.htm