Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ name: Lint

env:
HADOLINT_VERSION: v1.17.2
SHELLCHECK_OPTS: -e SC1008 -s bash

on:
pull_request:
Expand Down Expand Up @@ -50,6 +49,8 @@ jobs:

- name: Run linter
uses: ludeeus/[email protected]
env:
SHELLCHECK_OPTS: -e SC1008 -s bash -x
with:
# Names of scripts with custom shebangs that the action would not
# discover on its own:
Expand Down
6 changes: 6 additions & 0 deletions openthread_border_router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 2.16.6

- Fix and improve NAT64 firewall rules
- Enable recovery mechanism from "radio tx timeout" errors for beta
- Narrow non-firewall forwarding rules to Thread and infrastructure interface

## 2.16.5

- Add `backbone_interface` option to override the network interface used for IPv6 routing.
Expand Down
1 change: 1 addition & 0 deletions openthread_border_router/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ RUN \
-DOT_COAPS=OFF \
-DOT_THREAD_VERSION=1.4 \
-DOT_PROJECT_CONFIG="/usr/src/ot-br-posix/third_party/openthread/repo/openthread-core-ha-config-posix.h" \
-DOT_RCP_RESTORATION_MAX_COUNT=2 \
&& cd /usr/src/ot-br-posix/build/otbr \
&& ninja install

Expand Down
2 changes: 1 addition & 1 deletion openthread_border_router/config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
version: 2.16.5
version: 2.16.6
slug: openthread_border_router
name: OpenThread Border Router
description: OpenThread Border Router add-on
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ else
bashio::log.info "otbr-agent exited with code $e (by signal $2)."
fi

# shellcheck disable=SC1091
# shellcheck source=./openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-common
. /etc/s6-overlay/scripts/otbr-agent-common

ipset_destroy_if_exist()
Expand All @@ -28,34 +28,58 @@ ipset_destroy_if_exist()
done
}

# shellcheck disable=SC2154,SC2086
while ip6tables -C FORWARD -o $thread_if -j $otbr_forward_ingress_chain 2> /dev/null; do
# shellcheck disable=SC2086
ip6tables -D FORWARD -o $thread_if -j $otbr_forward_ingress_chain
while ip6tables -C FORWARD -o "${thread_if}" -j "${otbr_forward_ingress_chain}" 2> /dev/null; do
ip6tables -D FORWARD -o "${thread_if}" -j "${otbr_forward_ingress_chain}"
done

# shellcheck disable=SC2086
if ip6tables -L $otbr_forward_ingress_chain 2> /dev/null; then
ip6tables -w -F $otbr_forward_ingress_chain
ip6tables -w -X $otbr_forward_ingress_chain
if ip6tables -L "${otbr_forward_ingress_chain}" 2> /dev/null; then
ip6tables -w -F "${otbr_forward_ingress_chain}"
ip6tables -w -X "${otbr_forward_ingress_chain}"
fi

ipset_destroy_if_exist otbr-ingress-deny-src
ipset_destroy_if_exist otbr-ingress-deny-src-swap
ipset_destroy_if_exist otbr-ingress-allow-dst
ipset_destroy_if_exist otbr-ingress-allow-dst-swap

# shellcheck disable=SC2154,SC2086
while ip6tables -C FORWARD -i $thread_if -j $otbr_forward_egress_chain 2> /dev/null; do
ip6tables -D FORWARD -i $thread_if -j $otbr_forward_egress_chain
while ip6tables -C FORWARD -i "${thread_if}" -j "${otbr_forward_egress_chain}" 2> /dev/null; do
ip6tables -D FORWARD -i "${thread_if}" -j "${otbr_forward_egress_chain}"
done

# shellcheck disable=SC2086
if ip6tables -L $otbr_forward_egress_chain 2> /dev/null; then
ip6tables -w -F $otbr_forward_egress_chain
ip6tables -w -X $otbr_forward_egress_chain
if ip6tables -L "${otbr_forward_egress_chain}" 2> /dev/null; then
ip6tables -w -F "${otbr_forward_egress_chain}"
ip6tables -w -X "${otbr_forward_egress_chain}"
fi
bashio::log.info "OTBR firewall teardown completed."

