12 ธันวาคม 2567

openssl generate CSR

rsa:2048

openssl req -new -newkey rsa:2048 -nodes \
  -keyout domain.tld.key \
  -out domain.tld.csr \
  -subj "/C=TH/ST=Bangkok/O=Organization/OU=IT/CN=www.domain.tld"
 

rsa:2048 with SAN

openssl req -new -newkey rsa:2048 -nodes \
  -keyout domain.tld.key \
  -out domain.tld.csr \
  -subj "/C=TH/ST=Bangkok/O=Organization/OU=IT/CN=www.domain.tld"  \
  -addext "subjectAltName = DNS:www.domain2.tld,DNS:www.domain3.tld"
 

P-256 (ECC)

openssl req -new -newkey ec:<(openssl ecparam -name prime256v1) -nodes \
  -keyout domain.tld.key \
  -out domain.tld.csr \
  -subj "/C=TH/ST=Bangkok/O=Organization/OU=IT/CN=www.domain.tld
 

P-256 (ECC) with SAN

openssl req -new -newkey ec:<(openssl ecparam -name prime256v1) -nodes \
  -keyout domain.tld.key \
  -out domain.tld.csr \
  -subj "/C=TH/ST=Bangkok/O=Organization/OU=IT/CN=www.domain.tld" \
  -addext "subjectAltName = DNS:www.domain2.tld,DNS:www.domain3.tld"
 
 
C = Country Name (2 letter code)
ST = State or Province Name
O = Organization Name
OU = Organizational Unit
CN = Common Name

02 ธันวาคม 2567

mikrotk wol script

 # Define variables
:local serverIP "192.168.1.100"  # Replace with the server's IP address
:local macAddress "AA:BB:CC:DD:EE:FF"  # Replace with the server's MAC address
:local interface "ether1"  # Replace with the appropriate interface

# Check if the server is reachable
:if ([/ping $serverIP count=3 interval=1] = 0) do={
    # If the server is unreachable, send a WoL packet
    /tool wol mac=$macAddress interface=$interface
    :log info "WoL packet sent to $macAddress"
} else={
    :log info "Server $serverIP is already online"
}


Script by ChatGPT

12 ตุลาคม 2567

local DOH DOT with coredns

# Corefile
.:53{
    forward . tls://1.1.1.1 tls://1.0.0.1 {
        tls_servername cloudflare-dns.com
    }
}
https://.:443 {
    tls /etc/coredns/certs/domain.tld.crt /etc/coredns/certs/domain.tld.key
    forward . 127.0.0.1
}
tls://.:853 {
    tls /etc/coredns/certs/domain.tld.crt /etc/coredns/certs/domain.tld.key
    forward . 127.0.0.1
}


$ docker run --rm -d --name coredns \
    -p 443:443/tcp -p 853:853/tcp \
    -v $PWD/Corefile:/etc/coredns/Corefile \
    -v $PWD/domain.tld.crt:/etc/coredns/certs/domain.tld.crt \
    -v $PWD/domain.tld.key:/etc/coredns/certs/domain.tld.key \
    coredns/coredns:latest \
    -conf /etc/coredns/Corefile

 

 https://coredns.io/plugins/tls/

local DOH DOT with adguard/dnsproxy

$ docker run --rm -d --name dnsproxy \
-p 53:53/udp -p 53:53/tcp -p 443:443/tcp -p 853:853/tcp \
-v $PWD/domain.tld.crt:/opt/dnsproxy/domain.tld.crt \
-v $PWD/domain.tld.key:/opt/dnsproxy/domain.tld.key \
adguard/dnsproxy:latest \
-u https://dns.adguard.com/dns-query -b 1.1.1.1:53 \
--https-port=443 --tls-port=853 \
--tls-crt=/opt/dnsproxy/domain.tld.crt \
--tls-key=/opt/dnsproxy/domain.tld.key


# Add -p 0 if you also want to disable plain-DNS handling and make dnsproxy only serve DoH with Basic Auth checking.

$ docker run --rm -d --name dnsproxy \
-p 443:443/tcp -p 853:853/tcp \
-v $PWD/domain.tld.crt:/opt/dnsproxy/domain.tld.crt \
-v $PWD/domain.tld.key:/opt/dnsproxy/domain.tld.key \
adguard/dnsproxy:latest \
-u https://dns.adguard.com/dns-query -b 1.1.1.1:53 \
--https-port=443 --tls-port=853 \
--tls-crt=/opt/dnsproxy/domain.tld.crt \
--tls-key=/opt/dnsproxy/domain.tld.key \
-p 0

