Etiqueta: linux

  • La rueda del ratón recorre el historial de comandos en lugar de desplazar la terminal

    Hace poco me volvió a pasar que después de algún evento que no consigo identificar bien, la rueda del raton en lugar de desplazar la vista de la terminal empieza a recorrer su historial de comandos.

    Algunas aplicaciones de terminal tienen la capacidad de restaurar el comportamiento anterior, pero este no era el caso así que busqué por Internet y descubrí un comando del que nunca antes había oído hablar; tput. En concreto la llamada que logra restaurar el desplazamiento de la terminal es el siguiente:

    tput rmcup

  • Un túnel SSH

    Mi primera intención con esta entrada era simplemente anotar a modo de nota/receta/chuleta cómo crear un túnel SSH para poder iniciar sesión en una máquina (o copiar ficheros por SCP) a la que no se tiene acceso directo, es decir, utilizando otra máquina como paso intermedio. Pero al final me he liado.

    En primer lugar hay que explicar en qué consiste el túnel o redirección de puertos SSH. Básicamente se trata de abrir un socket TCP en modo escucha, establecer otra conexión con otro socket TCP en modo escucha cuando se establezca una conexión con el primero, y enviar por cada una de estas dos conexiones todo lo que se reciba por la otra. Es decir, la primera conexión TCP es un extremo de un túnel y la segunda conexión TCP es el otro.

    Dicho esto, hay que tener en cuenta que el establecimiento y mantenimiento de un túnel SSH está asociado a una sesión SSH. Así, uno de los dos extremos del túnel estará forzosamente en el cliente o en el servidor de dicha sesión SSH. Por lo tanto, hay que decidir si dicho puente se quiere abrir en el cliente o en el servidor de esa necesaria sesión SSH.

    Si se desea establecer un puente desde la máquina local (cliente de la sesión SSH) se utilizará el parámetro -L (de Local tunnel, por ejemplo), mientras que si el puente se quiere establecer en la máquina remota (servidor de la sesión SSH) se utilizará -R (de Remote tunnel, para seguir con la misma lógica)

    Puesto que una imagen suele valer más que mil palabras, aquí van dos para reflejar ejemplos de ambas situaciones.

    Estas imágenes están atribuidas a Serypol [CC BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0)], from Wikimedia Commons.

    SSH Tunnel (remote)
    Túneles desde servidor de la sesión SSH.
    Ssh-L-Tunnel
    Túneles desde cliente de la sesión SSH.

    Seguiría extendiéndome porque el tema es interesante, pero ya me estoy cansando, así que voy a ir al grano de una vez, que es lo que originalmente pretendía.

    En definitiva, para establecer el túnel hay que proporcionar cierta información que clasifico en cuatro grupos. El primero define la necesaria sesión SSH, donde se deberá al menos indicar la máquina con la que establecerla. El segundo determina si el túnel va a situar su entrada en el cliente de dicha sesión SSH (local) o en el servidor (remoto). En el tercero se define el socket TCP de entrada al túnel. Y en el cuarto y último el socket con el que se conecta la salida.

    Para mostrar como se pone esto en práctica pondré dos ejemplos de túnel SSH que solucionan el problema que dio pie a esta entrada, uno en modo local y otro en modo remoto.

    El problema

    El problema a resolver consiste en obtener acceso a un servidor SSH con el que no tenía se tiene conectividad sino a través de otra servidor. La máquina desde la que se desea establecer la conexión se llamará local, la máquina desde la que se dará el salto (jump server se dice por ahí) se llamará proxima y la máquina destino final de la conexión se llamará ultima.

    La solución con túnel local

    Veamos como establecer el túnel en modo local definiendo los cuatro grupos de información que indiqué antes. El lugar donde colocar la entrada del túnel, como acabo de indicar, será en el lado local de la sesión SSH. La sesión SSH que soportará el túnel se establecerá entre las máquinas local y proxima, como no podía ser de otra forma. El socket TCP de entrada al túnel admitirá conexiones en todos los interfaces de local por el puerto 2222. Y el otro extremo del túnel establecerá conexión con el puerto 22 de ultima.

    Para crear este túnel se ejecutaría el siguiente comando:

    ssh -L *:2222:ultima:22 proxima -l usuario

    En este comando se especifican los cuatro grupos de información tal como se explica a continuación por orden de aparición:

    1. -L indica que se desea crear un túnel desde el extremo local de la sesión SSH a establecer.
    2. *:2222 define la entrada al túnel.
      1. * indica que el puerto de escucha se asociará a todos los interfaces de red (*) en local. Aquí se podría haber indicado una IP concreta (o IPv6) para admitir únicamente conexiones en el interfaz correspondiente a dicha IP.
      2. 2222 es el puerto de escucha en local.
    3. ultima:22 define el destino del túnel.
      1. ultima es la IP o nombre de equipo o de dominio de ultima, la máquina destino de la conexión desde la salida del túnel.
      2. 22 es el puerto en ultima hacia el que se canalizarán las conexiones que se establezcan con el puerto 2222 en proxima.
    4. proxima -l usuario define la sesión SSH que abre y mantiene el túnel.
      • proxima es la IP o nombre de equipo o de dominio de proxima, la máquina intermedia o jump server.
      • -l usuario indica el nombre del usuario con el que se establecerá la sesión SSH a proxima.

    Tras la ejecución de este comando se inicia una sesión SSH con proxima y, mientras dure dicha sesión, se mantendrá el túnel con entrada en el puerto 2222 de local y salida hacia el puerto 22 de ultima.

    Sin embargo, con esta forma de establecer el túnel debemos mantener activa una sesión SSH que tal vez no necesitamos utilizar. Afortunadamente, se pueden añadir un par de opciones al comando anterior para crear una sesión SSH desligada de nuestra sesión local, de forma que mantengamos abierto el túnel sin requerir una sesión SSH interactiva.

    Con el parámetro -f indicamos que la sesión SSH pase a segundo plano, desligándose de la sesión desde la que se lanza. Puesto que para pasar a segundo plano se debe indicar un comando a ejecutar en la sesión SSH, se añade también el parámetro -N que indica explícitamente que no se debe ejecutar ningún comando.

    Por tanto el comando completo sería algo así:

    ssh -L *:2222:ultima:22 proxima -l usuario -f -N

    Ahora se puede iniciar una conexión con el puerto 22 de última para iniciar una sesión SSH desde cualquier máquina con acceso al puerto 2222 de local:

    ssh -p 2222 local -l usuario

    El túnel canalizará la conexión establecida con el puerto 2222 de local con una nueva conexión desde proxima al puerto 22 de ultima, donde deberá estar escuchando su servidor SSH.

    La solución con túnel remoto

    Por último, se puede crear la entrada del túnel en la máquina remota de la sesión SSH, es decir, en proxima. Para ello basta con utilizar la opción -R (remota) en lugar de -L (local).

    ssh -R *:2222:ultima:22 proxima -l usuario -f -N

    En este caso, puesto que la entrada del túnel la crea el servidor SSH (sshd) del lado remoto de la sesión SSH, este deberá tener la opción GatewayPorts habilitada en el fichero /etc/ssh/sshd_config, de lo contrario, solo aceptará conexiones al túnel en el interfaz de loopback, es decir solo se podrán conectar clientes que se ejecuten en la misma máquina que el servidor SSH.

    Para permitir la conexión desde otras máquinas hay que comprobar que está la siguiente línea en el fichero /etc/ssh/sshd_config del servidor SSH (proxima) y reiniciar el servidor SSH si no lo estaba previamente:

    GatewayPorts yes

    Referencias:

  • El extraño caso del bonding medio sordo

    Una técnica muy utilizada para proporcionar mayor disponibilidad y capacidad a la conexión entre dos equipos consiste en utilizar simultáneamente varios enlaces físicos entre ambos, formando un grupo de agregación de enlaces o LAG (Link Aggregation Group). LAG considero que es el término más correcto, aunque también son conocidos como port channel en el mundo de las redes o bonding en el mundo GNU/Linux. También, aunque de forma incorrecta en mi opinión, se les llama a veces trunk (de una tecnología propietaria llamada port trunking), esto a mí me resulta ambiguo, porque el uso más generalizado del término es para referrirse a un puerto de un switch por el que se permite tráfico de varias VLAN.

    El caso es que para proporcionar mayor ancho de banda a un nuevo servidor de ficheros se quiere establecer un LAG entre este y el correspondiente conmutador (bonito término castellano para un switch). Esto, en principio, es bastante sencillo, sobre todo teniendo en cuenta que el servidor corre un Red Hat Enterprise Linux 7.3 (suficientemente moderno, su núcleo es la versión 3.10 de Linux) y el switch es un Cisco que ha costado más de lo que amortizo de hipoteca en un año.

    Para establecer el LAG entre el servidor y el switch se va a utilizar el protocolo LACP (Link Aggregation Control Protocol), soportado por ambos.

    El switch se configura creando un nuevo interfaz del tipo PortChannel, que será un interfaz virtual que representa al grupo de agregación, y añadiendo los interfaces físicos a utilizar a dicho grupo.

    Aquí llamaremos al port channel port-channel1 (Po1 para los amigos) y añadiremos a su grupo los interfaces Ethernet1/1 al Ethernet1/4.

    interface Po1
    
    interface Eth1/1 - 4
      channel-group 1

    Con esto es suficiente, ya que aunque hay varias formas de establecer el LAG, el modelo de switch utilizado usa el protocolo LACP por defecto. Como se verá más adelante, suponer que LACP era utilizado por defecto fue la causa del problema.

    En el servidor se hace de forma similar creando un ficheo de configuración para el bonding que llamaremos bond0 y cambiando la configuración de los interfaces físicos a añadir al LAG.

    /etc/sysconfig/network-scripts/ifcfg-bond0:

    TYPE=Bond
    BOOTPROTO=none
    NAME=bond0
    DEVICE=bond0
    ONBOOT=yes
    BONDING_MASTER=yes
    IPADDR=192.168.10.10
    GATEWAY=192.168.10.1
    PREFIX=24
    BONDING_OPTS="mode=4 miimon=100 lacp_rate=1"

    Aquí es necesario indicar el modo del bonding, ya que soporta varios tipos de funcionamiento, el modo 4 utilizado es el que corresponde al protocolo 802.3ad, es decir LACP. El parámetro miimon indica cada cuantos milisegundos se debe comprobar si un interfaz del bonding tiene enlace, si se detecta que no tiene enlace será extraído del LAG inmediatamente. El parámetro lacp_rate indica cada cuantos segundos se envía un paquete de control de LACP (LACPDU).

    Los interfaces miembro del LAG se configuran así:

    /etc/sysconfig/network-scripts/ifcfg-eth0

    TYPE=Ethernet
    BOOTPROTO=none
    NAME=eth0
    DEVICE=eth0
    ONBOOT=yes
    MASTER=bond0
    SLAVE=yes

    Una vez configurados los interfaces del servidor (habrá que reiniciar los servicios de red) y el switch se debe establecer el LAG entre ambos.

    Para ver el estado del interfaz bond0 se puede consultar el fichero /proc/net/bonding/bond0, aunque también podemos obtener suficiente información con un simple listado de los interfaces:

    #ip link
    ...
    8: eth0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master bond0 state UP mode DEFAULT qlen 1000
        link/ether a0:b6:cf:d0:2d:f8 brd ff:ff:ff:ff:ff:ff
    9: eth1: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master bond0 state UP mode DEFAULT qlen 1000
        link/ether a0:b6:cf:d0:2d:f8 brd ff:ff:ff:ff:ff:ff
    10: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT qlen 1000
        link/ether a0:b6:cf:d0:2d:f8 brd ff:ff:ff:ff:ff:ff
    ...

    Aquí se ve que hay dos interfaces eth0 y eth1 en modo SLAVE (parte de un bonding) y que hay un interfaz en modo MASTER (el bonding), todos están UP (tienen enlace) y todos tienen la misma MAC (como debe ser), ya que todos los interfaces físicos actúan «en representación» del interfaz de bonding.

    En el switch también parece estar todo bien:

    #sh int Po1
    port-channel1 is up
    admin state is up,
      Hardware: Port-Channel, address: a4bd.c6db.aac9 (bia a4bd.c6db.aac9)
      MTU 1500 bytes, BW 20000000 Kbit, DLY 10 usec
      reliability 255/255, txload 1/255, rxload 1/255
      Encapsulation ARPA, medium is broadcast
      Port mode is access
      full-duplex, 10 Gb/s
      Input flow-control is off, output flow-control is off
      Auto-mdix is turned off
      Switchport monitor is off
      EtherType is 0x8100
      Members in this channel: Eth1/1, Eth1/2, Eth1/3, Eth1/4
      Last clearing of "show interface" counters never
      1 interface resets
      30 seconds input rate 2328 bits/sec, 1 packets/sec
      30 seconds output rate 2520 bits/sec, 1 packets/sec
      Load-Interval #2: 5 minute (300 seconds)
        input rate 12.83 Mbps, 1.02 Kpps; output rate 139.13 Kbps, 181 pps
      RX
        2705286 unicast packets  3316 multicast packets  3932 broadcast packets
        2712534 input packets  3986560464 bytes
        0 jumbo packets  0 storm suppression packets
        0 runts  0 giants  0 CRC  0 no buffer
        0 input error  0 short frame  0 overrun   0 underrun  0 ignored
        0 watchdog  0 bad etype drop  0 bad proto drop  0 if down drop
        0 input with dribble  0 input discard
        0 Rx pause
      TX
        510610 unicast packets  29736 multicast packets  3699 broadcast packets
        544045 output packets  53042671 bytes
        0 jumbo packets
        0 output error  0 collision  0 deferred  0 late collision
        0 lost carrier  0 no carrier  0 babble  0 output discard
        0 Tx pause

    En esta información lo importante es que el port channel está UP y que el ancho de banda del mismo es 20.000.000 Kbit. El ancho de banda indica que hay dos puertos, de los cuatro que son miembros del port channel, que están conectados (se trata de puertos de 10 Gbps).

    Viendo esto todo parece estar bien, sin embargo, al hacer un ping a otro equipo que se envía por dicho interfaz resulta que no hay respuesta:

    # ping 192.168.10.20
    PING 192.168.10.20 (192.168.10.10) 56(84) bytes of data.
    From 192.168.10.10 icmp_seq=1 Destination Host Unreachable
    From 192.168.10.10 icmp_seq=2 Destination Host Unreachable

    Habrá que investigar, para ello lo primero comprobar qué pasa por el interfaz bond0:

    # tcpdump -nn -i bond0
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on bond0, link-type EN10MB (Ethernet), capture size 65535 bytes
    11:59:12.717212 ARP, Request who-has 192.168.10.20 tell 192.168.10.10, length 28
    11:59:13.719184 ARP, Request who-has 192.168.10.20 tell 192.168.10.10, length 28

    Y así sucesivamente, es decir, los ARP no obtienen respuesta, pero eso ¿por qué? Indaguemos un poco más y veamos el tráfico en cada interfaz:

    # tcpdump -nn -i eth0
    tcpdump: WARNING: eth0: no IPv4 address assigned
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
    12:01:53.985192 ARP, Request who-has 192.168.10.20 tell 192.168.10.10, length 28
    12:01:54.987189 ARP, Request who-has 192.168.10.20 tell 192.168.10.10, length 28

    Vale, el bond0 está utilizando el interfaz eth0 para envíar las consultas ARP y no obtiene respuesta. Veamos entonces si hay algo extraño en el eth1:

    # tcpdump -nn -i eth1
    tcpdump: WARNING: eth1: no IPv4 address assigned
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
    12:03:21.343287 ARP, Reply 192.168.10.20 is-at a0:d6:cf:d0:32:b0, length 46
    12:03:22.940519 ARP, Reply 192.168.10.20 is-at a0:b6:cf:d0:32:b0, length 46

    Bueno, no es muy extraño, la política de reparto de carga entre los enlaces no es la misma en el switch que en el servidor, por lo que el servidor envía una consulta ARP por un interfaz y la recibe por el otro. A mí me parece normal.

    Entonces, ¿por qué no pasan las respuetas ARP del interfaz eth1 al bond0? Pues porque el bonding está medio sordo. Pero, ¿por qué está medio sordo el bonding?

    Comienza la investigación por el Interné: Google, a ver qué encuentras sobre esto: «Linux bonding medio sordo». Pero parece que nadie ha escrito aún sobre esto, bueno a ver en inglés: «Linux bonding half deaf». Tampoco.

    En fin, toca leer la documentación del módulo de bonding y relacionada. Así, que tras no encontrar nada muy claro y buscar de todo relacionado con el bonding y 802.3ad dí con el artículo que me dio la clave (aunque trataba de otro problema): [Linux Bonding] 802.3ad bond interface has shown RX dropped packets.

    En ese artículo hablaba de que el bonding, de manera premeditada y (en otros casos, desde luego) correcta, descartaba los paquetes recibidos por los interfaces no activos del bonding. Esto está muy bien cuando el modo del bonding es tal que unos interfaces están activos y otros no, que no es el caso del modo 4, 802.3ad o LACP.

    Lo importante es que daba la clave de como evitar eso, el parámetro all_slaves_active. Así, estableciendo ese parámetro a uno se puede hacer un apaño y permitir que los paquetes recibidos por el interfaz eth1 sean admitidos y lleguen como recibidos por el interfaz bond0.

    # echo 1 > /sys/class/net/bond0/bonding/all_slaves_active

    Pero, como he dicho, eso es solo un apaño, ya que el problema de fondo aún está ahí. ¿Y cuál es ese problema? Pues que el bond0 no considera activo el interfaz eth1, pasa de él, como se deduce de lo siguiente:

    # ethtool bond0
    Settings for bond0:
            Supported ports: [ ]
            Supported link modes:   Not reported
            Supported pause frame use: No
            Supports auto-negotiation: No
            Advertised link modes:  Not reported
            Advertised pause frame use: No
            Advertised auto-negotiation: No
            Speed: 10000Mb/s
            Duplex: Full
            Port: Other
            PHYAD: 0
            Transceiver: internal
            Auto-negotiation: off
            Link detected: yes

    El ancho de banda del interfaz es 10.000Mbps, es decir, lo que da un interfaz. Si estuviera utilizando los dos sería 20.000Mbps, como se vió en el estado del LAG en el lado del switch.

    Por tanto el switch ha activado ambos enlaces del LAG (como se ve al recibir tráfico por los dos interfaces en el servidor), pero el servidor solo ha activado uno.

    Mirando el detalle del estado del bonding se ve lo siguiente:

    # cat /proc/net/bonding/bond0
    Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)
    
    Bonding Mode: IEEE 802.3ad Dynamic link aggregation
    Transmit Hash Policy: layer3+4 (1)
    MII Status: up
    MII Polling Interval (ms): 100
    Up Delay (ms): 0
    Down Delay (ms): 0
    
    802.3ad info
    LACP rate: slow
    Min links: 0
    Aggregator selection policy (ad_select): stable
    System priority: 65535
    System MAC address: a0:b6:cf:d0:2d:f8
    Active Aggregator Info:
            Aggregator ID: 1
            Number of ports: 1
            Actor Key: 13
            Partner Key: 1
            Partner Mac Address: 00:00:00:00:00:00
    
    Slave Interface: eth0
    MII Status: up
    Speed: 10000 Mbps
    Duplex: full
    Link Failure Count: 0
    Permanent HW addr: a0:b6:cf:d0:2d:f8
    Slave queue ID: 0
    Aggregator ID: 1
    Actor Churn State: none
    Partner Churn State: churned
    Actor Churned Count: 0
    Partner Churned Count: 1
    details actor lacp pdu:
        system priority: 65535
        system mac address: a0:b6:cf:d0:2d:f8
        port key: 13
        port priority: 255
        port number: 1
        port state: 77
    details partner lacp pdu:
        system priority: 65535
        system mac address: 00:00:00:00:00:00
        oper key: 1
        port priority: 255
        port number: 1
        port state: 1
    
    Slave Interface: eth1
    MII Status: up
    Speed: 10000 Mbps
    Duplex: full
    Link Failure Count: 0
    Permanent HW addr: a0:b6:cf:d0:2d:fa
    Slave queue ID: 0
    Aggregator ID: 2
    Actor Churn State: churned
    Partner Churn State: churned
    Actor Churned Count: 1
    Partner Churned Count: 1
    details actor lacp pdu:
        system priority: 65535
        system mac address: a0:b6:cf:d0:2d:f8
        port key: 13
        port priority: 255
        port number: 2
        port state: 69
    details partner lacp pdu:
        system priority: 65535
        system mac address: 00:00:00:00:00:00
        oper key: 1
        port priority: 255
        port number: 1
        port state: 1

    Una mente avezada no hubiera pasado por alto (al contrario de como hice yo inicialmente) la discordancia en los «Aggregator ID» de ambos interfaces miembros del bonding. Estaba empeñado en que la culpa era de la configuración del bonding pero, preguntándole a Google por qué puede haber diferentes aggregator ID, me dice un par de cosas. En StackExchange ya me confirman algo que no terminaba de interpretar correctamente en la documentación del bonding, y es que los diferentes aggregator ID están destinados a hacer grupos de interfaces separados dentro del bonding, utilizando solo uno de ellos. Esto me hace pensar que, tal vez, el switch esté haciendo algo mal.

    La confirmación de esto la tuve en esta entrada del foro de CentOS, Only 1 NIC used in the bond, ahí se apuntaba a una entrada de un blog en la que se trataba otro síntoma, la MAC 00:00:00:00:00:00 del otro extremo. En esta entrada se remarca en negrita que lo que hay que hacer es comprobar que el port channel está en modo activo (LACP). Así que fui a hacer la comprobación:

    # show port-channel database
    port-channel1
        Last membership update is successful
        4 ports in total, 2 ports up
        First operational port is Ethernet1/1
        Age of the port-channel is 0d:20h:20m:41s
        Time since last bundle is 0d:20h:20m:51s
        Last bundled member is Ethernet1/4
        Ports:   Ethernet1/1    [on] [up]
                 Ethernet1/2    [on] [up] *
                 Ethernet1/3    [on] [down]
                 Ethernet1/4    [on] [down]

     Había supuesto erróneamente que el modo por defecto era LACP, cuando en realidad era ON. En el modo on el switch simplemente añade los puertos al port channel si tienen enlace, sin más. Por tanto para el switch los dos puertos conectados al servidor formaban parte del port channel y, consecuentemente repartía el tráfico de salida entre ellos. Pero como el servidor estaba en modo LACP y no lograba negociar la agregación con este protocolo, asigna cada interfaz a un grupo de agregación distinto y utiliza solo uno de los grupos, formado por un solo interfaz.

    La solución parecía ya al alcance de las manos.

    # configure terminal
    (config)# interface Eth1/1 - 4
    (config-if-range)# no channel-group 1
    (config-if-range)# channel-group 1 mode active
    LACP process needs to be started before configuring active or passive mode

    Resulta que ni siquiera estaba activada la capacidad LACP en el switch. En NX-OS la mayoría de capacidades del switch vienen desactivadas por defecto y hay que activarlas antes de utilizarlas. Activémosla pues y repitamos:

    (config)# feature lacp
    (config)# interface Eth1/1 - 4
    (config-if-range)# channel-group 1 mode active
    (config-if-range)# sh port-channel database
    port-channel1
        Last membership update is successful
        4 ports in total, 0 ports up
        Age of the port-channel is 0d:20h:34m:57s
        Time since last bundle is 0d:00h:00m:48s
        Last bundled member is Ethernet1/1
        Time since last unbundle is 0d:00h:04m:50s
        Last unbundled member is Ethernet1/4
        Ports:   Ethernet1/1    [active ] [up]
                 Ethernet1/2    [active ] [up] *
                 Ethernet1/3    [active ] [down]
                 Ethernet1/4    [active ] [down]
    (config-if-range)# copy running-config startup-config
    [########################################] 100%
    Copy complete, now saving to disk (please wait)...

    Ahora.

    Comprobemos el otro lado:

    # cat /proc/net/bonding/bond0
    Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)
    
    Bonding Mode: IEEE 802.3ad Dynamic link aggregation
    Transmit Hash Policy: layer3+4 (1)
    MII Status: up
    MII Polling Interval (ms): 100
    Up Delay (ms): 0
    Down Delay (ms): 0
    
    802.3ad info
    LACP rate: slow
    Min links: 0
    Aggregator selection policy (ad_select): stable
    System priority: 65535
    System MAC address: a0:b6:cf:d0:2d:f8
    Active Aggregator Info:
            Aggregator ID: 1
            Number of ports: 2
            Actor Key: 13
            Partner Key: 110
            Partner Mac Address: 00:01:02:03:aa:fc
    
    Slave Interface: p4p1
    MII Status: up
    Speed: 10000 Mbps
    Duplex: full
    Link Failure Count: 2
    Permanent HW addr: a0:b6:cf:d0:2d:f8
    Slave queue ID: 0
    Aggregator ID: 1
    Actor Churn State: none
    Partner Churn State: none
    Actor Churned Count: 1
    Partner Churned Count: 2
    details actor lacp pdu:
        system priority: 65535
        system mac address: a0:b6:cf:d0:2d:f8
        port key: 13
        port priority: 255
        port number: 1
        port state: 61
    details partner lacp pdu:
        system priority: 32768
        system mac address: 00:01:02:03:aa:fc
        oper key: 110
        port priority: 32768
        port number: 389
        port state: 61
    
    Slave Interface: p4p2
    MII Status: up
    Speed: 10000 Mbps
    Duplex: full
    Link Failure Count: 2
    Permanent HW addr: a0:b6:cf:d0:2d:fa
    Slave queue ID: 0
    Aggregator ID: 1
    Actor Churn State: none
    Partner Churn State: none
    Actor Churned Count: 2
    Partner Churned Count: 2
    details actor lacp pdu:
        system priority: 65535
        system mac address: a0:b6:cf:d0:2d:f8
        port key: 13
        port priority: 255
        port number: 2
        port state: 61
    details partner lacp pdu:
        system priority: 32768
        system mac address: 00:01:02:03:aa:fc
        oper key: 110
        port priority: 32768
        port number: 385
        port state: 61
    # ethtool bond0
    Settings for bond0:
            Supported ports: [ ]
            Supported link modes:   Not reported
            Supported pause frame use: No
            Supports auto-negotiation: No
            Advertised link modes:  Not reported
            Advertised pause frame use: No
            Advertised auto-negotiation: No
            Speed: 20000Mb/s
            Duplex: Full
            Port: Other
            PHYAD: 0
            Transceiver: internal
            Auto-negotiation: off
            Link detected: yes

    Todo listo, ambos interfaces en el mismo grupo de agregación, el ancho de banda de ambos interfaces agregado al bonding y la MAC del switch detectada.

    ¡El bonding ya no está medio sordo!

    Ya se puede desactivar el apaño del all_slaves_active, el LAG está ya funcionando correctamente (aunque esta configuración no era persistente).

    # echo 0 > /sys/class/net/bond0/bonding/all_slaves_active

    Otras referencias:

    Para entender el significado de los estados de los interfaces del bonding (port state) ver las definiciones AD_STATE_… en el código del fichero bond_3ad.c.

    El estado mostrado en /proc/net/bonding/bond0 es la representación en decimal del resultado de unir (OR) los valores que corresponden al estado del puerto según las definiciones encontradas en dicho código fuente. Es decir, cuando se estableció correctamente el LAG, el estado del bonding era 61 = 0x3d = 0x20+ 0x10 + 0x08 + 0x04 + 0x01 = DISTRIBUTING + COLLECTING + SYNCHRONIZATION + AGGREGATION + LACP_ACTIVITY.

    Antes, cuando el bonding estaba medio sordo, un interfaz del bonding estabe en estado 77 = 0x4d = 0x40 + 0x08 + 0x04 + 0x01 = DEFAULTED + SYNCHRONIZATION + AGGREGATION + LACP_ACTIVITY. El otro puerto estaba en estado 69 = 0x45 = 0x40 + 0x04 + 0x01 = DEFAULTED + AGGREGATION + LACP_ACTIVITY.

  • Instalar Drupal en servidor LAMP

    Este artículo proporciona todos los pasos realizados para instalar Drupal 6 en un equipo Ubuntu. Algunos paquetes no son imprescindibles o pueden sustituirse por otros, pero  con ellos y siguiendo estos pasos se pone en marcha una instalación Drupal.

    Paquetes necesarios

    En primer lugar se instalan los siguientes paquetes:

    sudo apt-get install apache2
    sudo apt-get install mysql-server
    sudo apt-get install php5
    sudo apt-get install php-pear
    sudo apt-get install php5-mysql
    sudo apt-get install phpmyadmin

    Durante la instalación de phpmyadmin hay que seleccionar la configuración automática para su uso con Apache.

    Descargar desde http://drupal.org/project/l10n_install la versión de Drupal 6 con opciones de localización (selección de idioma), hay que elegir la descarga core.

    Configuración de DNS

    En cualquier caso, si se desea tener un sitio concreto para Drupal y no se dispone de un servidor DNS, se debe instalar BIND (el mejor servidor DNS).

    sudo apt-get install bind9

    Pero si se instala un servidor de DNS local, antes de continuar se debe configurar el sistema para utilizarlo en primer lugar. Si se utiliza una configuración estática de red, bastaría con editar el fichero /etc/resolv.conf y añadir en la primera línea lo siguiente:

    nameserver 127.0.0.1

    Si nuestra configuración de red se obtiene por DHCP habrá que modificar la configuración del servidor DHCP para que en primer lugar proporcione la dirección de nuestro equipo. Si no se puede cambiar la configuración del servidor DHCP, o no se desea hacerlo, se puede seguir lo indicado en el artículo Configuración de un servidor DNS distinto al proporcionado por DHCP.

    La configuración del sitio dentro de BIND puede ser bastante sencilla si es suficiente con utilizar nombres como drupal6.localhost. En este caso bastará con añadir al final de /etc/bind/db.local la siguiente línea:

    drupal6 IN    CNAME   localhost.

    Atención al punto al final de la línea, no es un fin de párrafo que se haya colado, hay que ponerlo. Para configuraciones más complejas se puede seguir lo indicado en Configurar servidor DNS BIND con vistas. Es posible que también un día explique como lo tengo yo montado.

    Una vez guardado el cambio se recarga la configuración de BIND y se comprueba que todo funciona:

    sudo service bind9 reload
    ping drupal6.localhost

    Configuración de Apache

    Tras la instalación inicial de Apache el inicio del servicio proporciona el aviso siguiente:

    apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName

    Para resolver este aviso, sin importancia de todas formas, se añade al fichero /etc/apache2/httpd.conf la siguiente línea:

    ServerName localhost

    Ahora se recarga la configuración de Apache y se comprueba que el aviso ha desaparecido:

    sudo service apache2 reload

    También es recomendable habilitar el módulo rewrite de Apache, que permitirá utilizar unas direcciones más prácticas para los distintos recursos del sitio Drupal.

    sudo a2enmod rewrite
    sudo service apache2 restart

    Finalmente, se necesita configurar Apache para que proporcione un contenido específico para el sitio creado, ya que, por el momento, http://localhost/ y http://drupal6.localhost/ corresponden a un mismo sitio en Apache.

    Para hacer las cosas bien se debe crear en /etc/apache2/sites-available un fichero llamado drupal6.localhost con un contenido como el siguiente, suponiendo que los ficheros de Drupal 6 se situarán en /var/www/drupal6:

    <VirtualHost *:80>
      ServerAdmin direccion@email.mia
      DocumentRoot /var/www/drupal6
    
      ServerName drupal6.localhost
      ServerAlias alias.drupal6.localhost
    
      ErrorLog /var/log/apache2/drupal6.localhost-error.log
      AccessLog /var/log/apache2/drupal6.localhost-access.log
    
      <Directory "/var/www/drupal6/">
        php_admin_value memory_limit 512M
        php_admin_value post_max_size 16M
        php_admin_value upload_max_filesize 16M
      </Directory>
    </VirtualHost>

    Tras crear el fichero /etc/apache2/sites-available/drupal6.localhost se debe habilitar su uso creando un enlace simbólico hacia él en /etc/apache2/sites-enabled y recargar la configuración para hacerla efectiva:

    cd /etc/apache2/sites-enabled
    sudo ln -s ../sites-available/drupal6.localhost 001-drupal6
    sudo service apache2 reload

    Configuración de MySQL

    En este momento, Apache está configurado y el sitio http://drupal6.localhost/phpmyadmin está disponible, desde allí, utilizando el usuario root y la contraseña introducida durante la instalación de MySQL, se accede al apartado Privlegios y se crea el usuario drupal6, especificando únicamente la contraseña y la opción para crear una base de datos del mismo nombre sobre la que el usuario tendrá todos los privilegios.

    Instalación de Drupal

    Hay que situar en el directorio /var/www/drupal6 indicado en la configuración de Apache, el contenido del fichero comprimido de Drupal 6.

    En /var/www sólo root tiene permisos de escritura, por lo que es conveniente hacer algo como lo siguiente que nos permita situar allí los ficheros de Drupal con nuestro usuario como propietario, para facilitar las posteriores tareas de mantenimiento:

    cd /var/www
    sudo mkdir drupal
    sudo chown <nuestro_usuario> drupal
    cd drupal
    tar xzvf /<ruta del directorio>/l10n_install-6.x-1.0-beta4-core.tar.gz
    cd ..
    sudo ln -s drupal/drupal-6.22 drupal6

    Ahora ya se puede acceder al sitio Drupal mediante la dirección http://drupal6.localhost/ y comenzar con la instalación de Drupal, para ello se debe conceder permiso de escritura a Apache sobre el directorio sites/default y sobre el fichero sites/default/settings.php, que debe ser una copia del ya existente sites/default/default.settings.php, esto se puede conseguir otorgando permisos de escritura para el grupo otros sobre este directorio y este fichero:

    cd /var/www/drupal6/sites/default
    cp default.settings.php settings.php
    chmod o+w settings.php
    chmod o+w .

    Una vez seleccionado el idioma de la instalación, introducidos los datos de la base de datos y del sitio web a crear, se deben restaurar los permisos originales sobre sites/default y sites/default/settings.php para evitar riesgos de seguridad.

    cd /var/www/drupal6/sites/default
    chmod o-w settings.php
    chmod o-w .

    Configuración de Drupal

    La siguiente tarea es ponerse a trabajar ya sobre el sitio Drupal creado. Para ello lo más habitual es comenzar a habilitar módulos instalados con Drupal pero aún no activos e instalar módulos y temas adicionales de terceros disponibles desde el sitio oficial de Drupal.

    Sin entrar en detalles, se exponen a continuación algunos módulos de Drupal a habilitar y otros adicionales a instalar. Esta selección no sirve a ningún propósito concreto, es simplemente un conjunto de módulos que aportan ciertas funciones que no entraré a detallar. Puede haber mejores opciones y, desde luego, no serán todos los indicados para cualquier usuario. Lo que sí será cierto para todos es que se deben crear los directorios sites/all/modules y sites/all/themes, y descomprimir allí los módulos y temas respectivamente que se descarguen.

    Módulos core habilitados:

    • Blog
    • Contact
    • Forum
    • Search
    • Statistics
    • Upload

    Módulos adicionales instalados: