Mikrotik RouterOS no Docker com Qemu

Bom Dia a todos! Neste artigo, quero falar sobre um projeto OpenSource chamado Docker RouterOS , que foi originalmente criado como um campo de testes para testes de integração e nada mais, mas com o tempo, a pedido dos usuários, foram adicionadas várias melhorias que expandem o leque de recursos.


Vou falar sobre os motivos da aparência do projeto, suas iterações iniciais, bem como sobre os problemas que tive que enfrentar.


Continua sob o corte.


Pelo que?


E essa é a pergunta certa, talvez valha a pena começar com isso. Em geral, há alguns anos atrás, iniciei um projeto de uma biblioteca PHP para trabalhar com o RouterOS por meio da API (se o público gostar deste post, o artigo sobre a biblioteca PHP não demorará muito), como mostrado Na prática, para obter uma operação estável da biblioteca em diferentes versões do RouterOS, é muito útil fazer testes.


Como é correto verificar a operação correta, como o login ou a análise correta da matriz de dados, na implementação atual da API do cliente, é uma tarefa não trivial tomar uma decisão em vez de escrever várias decisões para interceptar solicitações e substituir respostas para executar testes em hardware ativo.


A versão inicial dos testes foi realizada no meu roteador doméstico, e tudo ficaria bem, mas alguns testes alteraram algumas configurações importantes do roteador, o que muitas vezes levou a Internet inoperante e descontentamento doméstico, enquanto outros testes exigiram uma versão mais antiga do RouterOS, para não reverter o SO devido a disto.


E um dia eu estava cansado disso e comecei a procurar uma solução para o problema.


Podemos dizer que foi o momento exato em que a idéia de um determinado ambiente virtual que poderia ser lançado, digamos no VirtualBox, se estabeleceu em meus pensamentos e fez algo de bom com ele, sem ameaçar quebrar algo novamente.


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