https://hub.docker.com/r/adguard/dnsproxy
https://github.com/AdguardTeam/dnsproxy

05 กันยายน 2567

Running erisamoe/cloudflared on mikrotik container with 56MB tmpfs

Testing hardware
- hAP ax lite
- hAP ax2

/interface veth
add address=10.0.0.20/24 gateway=10.0.0.1 name=cf-tunnel

/interface bridge port
add bridge=br-lan interface=cf-tunnel
 
/container envs
add name=cf-tunnel key=TUNNEL_TOKEN  value=XXX

/disk
add slot=tmpfs tmpfs-max-size=56M type=tmpfs

/container config
set registry-url=https://registry-1.docker.io tmpdir=tmpfs

/system script
add name=addCloudflared source=":delay 20s\
    \n/container remove [find tag~\"cloudflared\"]\
    \n:delay 5s\
    \n/container add remote-image=erisamoe/cloudflared:latest interface=cf-tunnel envlist=cf-tunnel cmd=\"tunnel run\" logging=yes root-dir=tmpfs\
    \n:delay 10s\
    \nwhile ([/container get [find tag~\"cloudflare\"] status] != \"running\") do={\
    \n    :delay 10s\
    \n    /container start [find tag~\"cloudflared\"]\
    \n}"

add name=restartCloudflared source=\
    "/container stop [find tag~\"cloudflared\"]\
    \nwhile ([/container get [find tag~\"cloudflare\"] status] != \"running\") do={\
    \n    :delay 3s\
    \n    /container start [find tag~\"cloudflared\"]\
    \n}"
    
/system scheduler
add name=startCloudflare on-event=addCloudflared start-time=startup

/system/script/run restartCloudflared

Running official cloudflared on mikrotik container with 128MB tmpfs (amd64 / amd64)

Testing hardware
- hAP ax² 

/interface veth
add address=10.0.0.20/24 gateway=10.0.0.1 name=cf-tunnel

/interface bridge port
add bridge=br-lan interface=cf-tunnel

/disk
add slot=tmpfs tmpfs-max-size=128M type=tmpfs

/container config
set registry-url=https://registry-1.docker.io tmpdir=tmpfs

/system script
add name=addCloudflared source=":delay 20s\
    \n/container remove [find tag~\"cloudflared\"]\
    \n:delay 5s\
    \n/container add remote-image=cloudflare/cloudflared root-dir=tmpfs interface=cf-tunnel logging=yes cmd=\"tunnel --no-autoupdate run --token XXX\"\
    \n:delay 30s\
    \nwhile ([/container get [find tag~\"cloudflare\"] status] != \"running\") do={\
    \n    :delay 10s\
    \n    /container start [find tag~\"cloudflared\"]\
    \n}"

/system scheduler
add name=startCloudflare on-event=addCloudflared start-time=startup

15 สิงหาคม 2567

Running cloudflared tunnel with alpine container on mikrotik

Support arm, arm64, amd64
 
Testing hardware
- hAP ax lite
- hAP ax² 


/container/add interface=veth-cf-tunnel remote-image=alpine cmd="sleep infinity" start-on-boot=yes logging=yes

/container/start number=0

/container/shell number=0

# apk add --no-cache ca-certificates curl && curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm -o /usr/local/bin/cloudflared && chmod +x /usr/local/bin/cloudflared && apk del curl ca-certificates && rm -rf /var/cache/apk/* /tmp/* /var/lib/apt/lists/* /usr/share/man /usr/share/doc /usr/share/doc-base

# exit

/container/stop number=0

/container/set numbers=0 cmd="cloudflared tunnel --no-autoupdate run --token XXX"

/container/start number=0
 
 
Note : select binary depend on your architecture
- https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm
- https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64
- https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64

31 กรกฎาคม 2567

Mikrotik CHR on debian with qemu-kvm

sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst libvirt-daemon
sudo apt install cpu-checker vim unzip

sudo vi /etc/network/interfaces

iface enp1s0 inet manual