# Cleanup non-firewall rules
while ip6tables -C FORWARD -i "${thread_if}" -o "${backbone_if}" -j ACCEPT 2>/dev/null; do
ip6tables -D FORWARD -i "${thread_if}" -o "${backbone_if}" -j ACCEPT
done

while ip6tables -C FORWARD -i "${backbone_if}" -o "${thread_if}" -j ACCEPT 2>/dev/null; do
ip6tables -D FORWARD -i "${backbone_if}" -o "${thread_if}" -j ACCEPT
done
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Persist backbone_if so teardown can remove these FORWARD rules.

finish never initializes backbone_if, so Line 55 and Line 59 end up matching an empty interface and these accepts survive every restart.

🛠️ Suggested fix
# openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run
+printf '%s\n' "${backbone_if}" > /tmp/otbr-backbone-if
# openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish
+backbone_if=""
+if [ -f /tmp/otbr-backbone-if ]; then
+    backbone_if="$(< /tmp/otbr-backbone-if)"
+fi

Wrap the delete loops in an [ -n "${backbone_if}" ] guard and rm -f /tmp/otbr-backbone-if after cleanup.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish`
around lines 54 - 61, finish currently does not load backbone_if before the
ip6tables delete loops, so the FORWARD rules targeting the backbone interface
are never removed; modify finish to read/initialize backbone_if from the
persisted state (e.g. /tmp/otbr-backbone-if) before the delete loops, wrap both
ip6tables -C/-D FORWARD loops that reference backbone_if and thread_if in a
guard that checks [ -n "${backbone_if}" ], and after successfully removing rules
remove the persisted file (rm -f /tmp/otbr-backbone-if) so subsequent restarts
don’t reuse a stale value.


# Remove FORWARD jump(s)
while iptables -C FORWARD -j "${otbr_forward_nat64_chain}" 2>/dev/null; do
iptables -D FORWARD -j "${otbr_forward_nat64_chain}"
done

# Flush and delete chain
if iptables -L "${otbr_forward_nat64_chain}" -n 2>/dev/null; then
iptables -w -F "${otbr_forward_nat64_chain}"
iptables -w -X "${otbr_forward_nat64_chain}"
fi

# Clean mangle and nat rules
while iptables -t mangle -C PREROUTING -i "${thread_if}" -j MARK --set-mark "${otbr_fw_mark}" 2>/dev/null; do
iptables -t mangle -D PREROUTING -i "${thread_if}" -j MARK --set-mark "${otbr_fw_mark}"
done

while iptables -t nat -C POSTROUTING -m mark --mark "${otbr_fw_mark}" -j MASQUERADE 2>/dev/null; do
iptables -t nat -D POSTROUTING -m mark --mark "${otbr_fw_mark}" -j MASQUERADE
done
bashio::log.info "OTBR firewall/NAT64 rules teardown completed."

if test "$e" -ne 0; then
echo "$e" > /run/s6-linux-init-container-results/exitcode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# OpenThread BorderRouter start script
# ==============================================================================

# shellcheck disable=SC1091
# shellcheck source=./openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-common
. /etc/s6-overlay/scripts/otbr-agent-common

declare backbone_if
Expand Down Expand Up @@ -98,43 +98,41 @@ ipset create -exist otbr-ingress-allow-dst-swap hash:net family inet6

if bashio::config.true 'firewall'; then
bashio::log.info "Setup OTBR firewall..."
# shellcheck disable=SC2086,SC2154
ip6tables -N $otbr_forward_ingress_chain
# shellcheck disable=SC2086,SC2154
ip6tables -I FORWARD 1 -o $thread_if -j $otbr_forward_ingress_chain

# shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m pkttype --pkt-type unicast -i ${thread_if} -j DROP
# shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m set --match-set otbr-ingress-deny-src src -j DROP
# shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m set --match-set otbr-ingress-allow-dst dst -j ACCEPT
# shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -m pkttype --pkt-type unicast -j DROP
# shellcheck disable=SC2086
ip6tables -A $otbr_forward_ingress_chain -j ACCEPT

# shellcheck disable=SC2086,SC2154
ip6tables -N $otbr_forward_egress_chain
# shellcheck disable=SC2086
ip6tables -I FORWARD 2 -i $thread_if -j $otbr_forward_egress_chain
# shellcheck disable=SC2086
ip6tables -A $otbr_forward_egress_chain -j ACCEPT

ip6tables -N "${otbr_forward_ingress_chain}"

ip6tables -I FORWARD 1 -o "${thread_if}" -j "${otbr_forward_ingress_chain}"

ip6tables -A "${otbr_forward_ingress_chain}" -m pkttype --pkt-type unicast -i "${thread_if}" -j DROP
ip6tables -A "${otbr_forward_ingress_chain}" -m set --match-set otbr-ingress-deny-src src -j DROP
ip6tables -A "${otbr_forward_ingress_chain}" -m set --match-set otbr-ingress-allow-dst dst -j ACCEPT
ip6tables -A "${otbr_forward_ingress_chain}" -m pkttype --pkt-type unicast -j DROP
ip6tables -A "${otbr_forward_ingress_chain}" -j ACCEPT

ip6tables -N "${otbr_forward_egress_chain}"
ip6tables -I FORWARD 2 -i "${thread_if}" -j "${otbr_forward_egress_chain}"
ip6tables -A "${otbr_forward_egress_chain}" -j ACCEPT
else
# Make sure ip6tables (as used by Docker) allow IP forwarding
ip6tables -P FORWARD ACCEPT
# HAOS 9.3 and earlier (for 9.4 accept is the default so this won't do anything)
ip6tables-legacy -P FORWARD ACCEPT
# Make sure ip6tables allow IP forwarding
ip6tables -A FORWARD -i "${thread_if}" -o "${backbone_if}" -j ACCEPT
ip6tables -A FORWARD -i "${backbone_if}" -o "${thread_if}" -j ACCEPT
fi

if bashio::config.true 'nat64'; then
# shellcheck disable=SC2086
iptables -t mangle -A PREROUTING -i ${thread_if} -j MARK --set-mark 0x1001
iptables -t nat -A POSTROUTING -m mark --mark 0x1001 -j MASQUERADE
# shellcheck disable=SC2086
iptables -t filter -A FORWARD -o ${backbone_if} -j ACCEPT
# shellcheck disable=SC2086
iptables -t filter -A FORWARD -i ${backbone_if} -j ACCEPT
# Mark Thread traffic in mangle
iptables -t mangle -A PREROUTING -i "${thread_if}" -j MARK --set-mark "${otbr_fw_mark}"

# MASQUERADE marked traffic
iptables -t nat -A POSTROUTING -m mark --mark "${otbr_fw_mark}" -j MASQUERADE

# NAT64 forward chain — jump unconditionally, filter inside
iptables -N "${otbr_forward_nat64_chain}"
iptables -I FORWARD 1 -j "${otbr_forward_nat64_chain}"

# Forward marked traffic
iptables -A "${otbr_forward_nat64_chain}" -m mark --mark "${otbr_fw_mark}" -o "${backbone_if}" -j ACCEPT
# Use conntrack to identify return traffic
iptables -A "${otbr_forward_nat64_chain}" -m conntrack --ctstate ESTABLISHED,RELATED -i "${backbone_if}" -o "${thread_if}" -j ACCEPT
fi

otbr_rest_listen="::"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
#!/bin/sh
# shellcheck shell=bash
# shellcheck disable=SC2034

declare thread_if
declare otbr_forward_ingress_chain
declare otbr_forward_egress_chain
declare otbr_forward_nat64_chain
declare otbr_fw_mark
thread_if="wpan0"
otbr_forward_ingress_chain="OTBR_FORWARD_INGRESS"
otbr_forward_egress_chain="OTBR_FORWARD_EGRESS"
otbr_forward_nat64_chain="OTBR_FORWARD_NAT64"
otbr_fw_mark="0x1001"

Loading