A tiny scriptable CLI client/wrapper for MikroTik RouterOS REST API, for manipulating IPv4/IPv6 firewall address lists. Can be used standalone or as an automated action for your IDS/firewall/honeypot. Written in Zig.
Appends an IP address to a RouterOS /ip or /ipv6 /firewall/address-list for use in firewall filters/dns or etc.
Options:
-a, --address (REQUIRED) IP address to append to address-list.
-r, --router (REQUIRED*) Firewall/router hostname or IP. May also be set
via environment variable $MICROMIKRO_ROUTER
-l, --address-list Name of address-list (default: 'zigwang')
-c, --comment Comment (printable ascii <= 127). (default: "")
-t, --timeout Timeout - i.e. 4h or 00:04:00 (default: 4h)
-e, --auth (REQUIRED*) Base64-encoded http basic auth string (i.e.
result of `echo -n "user:pass" | base64`). May also be set
via environment variable $MICROMIKRO_AUTH
-u, --user Username of service account on firewall. If this arg is
specified, a dialog (kdialog or stdin) will be spawned to
prompt for password. Can only be used in an interactive
shell - not scriptable. Recommended to pass `--auth` instead.
-p, --port Port, in case of REST API on non-standard port. Optional.
-x, --proxy HTTP(S) proxy. This option takes precedence over any proxies
found in $HTTP_PROXY/$HTTPS_PROXY env vars (i.e. --proxy ->
environment -> none). Optional.
-P, --ignore-system-proxy Ignore $HTTP_PROXY/$HTTPS_PROXY environment variables. Might
be useful for testing or odd networks.
-I, --insecure Use plaintext http (no tls) (not recommended). Only for
testing; be mindful that without TLS, you'll be sending
RouterOS credentials, with write access to your firewall, in
plaintext across the network. Do not use this option if the
RouterOS host is not link-local. *See RouterOS wiki for help
with certificates.
-6, --ipv6 Target IPv6 firewall (i.e. call
`/ipv6/firewall/address-list` endpoint as opposed to
`/ip/firewall/address-list`). Use this option if `--address`
is a v6 addr, thought that's not exactly what the option
means; the v4 firewall does not accept a v6 addr. I have
chosen to not detect/choose automatically, in favor of explicitness.
--dry-run Dry run. Don't send request to RouterOS host; instead, print
some info to stderr about what *would* have been sent.
--ignore-config Ignore config - don't read options from config file OR
environment vars. Mostly for development; CLI args will
always override config anyways.
--no-newline Don't append trailing newline to output. May be useful in scripts.
--help print help information
--version print version information
-a, --address| The IP you want to add to the address-list. RouterOS will also accept a DNS name, which it will resolve on its own using whatever DNS is configured for its own queries.-r, --router| DNS name or IP addr of RouterOS host. (Can also set in static config)--author--user| Either of these two auth options may be used, OR auth can be set in config (see below).--authexpects the base64-encoded (or not)user:passsubstring of a http basic auth header (rfc7617). Easy way to get this value:echo -n "username:password" | base64. If--useris passed instead, you'll be prompted interactively for a password via either kdialog (if available and in a graphical environment) or a stdin reader. (thus--usershouldn't be used in scripts).- Recommended to also include
-l, --address-list,-t, --timeout, and-c, --comment. If not included, some defaults will be used, which may or may not suit your preferences. (TODO: Allow these to be configured in conf file)
The RouterOS host address (-r/--router) and auth creds (--auth) can also be configured in $XDG_CONFIG_HOME/micro-mikro-client/.env.json, or via environment variables (MICROMIKRO_AUTH and MICROMIKRO_ROUTER).
Program also respects existing $HTTP_PROXY + $HTTPS_PROXY environment variables and will use them if found.
The RouterOS host's TLS cert must be trusted by the host running the program, otherwise you will need to use -I/--insecure (no TLS). Supports TLS v1.2 via stdlib's std.http.Client.
mkcertis useful for testing certs. If for some reason you haven't configured TLS on your RouterOS host, then you really need to do so anyways if you're enabling the APIs and/or web interface.
If you have configured your auth string and RouterOS hostname in static config, you only need to pass -a/--address:
micro-mikro-client -a 10.20.30.40Append an address 10.0.10.1 to an IPv4 address-list named badips, timeout 4 hours, RouterOS host at 192.168.88.1:
micro-mikro-client \
-a 10.0.10.1 \
-r 192.168.88.1 \
-t 4h \
--address-list "badips" \
--comment "testing" \
--auth "dXNlcjpwd2Q="Same as above, but append an IPv6 addr to an IPv6 address-list:
micro-mikro-client \
-6 \
-a 2001:db8::bad:add \
-r 192.168.88.1 \
-t 4h \
--address-list "badips" \
--auth "dXNlcjpwd2Q="Add own public IP addr to an address list:
micro-mikro-client -a $(curl https://ip.mepley.net) --address-list "self-public" -t 4h --comment "Automated" Encode a raw auth str via base64:
micro-mikro-client -6 -a 2001:db8::bad:add:2 -r 2001:db8::1 -l "example-list" --auth $(echo -n "user:pass" | base64)In many cases the program will catch and encode an un-encoded auth str, but it performs a naive check that won't catch everything. Therefore I recommend encoding it.
Some options can be configured statically in $XDG_CONFIG_HOME/micro-mikro-client/.env.json, which is read at runtime; see .env.json.default for example config.
Command line options override static config.
zig build -Doptimize=ReleaseFast
Or, for specific target triples:
zig build -Doptimize=ReleaseSmall -Dcpu=znver5 -Dtarget=x86_64-linux-gnu- For Extreme Networks ap3825i (Freescale p1020) running OpenWRT (haven't tested on it yet, but it builds):
zig build -Dtarget=powerpc-linux-musl -Doptimize=ReleaseSmall(see since 2015 OpenWRT is based on musl libc)
- zli (note: there are currently several different libs named ZLI to be found, for similar purposes).
Optional:
kdialog- If doing interactive auth, andkdialogis available, it will be used to prompt user for pw.
- RouterOS will accept an IPv4 address to add to an IPv6 address-list, but not vice versa. If the API responds with "xxx is not a valid DNS name", check your
--addressvalue. - To b64-encode your creds, you can use
echo -n "user:pass" | base64in a bash shell. - Lots of
@branchHint(.likely)/@branchHint(.unlikely)are used throughout the code, particularly around validation flows- because you're passing valid parameter values, right? ;) - http client works fine with RouterOS's TLS v1.2, but seemingly only by domain name and not IP. Not sure whether issue is with RouterOS or http.Client, or on my part.
TODO: this
Any pull requests are welcome, but maybe open an issue before putting your time into it. Expect spontaneous breaking changes.
For some low-hanging fruit, search the code for comments beginning with TODO or see TODO.md.