auto vmbr0
iface vmbr0 inet dhcp
        bridge-ports enp1s0
        bridge-stp off
        bridge-fd 0
        bridge_maxwait 0

auto vmbr1
iface vmbr1 inet static
        address 10.0.0.20/24
        bridge-ports none
        bridge-stp off
        bridge-fd 0
        bridge_maxwait 0
  
sudo systemctl restart networking

wget https://download.mikrotik.com/routeros/7.15.3/chr-7.15.3.img.zip
unzip chr-7.15.3.img.zip

sudo mv chr-7.15.3.img /var/lib/libvirt/images/

sudo virt-install \
--name mikrotik \
--ram 512 \
--disk path=/var/lib/libvirt/images/chr-7.15.3.img,format=raw \
--vcpus 1 \
--os-variant debian10 \
--network bridge=vmbr0 \
--network bridge=vmbr1 \
--graphics none \
--console pty,target_type=serial \
--import

sudo virsh autostart mikrotik

sudo virsh console mikrotik
sudo virsh reset mikrotik
sudo virsh reboot mikrotik
sudo virsh start mikrotik
sudo virsh shutdown mikrotik
 

ref : https://reintech.io/blog/installing-using-kvm-virtualization-debian-12

22 มิถุนายน 2567

Mikrotik RouterOS donwload script

Script download latest RouterOS (Main Package and Extra Package)
for architectures
- x86
- arm64
- arm
- mipsbe
- mmips
- ppc
- smips

and check existing local file before download

https://github.com/leakung/getRouterOS

17 มิถุนายน 2567

Mikrotik script monitor wireguard connection and reconnect with new listen port

wireguard name : wg1
port range : 13232 - 13239

/system script
add dont-require-permissions=no name=checkWireguard owner=admin source=":local wgName wg1;\r\
    \n:local newPort [:rndstr length=1 from=\"23456789\"];\r\
    \n:local newPort (\"1323\".\$newPort);\r\
    \n\r\
    \n:if ([/interface wireguard get [find name=\$wgName] running] = true) do={\r\
    \n\r\
    \n  :local pingResult [/ping count=1 10.10.10.1];\r\
    \n\r\
    \n  :if (\$pingResult = 0) do={\r\
    \n\r\
    \n    :log warning \"\$wgName connection lost. Changing listen port...\";\r\
    \n\r\
    \n    /interface wireguard set [find name=\$wgName] disabled=yes\r\
    \n    /interface wireguard set [find name=\$wgName] listen-port=\$newPort;\r\
    \n    /interface wireguard set [find name=\$wgName] disabled=no\r\
    \n\r\
    \n    :local currentPort [/interface wireguard get [find name=\$wgName] listen-port];\r\
    \n    :log warning \"WireGuard \$wgName listen port changed to \$currentPort\";\r\
    \n\r\
    \n  }\r\
    \n  \r\
    \n}"

/system scheduler
add interval=1m name=checkWireguard on-event=checkWireguard start-time=startup

15 มิถุนายน 2567

Cloudflare Tunnel docker compose

docker-compose.yml
services:
  cloudflared:
    image: cloudflare/cloudflared
    container_name: cloudflared
    restart: unless-stopped
    command: tunnel run
    environment:
      - TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
    network_mode: host

.env
CLOUDFLARE_TUNNEL_TOKEN=XXXX


git clone https://github.com/leakung/cf-compose cloudflare-tunnel

18 พฤษภาคม 2567

mikrotik script for new device

- set dhcp client for ether1
- set bridge lan for the rest
- assign random private ip for bridge lan
- set dhcp server for bridge lan
- set srcnat masquerade all interface
- set ntp client
- set quad9 dns

save script to newdevice.rsc
upload file and import newdevice.rsc

---- start script ----
/ip dhcp-client
add interface=ether1 use-peer-dns=no use-peer-ntp=no

/interface bridge
add name=br-lan

/interface list
add name=LAN

:foreach i in=[/interface find name!="ether1" && name!="lo"] do={
    :local interfaceName [/interface get $i name]
    /interface list member
    add interface=$interfaceName list=LAN
}

/interface bridge port
add bridge=br-lan interface=LAN

/ipv6 settings
set disable-ipv6=yes forward=no

:local thirdOctet ([ :rndnum from=0 to=255 ])
:local ipAddress ("192.168." . $thirdOctet . ".1/24")

