Mikrotik RouterOS en Docker con Qemu

¡Buen día a todos! En este artículo quiero hablar sobre un proyecto OpenSource llamado Docker RouterOS , fue creado originalmente como un campo de pruebas para pruebas de integración y nada más, pero con el tiempo, a pedido de los usuarios, se agregaron una serie de mejoras que amplían la gama de capacidades.


Hablaré sobre los motivos de la aparición del proyecto, sus iteraciones iniciales, así como sobre los problemas que tuve que enfrentar.


Continúa debajo del corte.


¿Para qué?


Y esta es la pregunta correcta, quizás valga la pena comenzar con ella, en general hace un par de años comencé un proyecto de una biblioteca PHP para trabajar con RouterOS a través de la API (si al público le gusta esta publicación, el artículo sobre la biblioteca PHP no tardará mucho), como se muestra práctica, para lograr un funcionamiento estable de la biblioteca en diferentes versiones de RouterOS, es muy útil tener pruebas.


Dado que es correcto verificar la operación correcta, como el inicio de sesión o el análisis correcto de la matriz de datos, en la implementación actual de la API del cliente, es una tarea no trivial tomar una decisión en lugar de escribir varias decisiones para interceptar solicitudes y sustituir respuestas para ejecutar pruebas en hardware en vivo.


La versión inicial de las pruebas se llevó a cabo en el enrutador de mi casa, y todo estaría bien, pero algunas pruebas cambiaron algunas configuraciones importantes del enrutador, lo que a menudo condujo a un descontento doméstico y a Internet inactivo, mientras que otras pruebas requerían una versión anterior de RouterOS, para no revertir el sistema operativo debido a de esta.


Y un día estaba cansado de eso, y comencé a buscar una solución al problema.


Podemos decir que fue el momento en que la idea de un determinado entorno virtual que podría iniciarse, por ejemplo en VirtualBox, se instaló en mis pensamientos e hizo algo bueno con él, sin amenazar con romper algo nuevamente.


Cloud Hosted Router , Mikrotik. CHR, , - "" . , CHR VDI/VMDK/OVA/etc. , RouterOS, .


, , 6.42 ( 6.44).


, 6.43 RouterOS API, , , .


VirtualBox , .


?


, .


?


Travis-CI, , VirtualBox Travis-CI , Travis "" .


… Docker!


?


Docker , , .


, " RouterOS Docker ?", QEMU, PC .


QEMU // , headless , Docker .


RouterOS QEMU - , , API.


image, Alpine Linux.


Version 0


:


Dockerfile
FROM alpine:3.8

RUN mkdir /routeros
WORKDIR /routeros
ADD [".", "/routeros"]

RUN apk add --no-cache --update netcat-openbsd qemu-x86_64 qemu-system-x86_64 \
 && wget "https://download.mikrotik.com/routeros/6.42.7/chr-6.42.7.vdi"

ENTRYPOINT ["/routeros/entrypoint.sh"]

WORKDIR , mkdir .


Dockerfile , alpine 3.8, , Mikrotik.


entrypoint.sh
#!/bin/sh

qemu-system-x86_64 \
    -vnc 0.0.0.0:0 \
    -m 256 \
    -hda /routeros/chr-6.42.7.vdi \
    -device e1000,netdev=net0 \
    -netdev user,id=net0,hostfwd=tcp::22-:22,hostfwd=tcp::23-:23,hostfwd=tcp::8728-:8728,hostfwd=tcp::8729-:8729

Entrypoint , , 256 , VNC 5900 , , .


, Docker, , . , , QEMU, Docker .


hostfwd , Docker , , .


Version 1


, URL , .


Dockerfile
FROM alpine:3.8

ENV ROUTEROS_VERSON="6.42.7"
ENV ROUTEROS_IMAGE="chr-$ROUTEROS_VERSON.vdi"
ENV ROUTEROS_PATH="https://download.mikrotik.com/routeros/$ROUTEROS_VERSON/$ROUTEROS_IMAGE"

RUN mkdir /routeros
WORKDIR /routeros
ADD [".", "/routeros"]

RUN apk add --no-cache --update netcat-openbsd qemu-x86_64 qemu-system-x86_64 \
 && echo ">>> $ROUTEROS_PATH" \
 && if [ ! -e "$ROUTEROS_IMAGE" ]; then wget "$ROUTEROS_PATH"; fi

# For access via VNC
EXPOSE 5900

# Default ports of RouterOS
EXPOSE 21
EXPOSE 22
EXPOSE 23
EXPOSE 80
EXPOSE 443
EXPOSE 8291
EXPOSE 8728
EXPOSE 8729

