Netwatch
Netwatch
Section titled “Netwatch”Netwatch monitors the state of hosts on the network. For each monitored host you specify a probe type, check interval, and scripts to run when the host state changes. The primary use is executing arbitrary console commands on state transitions — making it suitable for failover automation, alerting, and conditional network management.
Netwatch was expanded significantly in RouterOS 7.4. Prior versions only supported the simple (ICMP-only) probe. Entries created before upgrading retain the simple type for backward compatibility.
Overview
Section titled “Overview”Netwatch periodically probes specified hosts and tracks their availability. When a host transitions between up and down, Netwatch executes the configured script. Use cases include:
- WAN failover: switch default routes when an upstream gateway fails
- Service monitoring: detect when a critical TCP port or HTTP endpoint becomes unavailable
- Alerting: send email or log entries on state changes
Sub-menu
Section titled “Sub-menu”/tool/netwatch
Configuration
Section titled “Configuration”Adding a Netwatch Entry
Section titled “Adding a Netwatch Entry”Monitor a host using ICMP (ping-style probes):
/tool/netwatch add host=8.8.8.8 type=icmp interval=30sMonitor a TCP port:
/tool/netwatch add host=192.168.1.100 type=tcp-conn port=22 interval=1mMonitor an HTTP endpoint:
/tool/netwatch add host=10.0.0.1 type=http-get port=80 interval=1mViewing Status
Section titled “Viewing Status”/tool/netwatch printExample output:
Flags: X - disabled # NAME HOST TYPE SINCE STATUS 0 wan-gateway 203.0.113.1 icmp mar/22/2026 up 1 web-service 10.0.0.1 http-get mar/22/2026 downProperties
Section titled “Properties”| Property | Default | Description |
|---|---|---|
| host | — | IP address (IPv4, IPv6, or IPv6 link-local). Supports VRF: ip@vrf |
| type | simple | Probe type: icmp, tcp-conn, http-get, https-get, or simple |
| interval | 10s | Time between probes |
| timeout | 3s | Maximum time to wait for a probe response |
| up-script | — | Script body or name to execute when status changes to up |
| down-script | — | Script body or name to execute when status changes to down |
| unknown-script | — | Script executed when status transitions to unknown (e.g. on first run before any probe completes, or when disabled and re-enabled) |
| test-script | — | Script executed after every probe, regardless of status change |
| name | — | Optional name for the Netwatch entry |
| comment | — | Human-readable description |
| disabled | no | Disable this entry without removing it |
| start-delay | 0s | Delay before the first probe after Netwatch starts or the router boots. Use to avoid false alarms during boot when upstream connectivity is not yet ready |
Probe Types
Section titled “Probe Types”ICMP Probe (type=icmp)
Section titled “ICMP Probe (type=icmp)”Sends a series of ICMP Echo Requests (ping) per interval and evaluates RTT and packet loss against configurable thresholds. This is the most detailed probe type and provides rich statistics for use in scripts.
/tool/netwatch add host=8.8.8.8 type=icmp interval=30sICMP Options
Section titled “ICMP Options”| Property | Default | Description |
|---|---|---|
| packet-count | 10 | ICMP packets sent per probe cycle |
| packet-interval | 50ms | Delay between packets within a probe cycle |
| packet-size | 54 | Total IP packet size (bytes) |
| thr-max | 1s | RTT-max threshold — probe fails if any packet exceeds this |
| thr-avg | 100ms | RTT-avg threshold — probe fails if average RTT exceeds this |
| thr-stdev | 250ms | RTT standard deviation threshold |
| thr-jitter | 1s | Jitter threshold |
| thr-loss-count | 0 | Packet loss threshold (count) |
| thr-loss-percent | 0 | Packet loss threshold (percent) |
ICMP Status Variables
Section titled “ICMP Status Variables”| Variable | Description |
|---|---|
| sent-count | ICMP packets sent in last probe cycle |
| response-count | Valid ICMP responses received |
| thr-loss-count | Lost packet count |
| thr-loss-percent | Lost packet percentage |
| thr-avg | Mean round-trip time |
| thr-max | Maximum round-trip time |
| thr-stdev | Round-trip time standard deviation |
| thr-jitter | Jitter value |
Simple Probe (type=simple)
Section titled “Simple Probe (type=simple)”A simplified ICMP probe retained for backward compatibility with RouterOS 6 Netwatch entries. It supports fewer options and statistics than the icmp type. Prefer type=icmp for new configurations.
TCP Probe (type=tcp-conn)
Section titled “TCP Probe (type=tcp-conn)”Attempts a full TCP three-way handshake to verify that a service is accepting connections.
/tool/netwatch add host=10.0.0.1 type=tcp-conn port=443 interval=1mTCP Options
Section titled “TCP Options”| Property | Default | Description |
|---|---|---|
| port | 80 | TCP destination port |
Pass/fail: the probe passes when the TCP connection is established. Connection refused, timeout, or RST causes a fail.
HTTP Probe (type=http-get)
Section titled “HTTP Probe (type=http-get)”Issues an HTTP GET request and validates the response code against a configurable range. Available in RouterOS 7.4+.
/tool/netwatch add host=10.0.0.1 type=http-get port=80 interval=1mHTTP Options
Section titled “HTTP Options”| Property | Default | Description |
|---|---|---|
| port | 80 | TCP port for the HTTP connection |
| http-code-min | 100 | Minimum acceptable HTTP response code |
| http-code-max | 299 | Maximum acceptable HTTP response code |
| thr-http-time | 10s | Response time threshold — probe fails if exceeded |
A response code in the range [http-code-min, http-code-max] is a pass. Any code outside that range, a connection failure, or exceeding thr-http-time is a fail.
HTTP Status Variables
Section titled “HTTP Status Variables”| Variable | Description |
|---|---|
| http-status-code | HTTP response code received (e.g. 200, 404) |
HTTPS Probe (type=https-get)
Section titled “HTTPS Probe (type=https-get)”Identical to the HTTP probe but establishes a TLS connection first. Use for monitoring HTTPS endpoints.
/tool/netwatch add host=1.1.1.1 type=https-get port=443 interval=1mThe same http-code-min, http-code-max, thr-http-time, and http-status-code options and variables apply.
Scripts
Section titled “Scripts”Netwatch executes scripts on status transitions. Scripts can be defined as inline code or as a reference to a named entry in /system/script.
Inline Scripts
Section titled “Inline Scripts”Inline scripts are set directly on the netwatch entry:
/tool/netwatch add host=8.8.8.8 type=icmp interval=30s \ up-script=":log info \"WAN gateway is UP\"" \ down-script=":log warning \"WAN gateway is DOWN\""Named Scripts
Section titled “Named Scripts”For longer scripts, define them in /system/script and reference them by name:
/system/script add name=wan-down source={ :log warning "WAN gateway DOWN - switching to backup" /ip/route set [find where comment="primary-wan"] disabled=yes /ip/route set [find where comment="backup-wan"] disabled=no}
/system/script add name=wan-up source={ :log info "WAN gateway UP - restoring primary route" /ip/route set [find where comment="primary-wan"] disabled=no /ip/route set [find where comment="backup-wan"] disabled=yes}
/tool/netwatch add host=203.0.113.1 type=icmp interval=20s \ down-script=wan-down \ up-script=wan-upScript Variables
Section titled “Script Variables”Scripts have access to probe statistics. Variables with hyphens in their names must be quoted in RouterOS scripting syntax.
Generic Variables (All Probe Types)
Section titled “Generic Variables (All Probe Types)”| Variable | Description |
|---|---|
| $host | Monitored host address |
| $type | Probe type |
| $status | Current status: up or down |
| $since | Timestamp of last status change |
| $“done-tests” | Total probes completed |
| $“failed-tests” | Consecutive failed probes |
ICMP Variables
Section titled “ICMP Variables”| Variable | Description |
|---|---|
| $“sent-count” | Packets sent in last cycle |
| $“response-count” | Packets received |
| $“thr-loss-count” | Lost packet count |
| $“thr-loss-percent” | Packet loss percentage |
| $“thr-avg” | Average RTT |
| $“thr-max” | Maximum RTT |
HTTP/HTTPS Variables
Section titled “HTTP/HTTPS Variables”| Variable | Description |
|---|---|
| $“http-status-code” | HTTP response status code |
Test Script
Section titled “Test Script”The test-script runs after every probe, whether or not the status changed. Use it to log metrics or update external state continuously:
/tool/netwatch set [find where host=8.8.8.8] \ test-script=":log debug (\"RTT avg=\" . \$\"thr-avg\")"Logging
Section titled “Logging”Netwatch automatically writes to the system log on state changes:
- info level: Probe identification and state transition (OK→fail or fail→OK)
- debug level: Full probe statistics and configuration
To view Netwatch log entries:
/log print where topics~"info" message~"netwatch"You can also filter for a specific host:
/log print where message~"8.8.8.8"Example output:
08:03:26 script,info Ping to 8.8.8.8 successful08:10:47 netwatch,info 8.8.8.8: OK -> FAILSending Alerts via Email
Section titled “Sending Alerts via Email”To send email notifications on state changes, configure /tool/e-mail first, then call it from a script:
/system/script add name=alert-wan-down source={ :local subject "ALERT: WAN gateway unreachable" :local body ("Host " . $host . " has been down since " . $since) :log warning $subject}
/tool/netwatch set [find where comment="primary-wan"] down-script=alert-wan-downAlerting Configurations
Section titled “Alerting Configurations”Netwatch scripts can integrate with a variety of notification systems. All examples below assume the Netwatch entry already has down-script and up-script set to the named scripts.
Email Notifications
Section titled “Email Notifications”Configure the email tool first, then reference it from a Netwatch script:
/tool/e-mail set server=smtp.example.com port=587 \ tls=starttls
/system/script add name=notify-down source={ :local subject ("ALERT: " . $host . " is DOWN") :local body ("Host: " . $host . "\nStatus: DOWN\nSince: " . $since \ . "\nFailed probes: " . $"failed-tests")}
/system/script add name=notify-up source={ :local subject ("RESOLVED: " . $host . " is UP") :local body ("Host: " . $host . "\nStatus: UP\nSince: " . $since)}
/tool/netwatch set [find where host=203.0.113.1] \ down-script=notify-down up-script=notify-upTelegram Bot Notifications
Section titled “Telegram Bot Notifications”Send alerts to a Telegram chat using /tool/fetch with the Telegram Bot API. Replace YOUR_BOT_TOKEN and YOUR_CHAT_ID with your actual values.
/system/script add name=telegram-down source={ :local botToken "YOUR_BOT_TOKEN" :local chatId "YOUR_CHAT_ID" :local msg ("\xF0\x9F\x94\xB4 HOST DOWN\nHost: " . $host \ . "\nSince: " . $since \ . "\nFailed probes: " . $"failed-tests") /tool/fetch url=("https://api.telegram.org/bot" . $botToken \ . "/sendMessage") \ http-method=post \ http-header-field="Content-Type: application/json" \ http-data=("{\"chat_id\":\"" . $chatId . "\",\"text\":\"" . $msg . "\"}") \ output=none}
/system/script add name=telegram-up source={ :local botToken "YOUR_BOT_TOKEN" :local chatId "YOUR_CHAT_ID" :local msg ("\xE2\x9C\x85 HOST UP\nHost: " . $host \ . "\nRecovered: " . $since) /tool/fetch url=("https://api.telegram.org/bot" . $botToken \ . "/sendMessage") \ http-method=post \ http-header-field="Content-Type: application/json" \ http-data=("{\"chat_id\":\"" . $chatId . "\",\"text\":\"" . $msg . "\"}") \ output=none}
/tool/netwatch set [find where host=203.0.113.1] \ down-script=telegram-down up-script=telegram-upHTTP Webhook Notifications
Section titled “HTTP Webhook Notifications”POST a JSON payload to any webhook endpoint (Slack, ntfy.sh, custom systems):
/system/script add name=webhook-down source={ :local webhookUrl "https://hooks.example.com/services/XXXX/YYYY/ZZZZ" :local payload ("{\"text\":\"HOST DOWN: " . $host . " since " . $since . "\"}") /tool/fetch url=$webhookUrl http-method=post \ http-header-field="Content-Type: application/json" \ http-data=$payload output=none}For ntfy.sh or a self-hosted ntfy instance:
/system/script add name=ntfy-down source={ :local topic "my-router-alerts" /tool/fetch url=("https://ntfy.sh/" . $topic) \ http-method=post \ http-header-field="Title: Host Down" \ http-data=("Host " . $host . " is unreachable since " . $since) \ output=none}Logging Only (No External Dependency)
Section titled “Logging Only (No External Dependency)”When external services are unavailable or unnecessary, write structured log entries:
/system/script add name=log-down source={ :log warning ("NETWATCH DOWN host=" . $host . " since=" . $since \ . " failed=" . $"failed-tests")}
/system/script add name=log-up source={ :log info ("NETWATCH UP host=" . $host . " recovered=" . $since)}Filter these entries later:
/log print where message~"NETWATCH"Suppressing Alerts on Boot
Section titled “Suppressing Alerts on Boot”Avoid false alerts while the router is establishing connectivity after a reboot. Use start-delay to hold off the first probe:
/tool/netwatch set [find where host=203.0.113.1] start-delay=60sThis delays the first probe by 60 seconds, giving PPPoE, DHCP, or BGP sessions time to come up before Netwatch begins evaluating host reachability.
Practical Example: WAN Failover
Section titled “Practical Example: WAN Failover”This example monitors a primary WAN gateway. When it becomes unreachable, Netwatch disables the primary default route and enables a backup. When the gateway recovers, traffic automatically returns to the primary path.
Assume:
- Primary WAN: interface
ether1, gateway203.0.113.1 - Backup WAN: interface
ether2, gateway198.51.100.1 - Both routes exist in the routing table with comments for easy identification
Step 1: Add the routes
/ip/route add dst-address=0.0.0.0/0 gateway=203.0.113.1 comment=primary-wan distance=1/ip/route add dst-address=0.0.0.0/0 gateway=198.51.100.1 comment=backup-wan distance=2 disabled=yesStep 2: Create the failover scripts
/system/script add name=wan-failover-down source={ :log warning "Primary WAN DOWN - activating backup route" /ip/route set [find where comment="primary-wan"] disabled=yes /ip/route set [find where comment="backup-wan"] disabled=no :log info "Backup WAN route is now active"}
/system/script add name=wan-failover-up source={ :log info "Primary WAN UP - restoring primary route" /ip/route set [find where comment="backup-wan"] disabled=yes /ip/route set [find where comment="primary-wan"] disabled=no :log info "Primary WAN route restored"}Step 3: Configure Netwatch to monitor the primary gateway
/tool/netwatch add \ name=primary-wan-gw \ host=203.0.113.1 \ type=icmp \ interval=10s \ timeout=3s \ thr-loss-percent=50 \ down-script=wan-failover-down \ up-script=wan-failover-up \ comment="Primary WAN gateway health check"Step 4: Verify
/tool/netwatch print/log print where message~"WAN"Behavior
Section titled “Behavior”| Event | Action |
|---|---|
| Primary gateway packet loss exceeds 50% | down-script runs, backup route activates |
| Primary gateway becomes reachable again | up-script runs, primary route restores |
| Each probe cycle | Status and timestamps visible in /tool/netwatch print |
Using Routing Distances Instead of Disabling Routes
Section titled “Using Routing Distances Instead of Disabling Routes”An alternative approach keeps both routes active at all times and uses Netwatch scripts to change the distance value. The backup route is always present in the routing table; the scripts make it preferred by temporarily giving it a lower distance than the primary.
Step 1: Add both routes — primary preferred by default
/ip/route add dst-address=0.0.0.0/0 gateway=203.0.113.1 comment=primary-wan distance=1/ip/route add dst-address=0.0.0.0/0 gateway=198.51.100.1 comment=backup-wan distance=10Step 2: Create scripts that change the primary route’s distance
/system/script add name=wan-dist-down source={ :log warning "Primary WAN DOWN - raising primary route distance" /ip/route set [find where comment="primary-wan"] distance=20 :log info "Backup WAN now preferred (distance 10 < 20)"}
/system/script add name=wan-dist-up source={ :log info "Primary WAN UP - restoring primary route distance" /ip/route set [find where comment="primary-wan"] distance=1 :log info "Primary WAN restored to preferred path (distance 1)"}Step 3: Attach scripts to Netwatch
/tool/netwatch add \ name=primary-wan-gw \ host=203.0.113.1 \ type=icmp \ interval=10s \ thr-loss-percent=50 \ down-script=wan-dist-down \ up-script=wan-dist-upBoth routes remain visible in /ip/route print at all times, which makes it easy to inspect the current failover state without checking whether a route is disabled. The disable/enable approach (above) is equivalent in function; the distance approach is preferred when you want both paths visible for monitoring or when using tools that enumerate active routes.
Troubleshooting
Section titled “Troubleshooting”Host Always Shows Down
Section titled “Host Always Shows Down”- Verify the host IP is correct:
/ping 203.0.113.1 - Check firewall rules — ICMP may be blocked on the target or a transit device
- For TCP probes, verify the service is listening on the specified port
- Increase
timeoutfor hosts with high latency - Confirm routing to the target exists:
/ip/route print where active=yes
Scripts Not Executing
Section titled “Scripts Not Executing”- Check the script name is spelled correctly:
/system/script print - View script execution errors:
/log print where topics~"script" - Verify the netwatch entry has the script assigned:
/tool/netwatch print detail - Test the script manually:
/system/script run wan-failover-down
False Positives (Flapping)
Section titled “False Positives (Flapping)”- Increase
intervalto reduce sensitivity to momentary packet loss - Raise
thr-loss-percentthreshold for ICMP probes — require sustained loss before declaring down - Increase
timeoutto allow more time for slow responses - Use
type=tcp-conntargeting a specific service port rather than ICMP, which may be rate-limited
High CPU Usage
Section titled “High CPU Usage”- Reduce the number of monitored entries
- Increase
interval— frequent probes add measurable load on busy routers - Reduce
packet-countfor ICMP probes to send fewer packets per cycle
Related Commands
Section titled “Related Commands”/tool/ping— Manual connectivity test/tool/traceroute— Path analysis and hop latency/system/script— Script management/ip/route— Routing table management/tool/e-mail— Email notification configuration/log/print— View system log