/ip address add address=$ipAddress interface=br-lan

:local poolName "dhcp_pool0"
:local dhcpServerName "dhcp1"

/ip pool
add name=$poolName ranges=("192.168." . $thirdOctet . ".2-192.168." . $thirdOctet . ".254")

/ip dhcp-server
add name=$dhcpServerName interface=br-lan address-pool=$poolName lease-time=1d disabled=no

/ip dhcp-server network
add address=("192.168." . $thirdOctet . ".0/24") gateway=("192.168." . $thirdOctet . ".1") dns-server=("192.168." . $thirdOctet . ".1")

/ip firewall nat
add action=masquerade chain=srcnat

/ip cloud
set update-time=no

/system ntp client
set enabled=yes

/system ntp client servers
add address=0.pool.ntp.org
add address=clock.nectec.or.th

/ip dns
set allow-remote-requests=yes servers=9.9.9.9,149.112.112.112

/ip service
set telnet disabled=yes
set ftp disabled=yes
set api disabled=yes
set api-ssl disabled=yes
 
/ip ssh
set host-key-type=ed25519
ip ssh set strong-crypto=yes

/system routerboard settings
set auto-upgrade=yes

/system clock
set time-zone-autodetect=no time-zone-name=Asia/Bangkok

---- end script ----

30 มีนาคม 2567

Mikrotik container + observium

/interface veth
add address=10.0.0.11/24 gateway=10.0.0.1 name=veth-mariadb
add address=10.0.0.12/24 gateway=10.0.0.1 name=veth-observium

/interface bridge port
add bridge=Docker interface=veth-mariadb
add bridge=Docker interface=veth-observium

/container envs
add name=mariadb key=MYSQL_ROOT_PASSWORD value=root_pass
add name=mariadb key=MYSQL_USER value=observium
add name=mariadb key=MYSQL_PASSWORD value=db_pass
add name=mariadb key=MYSQL_DATABASE value=observium
add name=mariadb key=TZ value=Asia/Bangkok
add name=observium key=OBSERVIUM_ADMIN_USER value=admin
add name=observium key=OBSERVIUM_ADMIN_PASS value=admin
add name=observium key=OBSERVIUM_DB_HOST value=10.0.0.11
add name=observium key=OBSERVIUM_DB_NAME value=observium
add name=observium key=OBSERVIUM_DB_USER value=observium
add name=observium key=OBSERVIUM_DB_PASS value=db_pass
add name=observium key=OBSERVIUM_BASE_URL value=http://10.0.0.12
add name=observium key=TZ value=Asia/Bangkok

/container mounts
add name=mariadb_data src=/mariadb/data dst=/var/lib/mysql
add name=observium_rrd src=/observium_log/rrd dst=/opt/observium/rrd
add name=observium_log src=/observium_log/log dst=/opt/observium/logs

/container
add interface=veth-mariadb mounts=mariadb_data envlist=mariadb remote-image=mariadb:latest dns=10.0.0.1 start-on-boot=yes logging=yes
add interface=veth-observium mounts=observium_rrd,observium_log envlist=observium remote-image=mbixtech/observium:latest dns=10.0.0.1 start-on-boot=yes logging=yes

25 มีนาคม 2567

Pi-hole Mikrotik container

/system/device-mode/update container=yes

/container config
set registry-url=https://registry-1.docker.io

/interface bridge
add name=Docker

/ip address
add address=10.0.0.1/24 interface=Docker

/ip firewall nat
add chain=srcnat src-address=10.0.0.0/24 action=masquerade

/interface veth
add address=10.0.0.12/24 gateway=10.0.0.1 name=veth-pihole

/interface bridge port
add bridge=Docker interface=veth-pihole

/container envs
add key=TZ name=pihole_envs value=Asia/Bangkok
add key=WEBPASSWORD name=pihole_envs value=mypassword
add key=DNSMASQ_USER name=pihole_envs value=root

/container mounts
add dst=/etc/pihole name=pihole-etc src=/pihole/etc-pihole
add dst=/etc/dnsmasq.d name=pihole-dnsmasq src=/pihole/etc-dnsmasq.d

/container
add interface=veth-pihole remote-image=pihole/pihole:latest envlist=pihole_envs mounts=pihole-etc,pihole-dnsmasq start-on-boot=yes logging=yes