ENTRYPOINT ["/routeros/entrypoint.sh"]

EXPOS , best practice .


Dockerfile, , GitHub Docker Hub.


, Dockerfile , crontab.


cron.sh
#!/bin/bash

# Cron fix
cd "$(dirname $0)"

function getTarballs
{
    curl https://mikrotik.com/download/archive -o - 2>/dev/null | \
        grep -i vdi | \
        awk -F\" '{print $2}' | \
        sed 's:.*/::' | \
        sort -V
}

function getTag
{
    echo "$1" | sed -r 's/chr\-(.*)\.vdi/\1/gi'
}

function checkTag
{
    git rev-list "$1" 2>/dev/null
}

getTarballs | while read line; do
    tag=`getTag "$line"`
    echo ">>> $line >>> $tag"

    if [ "x$(checkTag "$tag")" == "x" ]
        then

            url="https://download.mikrotik.com/routeros/$tag/chr-$tag.vdi"
            if curl --output /dev/null --silent --head --fail "$url"; then
                echo ">>> URL exists: $url"
                sed -r "s/(ROUTEROS_VERSON=\")(.*)(\")/\1$tag\3/g" -i Dockerfile
                git commit -m "Release of RouterOS changed to $tag" -a
                git push
                git tag "$tag"
                git push --tags
            else
                echo ">>> URL don't exist: $url"
            fi

        else
            echo ">>> Tag $tag has been already created"
    fi

done

, , .


Travis-CI, , GitHub.


Version 2


, , , , RouterOS ICMP ( ) .


hostfwd, .


Qemu Docker, TAP eth0.


Debian, Alpine, , multistage . KVM, QEMU, .


VPS KVM, - KVM in KVM, Docker RouterOS KVM QEMU .


Dockerfile :


Dockerfile
FROM alpine:3.11

# For access via VNC
EXPOSE 5900

# Default ports of RouterOS
EXPOSE 21 22 23 80 443 8291 8728 8729

# Different VPN services
EXPOSE 50 51 500/udp 4500/udp 1194/tcp 1194/udp 1701 1723

# Change work dir (it will also create this folder if is not exist)
WORKDIR /routeros

# Install dependencies
RUN set -xe \
 && apk add --no-cache --update \
    netcat-openbsd qemu-x86_64 qemu-system-x86_64 \
    busybox-extras iproute2 iputils \
    bridge-utils iptables jq bash python3

# Environments which may be change
ENV ROUTEROS_VERSON="6.46.5"
ENV ROUTEROS_IMAGE="chr-$ROUTEROS_VERSON.vdi"
ENV ROUTEROS_PATH="https://download.mikrotik.com/routeros/$ROUTEROS_VERSON/$ROUTEROS_IMAGE"

# Download VDI image from remote site
RUN wget "$ROUTEROS_PATH" -O "/routeros/$ROUTEROS_IMAGE"

# Copy script to routeros folder
ADD ["./scripts", "/routeros"]

ENTRYPOINT ["/routeros/entrypoint.sh"]

best practice.


, , , , :


  • python3 — , udhcpd,
  • jq — ip addr -json
  • netcat-openbsd — ,

entrypoint :


entrypoint.sh
#!/bin/sh

###
###         ,
###      ,  
###    .
###

# Generate udhcpd configuration
/routeros/generate-dhcpd-conf.py $QEMU_BRIDGE > $DHCPD_CONF_FILE

# Get name of default interface
default=`ip -json route show | jq -r '.[] | select(.dst == "default") | .dev'`

# Finally, start udhcpd server
udhcpd -I $DUMMY_DHCPD_IP -f $DHCPD_CONF_FILE &

# And run the VM!
exec qemu-system-x86_64 \
    -nographic -serial mon:stdio \
    -vnc 0.0.0.0:0 \
    -m 256 \
    -nic tap,id=qemu0,script=$QEMU_IFUP,downscript=$QEMU_IFDOWN \
    "$@" \
    -hda $ROUTEROS_IMAGE

, , TAP . Docker RouterOS, RouterOS .


, udhcpd DNS ( 127.0.0.11) Docker Compose.


?


  • RouterOS Docker
  • , API Travis-CI
  • images RouterOS

, , . Docker Host RouterOS.


- ( ).


?



, udhcpd python - , bash.



, .



VDI RouterOS, Docker . , , RouterOS Linux Kernel , RouterOS .


Docker Host , , .



, 2010 , , LOR ON^W^W^W . Docker RouterOS , read-only mode .


, , , , , .


, , .




All Articles