22 มีนาคม 2567

cloudflare docker


container_name: tomcat9-jdk8
network name: tomcat9-jdk8_default
map ports: 8980:8080

Quick Tunnels

# host network

docker run --rm --network host --name cloudflared cloudflare/cloudflared:latest tunnel --url http://127.0.0.1:8980

# container network

docker run --rm --network tomcat9-jdk8_default --name cloudflared cloudflare/cloudflared:latest tunnel --url http://tomcat9-jdk8:8080


Cloudflare account

# host network

public hostname url http://127.0.0.1:8980
 
docker run -d --rm --network host --name cloudflared cloudflare/cloudflared:latest tunnel --no-autoupdate run --token XXXX


# container network

public hostname url http://tomcat9-jdk8:8080

docker run -d --rm --network tomcat9-jdk8_default --name cloudflared cloudflare/cloudflared:latest tunnel --no-autoupdate run --token XXXX
 
 

# docker compose

public hostname url http://tomcat9-jdk8:8080
 
services:

  tomcat9-jdk8:
    container_name: tomcat9-jdk8
    ...

  cloudflared:
    image: cloudflare/cloudflared
    container_name: cloudflared
    restart: unless-stopped
    command: tunnel run
    environment:
      - TUNNEL_TOKEN=XXXXX
 

11 มีนาคม 2567

acme.sh with alias challenge and cloudflare api

issue domain : domain.tld
alias domain : alias-domain.tld

- set CNAME
_acme-challenge.domain.tld CNAME _acme-challenge.alias-domain.tld

- cloudflare token for edit dns zone alias-dmain.tld


acme.sh command

Issue cert

export CF_Token="xxx"

acme.sh --issue --server letsencrypt -k ec-256 --dns dns_cf --challenge-alias alias-domain.tld  -d domain.tld --home /home/user/docker/nginx/acme.sh


Install cert
acme.sh --install-cert -d domain.tld  --key-file /home/user/docker/nginx/etc-nginx-certs/domain.tld.key --fullchain-file /home/user/docker/nginx/etc-nginx-certs/domain.tld.crt --reloadcmd "docker exec nginx /etc/init.d/nginx reload"  --home /home/user/docker/nginx/acme.sh

# renew cert
acme.sh --cron --home /home/user/docker/nginx/acme.sh 

acme.sh docker

Issue cert
docker run --rm -it -e CF_Token="xxx" -v /home/user/docker/nginx/acme.sh:/acme.sh neilpang/acme.sh --issue --server letsencrypt -k ec-256 --dns dns_cf --challenge-alias alias-domain.tld -d domain.tld

Install cert
docker run --rm -it -v /home/user/docker/nginx/acme.sh:/acme.sh -v /home/user/docker/nginx/etc-nginx-certs:/etc/nginx/cert neilpang/acme.sh --install-cert -d domain.tld --key-file /etc/nginx/certs/domain.tld.key --fullchain-file /etc/nginx/certs/domain.tld.crt && docker exec -it nginx /etc/init.d/nginx restart

Renew cert
docker run --rm -it -v /home/user/docker/nginx/acme.sh:/acme.sh -v /home/user/docker/nginx/etc-nginx-certs:/etc/nginx/certs neilpang/acme.sh --cron && docker exec -it nginx /etc/init.d/nginx restart

18 กุมภาพันธ์ 2567

Mikrotik persist route to wireguard server for dynamic wan

Persist route to wireguard server for dynamic wan in case of setting default route via wireguard
 
 
DHCP client script
 
:if ($bound=1) do={
    :ip route remove [/ip route find comment="route-wireguard-wan"]
    :ip route add distance=5 gateway=$"gateway-address" dst-address="1.2.3.4/32" scope=30  target-scope=10  comment="route-wireguard-wan"
} else={
    :ip route remove [/ip route find comment="route-wireguard-wan"]
}

14 กุมภาพันธ์ 2567

Change ubuntu source list to kku mirror

Change ubuntu source list to kku mirror


sed -i "s/th.archive.ubuntu.com/mirror.kku.ac.th/" /etc/apt/sources.list 

or

sed -i "s/archive.ubuntu.com/mirror.kku.ac.th/" /etc/apt/sources.list