0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenWrt Raspberry Pi Zero 2 W (H)

Last updated at Posted at 2025-09-21

:flag_jp: Japanese notation

OpenWrt_icon.png

はじめに

初心者対応構成

検証環境

  • Windows11 バージョン24H2

トピック

USBドングル拡張ボードキット

USBドングル拡張ボードキット.jpg


OpenWrt

OpenWrt Project へようこそ

320.logo.png

仕様

Techdata


The UCI system
LuCI web interface

WHR-300CR.png


情報サイト

URL

Raspberry Pi Zero 2 W


インストール

ファームウェア

デバイス用のOpenWrtカスタムファームウェアをダウンロード

イメージのダウンロード > FACTORY (SQUASHFS) をダウンロード

インストールされたパッケージ、初回起動時のスクリプトのカスタマイズ

インストールされたパッケージ

リリースビルド

base-files bcm27xx-gpu-fw bcm27xx-utils ca-bundle dnsmasq dropbear e2fsprogs firewall4 fstools kmod-fs-vfat kmod-nft-offload kmod-nls-cp437 kmod-nls-iso8859-1 kmod-sound-arm-bcm2835 kmod-sound-core kmod-usb-hid libc libgcc libustream-mbedtls logd mkf2fs mtd netifd nftables odhcp6c odhcpd-ipv6only opkg partx-utils ppp ppp-mod-pppoe procd-ujail uci uclient-fetch urandom-seed cypress-firmware-43430-sdio brcmfmac-nvram-43430-sdio cypress-firmware-43455-sdio brcmfmac-nvram-43455-sdio kmod-brcmfmac wpad-basic-mbedtls kmod-i2c-bcm2835 kmod-spi-bcm2835 kmod-spi-bcm2835-aux iwinfo luci

"snapshot" ビルド

apk-mbedtls base-files bcm27xx-gpu-fw bcm27xx-utils ca-bundle dnsmasq dropbear e2fsprogs firewall4 fstools kmod-fs-vfat kmod-nft-offload kmod-nls-cp437 kmod-nls-iso8859-1 kmod-sound-arm-bcm2835 kmod-sound-core kmod-usb-hid libc libgcc libustream-mbedtls logd mkf2fs mtd netifd nftables odhcp6c odhcpd-ipv6only partx-utils ppp ppp-mod-pppoe procd-ujail uci uclient-fetch urandom-seed cypress-firmware-43430-sdio brcmfmac-nvram-43430-sdio cypress-firmware-43455-sdio brcmfmac-nvram-43455-sdio kmod-brcmfmac wpad-basic-mbedtls kmod-i2c-bcm2835 kmod-spi-bcm2835 kmod-spi-bcm2835-aux iwinfo luci

初回起動時に実行されるスクリプト (uci-defaults)


SDカードサイズの拡張

SDカード初期化

※管理者として実行

diskpart
list disk
select disk 
clean

SDカードサイズの拡張

ファイルシステムの拡張

uci-defaults (setup.sh)
#! /bin/sh
enable_sd_resize="on"
[ -n "${enable_sd_resize}" ] && {
    parted -s /dev/mmcblk0 resizepart 2 100%
}

USB NIC

設定
#! /bin/sh
PKGS="kmod-usb-gadget-eth kmod-usb-dwc2"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
enable_usb_gadget="on"
[ -n "${enable_usb_gadget}" ] && [ -d /boot ] && {
    ! grep -q 'dtoverlay=dwc2' /boot/config.txt && echo 'dtoverlay=dwc2' >> /boot/config.txt
    sed -i 's/rootwait/& modules-load=dwc2,g_ether/' /boot/cmdline.txt
    printf '%s\n%s\n' "dwc2" "g_ether" > /etc/modules.d/99-gadget
    uci add_list network.@device[0].ports='usb0'
    uci commit network
    ifdown usb0 2>/dev/null
    ifup usb0
    modprobe dwc2 2>/dev/null
    modprobe g_ether 2>/dev/null
}

クロックアップ

設定
クロック over_voltage 推奨 備考
1000MHz (標準) 0 ノーマル電圧
1200MHz 2 安定重視
1350MHz 6〜8 高負荷/自己責任

What is config.txt?

#! /bin/sh
OVERCLOCK="1200"
BASE="500"
VOLT="2"

[ -f /boot/config.txt ] && {
  sed -i '/^arm_freq=/d' /boot/config.txt
  sed -i '/^core_freq=/d' /boot/config.txt
  sed -i '/^over_voltage=/d' /boot/config.txt
  cat <<EOF >> /boot/config.txt
arm_freq=${OVERCLOCK}
core_freq=${BASE}
over_voltage=${VOLT}
EOF
sync
}

フラッシュ&インストールシステム

aios.png

ランディングページ

ランディングページ

キッティングツール

デバイス用のOpenWrtカスタムファームウェアをダウンロード

サンプル
#!/bin/sh
cat > "/tmp/openwrt-network-auto-config.sh" << 'SCRIPT_END'
#!/bin/sh
set -eu
API_RESPONSE="$(wget -qO- https://auto-config.site-u.workers.dev/)"
echo "NOTICE=$(echo "$API_RESPONSE" | jsonfilter -e '@.notice')"
echo "IPV4=$(echo "$API_RESPONSE" | jsonfilter -e '@.ipv4')"
echo "IPV6=$(echo "$API_RESPONSE" | jsonfilter -e '@.ipv6')"
echo "COUNTRY=$(echo "$API_RESPONSE" | jsonfilter -e '@.country')"
echo "TIMEZONE=$(echo "$API_RESPONSE" | jsonfilter -e '@.timezone')"
echo "ZONENAME=$(echo "$API_RESPONSE" | jsonfilter -e '@.zonename')"
echo "ISP=$(echo "$API_RESPONSE" | jsonfilter -e '@.isp')"
echo "AS=$(echo "$API_RESPONSE" | jsonfilter -e '@.as')"
echo "REGION_NAME=$(echo "$API_RESPONSE" | jsonfilter -e '@.regionName')"
echo "REGION_CODE=$(echo "$API_RESPONSE" | jsonfilter -e '@.region')"
echo "AFTR_TYPE=$(echo "$API_RESPONSE" | jsonfilter -e '@.aftr.aftrType')"
echo "AFTR_JURISDICTION=$(echo "$API_RESPONSE" | jsonfilter -e '@.aftr.jurisdiction')"
echo "AFTR_IPV6=$(echo "$API_RESPONSE" | jsonfilter -e '@.aftr.aftrIpv6Address')"
echo "MAPE_BR_IPV6=$(echo "$API_RESPONSE" | jsonfilter -e '@.mape.brIpv6Address')"
echo "MAPE_EA_BITS=$(echo "$API_RESPONSE" | jsonfilter -e '@.mape.eaBitLength')"
echo "MAPE_IPV4_PREFIX=$(echo "$API_RESPONSE" | jsonfilter -e '@.mape.ipv4Prefix')"
echo "MAPE_IPV4_PLEN=$(echo "$API_RESPONSE" | jsonfilter -e '@.mape.ipv4PrefixLength')"
echo "MAPE_IPV6_PREFIX=$(echo "$API_RESPONSE" | jsonfilter -e '@.mape.ipv6Prefix')"
echo "MAPE_IPV6_PLEN=$(echo "$API_RESPONSE" | jsonfilter -e '@.mape.ipv6PrefixLength')"
echo "MAPE_PSID_OFFSET=$(echo "$API_RESPONSE" | jsonfilter -e '@.mape.psIdOffset')"
echo "MAPE_PSIDLEN=$(echo "$API_RESPONSE" | jsonfilter -e '@.mape.psidlen')"
SCRIPT_END
sh "/tmp/openwrt-network-auto-config.sh"

コンソールツール

all in one scripts
config software (旧版)

デバイスアクセス

デバイスアクセス(UCI)

パワーシェルでアクセス

PowerShellの開始

  • キー入力:Win+x > a > はい

UCI(SSH)アクセス

powershell:初期設定用
ssh -o StrictHostKeyChecking=no -oHostKeyAlgorithms=+ssh-rsa root@192.168.1.1
  • root@192.168.1.1's password:初期値:パスワード無し
SSHログイン出来ない場合:exclamation:
  • %USERPROFILE%\.ssh\known_hosts ※Windows隠しファイル
powershell
Clear-Content .ssh\known_hosts -Force 

OpenSSHのインストールが無い場合:exclamation: - 機能の確認 ※Windows 10 Fall Creators Update(1709)以降標準搭載 ```powershell:powershell Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*' ``` - 機能のインストール ```powershell:powershell Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 ``` ---

LuCi

ブラウザーでアクセス

初期設定

パスワード

初期値から変更
passwd

Changing password for root
New password:

passwd:入力モード
任意のパスワード

Retype password:

passwd:入力モード
再入力

passwd: password for root changed by root

exit

ホストネーム

ホストネーム(openwrt)を変更
#!/bin/sh
HOSTNAME='openwrt' # デバイス名
uci set system.@system[0].hostname=${HOSTNAME}
uci commit system
/etc/init.d/system reload

タイムゾーン

タイムゾーンを変更
#!/bin/sh
TIMEZONE='JST-9'
ZONENAME='Asia/Tokyo'
uci set system.@system[0].timezone=${TIMEZONE}
uci set system.@system[0].zonename=${ZONENAME}
uci commit system
/etc/init.d/sysntpd restart

NTP

NTPサーバーを変更
#!/bin/sh
POOL='jp'
uci delete system.ntp.server
uci add_list system.ntp.server=0.${POOL}.pool.ntp.org
uci add_list system.ntp.server=1.${POOL}.ppl.ntp.org
uci add_list system.ntp.server=2.${POOL}.pool.ntp.org 
uci add_list system.ntp.server=3.${POOL}.pool.ntp.org
uci set system.ntp.enable_server='1'
uci set system.ntp.use_dhcp='0'
uci set system.ntp.interface='lan'
uci commit system
/etc/init.d/sysntpd restart

SSH

WANからのアクセスを遮断
uci set dropbear.@dropbear[0].Interface='lan'
uci commit dropbear

LED

ネットワークアクセスで点灯点滅
#! /bin/sh
uci add system led
uci set system.@led[-1].name='wan'
uci set system.@led[-1].sysfs='green:status'
uci set system.@led[-1].trigger='netdev'
uci set system.@led[-1].dev='wan'
uci set system.@led[-1].mode='link tx rx'
uci add system led
uci set system.@led[-1].name='br-lan'
uci set system.@led[-1].sysfs='blue:wps'
uci set system.@led[-1].trigger='netdev'
uci set system.@led[-1].dev='br-lan'
uci set system.@led[-1].mode='link tx rx'
uci commit system
/etc/init.d/led reload

パッケージ

母国語サポート

LuCiの言語パッケージをインストール
  • 対応言語検索
#! /bin/sh
PATTERN="luci-i18n-base*"
command -v opkg && opkg update && opkg list $PATTERN
command -v apk  && apk update  && apk search $PATTERN
  • 設定
#! /bin/sh
I18N="ja"
PKGS="luci-i18n-base-${I18N} luci-i18n-firewall-${I18N}"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS

UCI(TTYD)

ブラウザーでUCIにアクセス
#! /bin/sh
I18N="ja"
PKGS="luci-i18n-ttyd-${I18N}"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
uci set ttyd.@ttyd[0].ipv6='1'
uci set ttyd.@ttyd[0].command='/bin/login -f root' #自動ログイン
uci commit ttyd
/etc/init.d/rpcd restart

ファイラー

ブラウザでファイルにアクセス
mkdir -p /tmp/aios && wget -q -O /tmp/aios/install-filebrowser.sh https://raw.githubusercontent.com/site-u2023/aios/main/install-filebrowser.sh && sh /tmp/aios/install-filebrowser.sh
# ポート変更
uci set filebrowser.config.port=9090
# ルートディレクトリ変更  
uci set filebrowser.config.root=/mnt/storage
# ユーザーネーム及びパスワード変更
uci set filebrowser.config.username='root'
uci set filebrowser.config.password='password'
uci commit filebrowser
# 設定確認
uci show filebrowser
# サービス再起動
service filebrowser restart
# 既存DBをリセットしてUCI値で上書きしたいとき
rm /etc/filebrowser/filebrowser.db
service filebrowser restart
  • 使用方法
    filebrowser_main.sh: 自動判定 (インストールまたはリムーブ)
    filebrowser_main.sh install: インストール
    filebrowser_main.sh remove: リムーブ
    filebrowser_main.sh status: 状態確認

WinSCPでファイルにアクセス
#! /bin/sh
PKGS="openssh-sftp-server"
command -v opkg && opkg update && opkg install $PKGS
command -v apk  && apk update  && apk add $PKGS

クライアント設定(Windows)

  • 手動インストール
  • 自動インストール
    • キー入力:Win+x > a > はい
    • 最新版ソフトウェアのインストール
powershell:クライアントPC
$psVersion = $PSVersionTable.PSVersion.Major
$LINKS = Invoke-WebRequest "https://winscp.net/eng/download.php"
$LINKS_VERSION = $LINKS.Links | Where-Object {$_.href -like "*WinSCP-*-Setup.exe*"} | Select-Object -ExpandProperty href
$VERSION = ($LINKS_VERSION -split '/')[-2] -replace "WinSCP-([0-9]+\.[0-9]+\.[0-9]+).*", '$1'
Write-Host "Version to install: $VERSION"
$downloadUrl = "https://jaist.dl.sourceforge.net/project/winscp/WinSCP/$VERSION/WinSCP-$VERSION-Setup.exe?viasf=1"
Write-Host "Downloading from: $downloadUrl"
$ONAMAE = (whoami).Split('\')[1]
$destinationPath = "C:\Users\$ONAMAE\Downloads\WinSCP-$VERSION-Setup.exe"
Invoke-WebRequest -Uri $downloadUrl -OutFile $destinationPath
Write-Host "Installing WinSCP..."
Start-Process -FilePath $destinationPath -ArgumentList "/VERYSILENT /NORESTART" -Wait
Invoke-Expression "C:\Users\$ONAMAE\AppData\Local\Programs\WinSCP\WinSCP.exe"
  • 警告 > 強制的に貼り付け

  • WinSCP設定

    • セッション
      • ホスト名:192.168.1.1
      • ユーザー名:root
      • パスワード:設定したパスワード
      • ログインをクリック

CPU負荷分散

インストール
#! /bin/sh
PKGS="irqbalance"
command -v opkg && opkg update && opkg install $PKGS
command -v apk  && apk update  && apk add $PKGS
uci set irqbalance.irqbalance=irqbalance
uci set irqbalance.irqbalance.enabled='1'
uci commit irqbalance
/etc/init.d/irqbalance start

ネットワーク統計インターフェイス

インストール
#! /bin/sh
I18N="ja"
PKGS="luci-i18n-statistics-${I18N}"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
/etc/init.d/collectd enable
/etc/init.d/rpcd restart
  • プラグイン検索
#! /bin/sh
PATTERN="collectd-mod\*"
command -v opkg && opkg update && opkg list $PATTERN
command -v apk  && apk update  && apk search $PATTERN

追加テーマ

インストール
#! /bin/sh
PKGS="luci-theme-openwrt luci-theme-material"
command -v opkg && opkg update && opkg install $PKGS
command -v apk  && apk update  && apk add $PKGS

AdGuard Home

インストール

オフィシャル版
OpenWrt版

  • インストール及びリムーブ
#!/bin/sh

TMP=/tmp/aios
mkdir -p "$TMP"
cat <<'EOF' > "$TMP"/standalone-blocker-adguardhome.sh
#!/bin/sh

# OpenWrt 19.07+ configuration
# Reference: https://openwrt.org/docs/guide-user/services/dns/adguard-home
#            https://github.com/AdguardTeam/AdGuardHome
# This script file can be used standalone.

SCRIPT_VERSION="2025.08.26-00-00"

# set -ex

REQUIRED_MEM="50" # unit: MB
REQUIRED_FLASH="100" # unit: MB
LAN="${LAN:-br-lan}"
DNS_PORT="${DNS_PORT:-53}"
DNS_BACKUP_PORT="${DNS_BACKUP_PORT:-54}"

NET_ADDR=""
NET_ADDR6_LIST=""
SERVICE_NAME=""
INSTALL_MODE=""
ARCH=""
AGH=""
PACKAGE_MANAGER=""
FAMILY_TYPE=""

check_system() {
  if /etc/AdGuardHome/AdGuardHome --version >/dev/null 2>&1 || /usr/bin/AdGuardHome --version >/dev/null 2>&1; then
    printf "\033[1;33mAdGuard Home is already installed. Exiting.\033[0m\n"
    remove_adguardhome
    exit 0
  fi
  
  printf "\033[1;34mChecking system requirements\033[0m\n"
  
  LAN="$(ubus call network.interface.lan status 2>/dev/null | jsonfilter -e '@.l3_device')"
  if [ -z "$LAN" ]; then
    printf "\033[1;31mLAN interface not found. Aborting.\033[0m\n"
    exit 1
  fi
  
  if command -v opkg >/dev/null 2>&1; then
    PACKAGE_MANAGER="opkg"
  elif command -v apk >/dev/null 2>&1; then
    PACKAGE_MANAGER="apk"
  else
    printf "\033[1;31mNo supported package manager (apk or opkg) found.\033[0m\n"
    printf "\033[1;31mThis script is designed for OpenWrt systems only.\033[0m\n"
    exit 1
  fi
  
  MEM_TOTAL_KB=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)
  MEM_FREE_KB=$(awk '/^MemAvailable:/ {print $2}' /proc/meminfo)
  BUFFERS_KB=$(awk '/^Buffers:/ {print $2}' /proc/meminfo)
  CACHED_KB=$(awk '/^Cached:/ {print $2}' /proc/meminfo)
  if [ -n "$MEM_FREE_KB" ]; then
    MEM_FREE_MB=$((MEM_FREE_KB / 1024))
  else
    MEM_FREE_MB=$(((BUFFERS_KB + CACHED_KB) / 1024))
  fi
  MEM_TOTAL_MB=$((MEM_TOTAL_KB / 1024))
  DF_OUT=$(df -k / | awk 'NR==2 {print $2, $4}')
  FLASH_TOTAL_KB=$(printf '%s\n' "$DF_OUT" | awk '{print $1}')
  FLASH_FREE_KB=$(printf '%s\n' "$DF_OUT" | awk '{print $2}')
  FLASH_FREE_MB=$((FLASH_FREE_KB / 1024))
  FLASH_TOTAL_MB=$((FLASH_TOTAL_KB / 1024))
  
  if [ "$MEM_FREE_MB" -lt "$REQUIRED_MEM" ]; then
    mem_col="1;31"
  else
    mem_col="1;32"
  fi
  if [ "$FLASH_FREE_MB" -lt "$REQUIRED_FLASH" ]; then
    flash_col="1;31"
  else
    flash_col="1;32"
  fi
  
  printf "Memory: Free \033[%sm%s MB\033[0m / Total %s MB\n" \
    "$mem_col" "$MEM_FREE_MB" "$MEM_TOTAL_MB"
  printf "Flash: Free \033[%sm%s MB\033[0m / Total %s MB\n" \
    "$flash_col" "$FLASH_FREE_MB" "$FLASH_TOTAL_MB"
  printf "LAN interface: %s\n" "$LAN"
  printf "Package manager: %s\n" "$PACKAGE_MANAGER"
  
  if [ "$MEM_FREE_MB" -lt "$REQUIRED_MEM" ]; then
    printf "\033[1;31mError: Insufficient memory. At least %sMB RAM is required.\033[0m\n" \
      "$REQUIRED_MEM"
    exit 1
  fi
  if [ "$FLASH_FREE_MB" -lt "$REQUIRED_FLASH" ]; then
    printf "\033[1;31mError: Insufficient flash storage. At least %sMB free space is required.\033[0m\n" \
      "$REQUIRED_FLASH"
    exit 1
  fi
}

install_prompt() {
  printf "\033[1;34mSystem resources are sufficient for AdGuard Home installation. Proceeding with setup.\033[0m\n"

  if [ -n "$1" ]; then
    case "$1" in
      official) INSTALL_MODE="official"; return ;;
      openwrt) INSTALL_MODE="openwrt"; return ;;
      remove) remove_adguardhome ;;
      exit) exit 0 ;;
      *) printf "\033[1;31mWarning: Unrecognized argument '$1'. Proceeding with interactive prompt.\033[0m\n" ;;
    esac
  fi

  while true; do
    printf "[1] Install OpenWrt package\n"
    printf "[2] Install Official binary\n"
    printf "[0] Exit\n"
    printf "Please select (1, 2 or 0): "
    read -r choice

    case "$choice" in
      1|openwrt) INSTALL_MODE="openwrt"; break ;;
      2|official) INSTALL_MODE="official"; break ;;
      0|exit)
        printf "\033[1;33mInstallation cancelled.\033[0m\n"
        exit 0
        ;;
      *) printf "\033[1;31mInvalid choice '$choice'. Please enter 1, 2, or 0.\033[0m\n" ;;
    esac
  done
}

install_cacertificates() {
  case "$PACKAGE_MANAGER" in
    apk)
      apk update >/dev/null 2>&1
      apk add ca-certificates >/dev/null 2>&1
      ;;
    opkg)
      opkg update --verbosity=0 >/dev/null 2>&1
      opkg install --verbosity=0 ca-bundle >/dev/null 2>&1
      ;;
  esac
}

install_openwrt() {
  printf "Installing adguardhome (OpenWrt package)\n"
  
  case "$PACKAGE_MANAGER" in
    apk)
      PKG_VER=$(apk search adguardhome | grep "^adguardhome-" | sed 's/^adguardhome-//' | sed 's/-r[0-9]*$//')
      if [ -n "$PKG_VER" ]; then
        apk add adguardhome || {
          printf "\033[1;31mNetwork error during apk add. Aborting.\033[0m\n"
          exit 1
        }
        printf "\033[1;32madguardhome %s has been installed\033[0m\n" "$PKG_VER"
      else
        printf "\033[1;31mPackage 'adguardhome' not found in apk repository, falling back to official\033[0m\n"
        install_official
      fi
      ;;
    opkg)
      PKG_VER=$(opkg list | grep "^adguardhome " | awk '{print $3}')
      if [ -n "$PKG_VER" ]; then
        opkg install --verbosity=0 adguardhome || {
          printf "\033[1;31mNetwork error during opkg install. Aborting.\033[0m\n"
          exit 1
        }
        printf "\033[1;32madguardhome %s has been installed\033[0m\n" "$PKG_VER"
      else
        printf "\033[1;31mPackage 'adguardhome' not found in opkg repository, falling back to official\033[0m\n"
        install_official
      fi
      ;;
  esac
  
  SERVICE_NAME="adguardhome"
}

install_official() {
  CA="--no-check-certificate"
  URL="https://api.github.com/repos/AdguardTeam/AdGuardHome/releases/latest"
  VER=$( { wget -q -O - "$URL" || wget -q "$CA" -O - "$URL"; } | jsonfilter -e '@.tag_name' )
  [ -n "$VER" ] || { printf "\033[1;31mError: Failed to get AdGuardHome version from GitHub API.\033[0m\n"; exit 1; }
  
  mkdir -p /etc/AdGuardHome
  case "$(uname -m)" in
    aarch64|arm64) ARCH=arm64 ;;
    armv7l)        ARCH=armv7 ;;
    armv6l)        ARCH=armv6 ;;
    armv5l)        ARCH=armv5 ;;
    x86_64|amd64)  ARCH=amd64 ;;
    i386|i686)     ARCH=386 ;;
    mips)          ARCH=mipsle ;;
    mips64)        ARCH=mips64le ;;
    *) printf "Unsupported arch: %s\n" "$(uname -m)"; exit 1 ;;
  esac
  TAR="AdGuardHome_linux_${ARCH}.tar.gz"
  URL2="https://github.com/AdguardTeam/AdGuardHome/releases/download/${VER}/${TAR}"
  DEST="/etc/AdGuardHome/${TAR}"
  
  printf "Downloading AdGuardHome (official binary)\n"
  if ! { wget -q -O "$DEST" "$URL2" || wget -q "$CA" -O "$DEST" "$URL2"; }; then
    printf '\033[1;31mDownload failed. Please check network connection.\033[0m\n'
    exit 1
  fi
  printf "\033[1;32mAdGuardHome %s has been downloaded\033[0m\n" "$VER"
  
  tar -C /etc/ -xzf "/etc/AdGuardHome/${TAR}"
  rm "/etc/AdGuardHome/${TAR}"
  chmod +x /etc/AdGuardHome/AdGuardHome
  SERVICE_NAME="AdGuardHome"
  
  /etc/AdGuardHome/AdGuardHome -s install >/dev/null 2>&1 || {
    printf "\033[1;31mInitialization failed. Check AdGuardHome.yaml and port availability.\033[0m\n"
    exit 1
  }
  chmod 700 /etc/"$SERVICE_NAME"
}

get_iface_addrs() {
  local flag=0
  
  if ip -4 -o addr show dev "$LAN" scope global | grep -q 'inet '; then
    NET_ADDR=$(ip -4 -o addr show dev "$LAN" scope global | awk 'NR==1{sub(/\/.*/,"",$4); print $4}')
    flag=$((flag | 1))
  else
    printf "\033[1;33mWarning: No IPv4 address on %s\033[0m\n" "$LAN"
  fi

  if ip -6 -o addr show dev "$LAN" scope global | grep -q 'inet6 '; then
    NET_ADDR6_LIST=$(ip -6 -o addr show dev "$LAN" scope global | grep -v temporary | awk 'match($4,/^(2|fd|fc)/){sub(/\/.*/,"",$4); print $4;}')
    flag=$((flag | 2))
  else
    printf "\033[1;33mWarning: No IPv6 address on %s\033[0m\n" "$LAN"
  fi

  case $flag in
    3) FAMILY_TYPE=any  ;;
    1) FAMILY_TYPE=ipv4 ;;
    2) FAMILY_TYPE=ipv6 ;;
    *) FAMILY_TYPE=""   ;;
  esac
}

common_config() {
  cp /etc/config/network  /etc/config/network.adguard.bak
  cp /etc/config/dhcp     /etc/config/dhcp.adguard.bak
  cp /etc/config/firewall /etc/config/firewall.adguard.bak
  uci set dhcp.@dnsmasq[0].noresolv="1"
  uci set dhcp.@dnsmasq[0].cachesize="0"
  uci set dhcp.@dnsmasq[0].rebind_protection='0'
  # uci set dhcp.@dnsmasq[0].rebind_protection='1'  # keep enabled
  # uci set dhcp.@dnsmasq[0].rebind_localhost='1'   # protect localhost
  # uci add_list dhcp.@dnsmasq[0].rebind_domain='lan'  # allow internal domain
  uci set dhcp.@dnsmasq[0].port="${DNS_BACKUP_PORT}"
  uci set dhcp.@dnsmasq[0].domain="lan"
  uci set dhcp.@dnsmasq[0].local="/lan/"
  uci set dhcp.@dnsmasq[0].expandhosts="1"
  uci -q del dhcp.@dnsmasq[0].server || true
  uci add_list dhcp.@dnsmasq[0].server="127.0.0.1#${DNS_PORT}"
  uci add_list dhcp.@dnsmasq[0].server="::1#${DNS_PORT}"
  uci -q del dhcp.lan.dhcp_option || true
  uci add_list dhcp.lan.dhcp_option="6,${NET_ADDR}"
  uci -q del dhcp.lan.dhcp_option6 || true
  if [ -n "$NET_ADDR6_LIST" ]; then
    for ip in $NET_ADDR6_LIST; do
      uci add_list dhcp.lan.dhcp_option6="option6:dns=[${ip}]"
    done
  fi
  uci commit dhcp
  /etc/init.d/dnsmasq restart || {
    printf "\033[1;31mFailed to restart dnsmasq\033[0m\n"
    printf "\033[1;31mTo remove AdGuard Home, run:\033[0m\n"
    printf "\033[1;31msh %s/standalone-blocker-adguardhome.sh remove_adguardhome auto\033[0m\n" "$TMP"
    exit 1
  }
  /etc/init.d/odhcpd restart || {
    printf "\033[1;31mFailed to restart odhcpd\033[0m\n"
    printf "\033[1;31mTo remove AdGuard Home, run:\033[0m\n"
    printf "\033[1;31msh %s/standalone-blocker-adguardhome.sh remove_adguardhome auto\033[0m\n" "$TMP"
    exit 1
  }
  /etc/init.d/"$SERVICE_NAME" enable
  /etc/init.d/"$SERVICE_NAME" start
  
  printf "Router IPv4: %s\n" "$NET_ADDR"
  if [ -z "$NET_ADDR6_LIST" ]; then
    printf "\033[1;33mRouter IPv6: none found\033[0m\n"
  else
    printf "Router IPv6: %s\n" "$(echo "$NET_ADDR6_LIST" | tr '\n' ' ')"
  fi
  
  printf "\033[1;32mSystem configuration completed\033[0m\n"
}

common_config_firewall() {
  uci -q delete firewall.@include[0].reload
  uci commit firewall
  
  rule_name="adguardhome_dns_${DNS_PORT}"
  uci -q delete firewall."$rule_name" || true
  if [ -z "$FAMILY_TYPE" ]; then
    printf "\033[1;31mNo valid IP address family detected. Skipping firewall rule setup.\033[0m\n"
    return
  fi
  uci set firewall."$rule_name"=redirect
  uci set firewall."$rule_name".name="AdGuardHome DNS Redirect (${FAMILY_TYPE})"
  uci set firewall."$rule_name".family="$FAMILY_TYPE"
  uci set firewall."$rule_name".src="lan"
  uci set firewall."$rule_name".dest="lan"
  uci add_list firewall."$rule_name".proto="tcp"
  uci add_list firewall."$rule_name".proto="udp"
  uci set firewall."$rule_name".src_dport="$DNS_PORT"
  uci set firewall."$rule_name".dest_port="$DNS_PORT"
  uci set firewall."$rule_name".target="DNAT"
  uci commit firewall
  /etc/init.d/firewall restart || {
    printf "\033[1;31mFailed to restart firewall\033[0m\n"
    printf "\033[1;31mTo remove AdGuard Home, run:\033[0m\n"
    printf "\033[1;31msh %s/standalone-blocker-adguardhome.sh remove_adguardhome auto\033[0m\n" "$TMP"
    exit 1
  }
  
  printf "\033[1;32mFirewall configuration completed\033[0m\n"
}

remove_adguardhome() {
  local auto_confirm="$1"

  printf "\033[1;34mRemoving AdGuard Home\033[0m\n"

  if /etc/AdGuardHome/AdGuardHome --version >/dev/null 2>&1; then
    INSTALL_TYPE="official"; AGH="AdGuardHome"
  elif /usr/bin/AdGuardHome --version >/dev/null 2>&1; then
    INSTALL_TYPE="openwrt"; AGH="adguardhome"
  else
    printf "\033[1;31mAdGuard Home not found\033[0m\n"
    return 1
  fi

  printf "Found AdGuard Home (%s version)\n" "$INSTALL_TYPE"
  
  if [ "$auto_confirm" != "auto" ]; then
    printf "Do you want to remove it? (y/N): "
    read -r confirm
    case "$confirm" in
      [yY]*) ;;
      *) printf "\033[1;33mCancelled\033[0m\n"; return 0 ;;
    esac
  else
    printf "\033[1;33mAuto-removing due to installation error\033[0m\n"
  fi
  
  /etc/init.d/"${AGH}" stop    2>/dev/null || true
  /etc/init.d/"${AGH}" disable 2>/dev/null || true

  if [ "$INSTALL_TYPE" = "official" ]; then
    "/etc/${AGH}/${AGH}" -s uninstall 2>/dev/null || true
  else
    if command -v apk >/dev/null 2>&1; then
      apk del "$AGH" 2>/dev/null || true
    else
      opkg remove --verbosity=0 "$AGH" 2>/dev/null || true
    fi
  fi

  if [ -d "/etc/${AGH}" ] || [ -f "/etc/adguardhome.yaml" ]; then
    if [ "$auto_confirm" != "auto" ]; then
      printf "Do you want to delete the AdGuard Home configuration file(s)? (y/N): "
      read -r cfg
      case "$cfg" in
        [yY]*) rm -rf "/etc/${AGH}" /etc/adguardhome.yaml ;;
      esac
    else
      rm -rf "/etc/${AGH}" /etc/adguardhome.yaml
    fi
  fi

  for cfg in network dhcp firewall; do
    bak="/etc/config/${cfg}.adguard.bak"
    if [ -f "$bak" ]; then
      printf "\033[1;34mRestoring %s configuration\033[0m\n" "$cfg"
      cp "$bak" "/etc/config/${cfg}"
      rm -f "$bak"
    fi
  done

  uci commit network
  uci commit dhcp
  uci commit firewall

  /etc/init.d/dnsmasq restart  || { printf "\033[1;31mFailed to restart dnsmasq\033[0m\n"; exit 1; }
  /etc/init.d/odhcpd restart   || { printf "\033[1;31mFailed to restart odhcpd\033[0m\n"; exit 1; }
  /etc/init.d/firewall restart || { printf "\033[1;31mFailed to restart firewall\033[0m\n"; exit 1; }

  printf "\033[1;32mAdGuard Home has been removed successfully.\033[0m\n"

  if [ "$auto_confirm" != "auto" ]; then
    printf "\033[33mPress any key to reboot.\033[0m\n"
    read -r -n1 -s
    reboot
  else
    printf "\033[1;33mAuto-rebooting\033[0m\n"
    reboot
  fi

  exit 0
}

get_access() {
  local cfg port addr
  if [ -f "/etc/AdGuardHome/AdGuardHome.yaml" ]; then
    cfg="/etc/AdGuardHome/AdGuardHome.yaml"
  elif [ -f "/etc/adguardhome.yaml" ]; then
    cfg="/etc/adguardhome.yaml"
  fi
  if [ -n "$cfg" ]; then
    addr=$(awk '
      $1=="http:" {flag=1; next}
      flag && /^[[:space:]]*address:/ {print $2; exit}
    ' "$cfg" 2>/dev/null)
    port="${addr##*:}"
    [ -z "$port" ] && port=
  fi
  [ -z "$port" ] && port=3000

  if command -v qrencode >/dev/null 2>&1; then
    printf "\033[1;32mWeb interface IPv4: http://${NET_ADDR}:${port}/\033[0m\n"
    printf "http://${NET_ADDR}:${port}/\n" | qrencode -t UTF8 -v 3
    if [ -n "$NET_ADDR6_LIST" ]; then
      set -- $NET_ADDR6_LIST
      printf "\033[1;32mWeb interface IPv6: http://[%s]:%s/\033[0m\n" "$1" "$port"
      printf "http://[%s]:%s/\n" "$1" "$port" | qrencode -t UTF8 -v 3
    fi
  else
    printf "\033[1;32mWeb interface IPv4: http://${NET_ADDR}:${port}/\033[0m\n"
    if [ -n "$NET_ADDR6_LIST" ]; then
      set -- $NET_ADDR6_LIST
      printf "\033[1;32mWeb interface IPv6: http://[%s]:%s/\033[0m\n" "$1" "$port"
    fi
  fi
}

adguardhome_main() {
  check_system
  install_prompt "$@"
  install_cacertificates
  install_"$INSTALL_MODE"
  get_iface_addrs
  common_config
  common_config_firewall
  printf "\n\033[1;32mAdGuard Home installation and configuration completed successfully.\033[0m\n\n"
  get_access
}

adguardhome_main "$@"
EOF
chmod +x "$TMP"/standalone-blocker-adguardhome.sh

sh "$TMP"/standalone-blocker-adguardhome.sh



  • DNS BIND MODE
# Set default bind mode: "loopback" or "gua"
DNS_BIND_MODE="${DNS_BIND_MODE:-loopback}"

common_config() {
  # Option | DNS_BIND_MODE
  #
  # By setting DNS_BIND_MODE, you can switch dnsmasq’s upstream DNS between
  # “loopback” mode (127.0.0.1#53 / ::1#53) and
  # “gua” mode (router’s global IP#53).
  #
  # ・loopback (default)
  #   – dnsmasq → always resolves via local loopback to AdGuard Home
  #   – Ideal for environments where AdGuard Home is bound to localhost only
  #
  # ・gua
  #   – dnsmasq → resolves via the router’s global IPv4/IPv6 addresses
  #   – Useful for MAP-E/DS-Lite/WireGuard tunnels or
  #     direct DNS access from external clients
  #
  # Usage:
  #   export DNS_BIND_MODE="${DNS_BIND_MODE:-loopback}"

  printf "\033[1;34mBacking up configuration files\033[0m\n"
  cp /etc/config/network  /etc/config/network.adguard.bak
  cp /etc/config/dhcp     /etc/config/dhcp.adguard.bak
  cp /etc/config/firewall /etc/config/firewall.adguard.bak

  [ "$INSTALL_MODE" = "official" ] && {
    /etc/AdGuardHome/AdGuardHome -s install >/dev/null 2>&1 || {
      printf "\033[1;31mInitialization failed. Check AdGuardHome.yaml and port availability.\033[0m\n"
      exit 1
    }
  }

  chmod 700 /etc/"$SERVICE_NAME"
  /etc/init.d/"$SERVICE_NAME" enable
  /etc/init.d/"$SERVICE_NAME" start

  uci set dhcp.@dnsmasq[0].noresolv="1"
  uci set dhcp.@dnsmasq[0].cachesize="0"
  uci set dhcp.@dnsmasq[0].rebind_protection='0'

  # uci set dhcp.@dnsmasq[0].rebind_protection='1'  # keep enabled
  # uci set dhcp.@dnsmasq[0].rebind_localhost='1'   # protect localhost
  # uci add_list dhcp.@dnsmasq[0].rebind_domain='lan'  # allow internal domain

  uci set dhcp.@dnsmasq[0].port="54"
  uci set dhcp.@dnsmasq[0].domain="lan"
  uci set dhcp.@dnsmasq[0].local="/lan/"
  uci set dhcp.@dnsmasq[0].expandhosts="1"

  uci -q del dhcp.@dnsmasq[0].server || true
  if [ "$DNS_BIND_MODE" = "gua" ]; then
    uci add_list dhcp.@dnsmasq[0].server="${NET_ADDR}#53"
    for ip6 in $NET_ADDR6_LIST; do
      uci add_list dhcp.@dnsmasq[0].server="${ip6}#53"
    done
  else
    uci add_list dhcp.@dnsmasq[0].server='127.0.0.1#53'
    uci add_list dhcp.@dnsmasq[0].server='::1#53'
  fi

  uci -q del dhcp.lan.dhcp_option || true
  uci add_list dhcp.lan.dhcp_option="6,${NET_ADDR}"

  uci set dhcp.@dnsmasq[0].dns="::"
  uci -q del dhcp.lan.dhcp_option6 || true
  if [ -n "$NET_ADDR6_LIST" ]; then
    for ip6 in $NET_ADDR6_LIST; do
      uci add_list dhcp.lan.dhcp_option6="option6:dns=[${ip6}]"
    done
  fi

  uci commit dhcp

  /etc/init.d/dnsmasq restart || {
    printf "\033[1;31mFailed to restart dnsmasq\033[0m\n"
    printf "\033[1;31mCritical error: Auto-removing AdGuard Home and rebooting in 10 seconds (Ctrl+C to cancel)\033[0m\n"
    sleep 10
    remove_adguardhome "auto"
    reboot
    exit 1
  }

  /etc/init.d/odhcpd restart || {
    printf "\033[1;31mFailed to restart odhcpd\033[0m\n"
    printf "\033[1;31mCritical error: Auto-removing AdGuard Home and rebooting in 10 seconds (Ctrl+C to cancel)\033[0m\n"
    sleep 10
    remove_adguardhome "auto"
    reboot
    exit 1
  }

  printf "\033[1;32mRouter IPv4: %s\033[0m\n" "$NET_ADDR"

  if [ -z "$NET_ADDR6_LIST" ]; then
    printf "\033[1;33mRouter IPv6: none found\033[0m\n"
  else
    printf "Router IPv6: %s\n" "$NET_ADDR6_LIST"
  fi
}

Webmin

インストール
  • webminインストール
#!/bin/sh
set -e

## 1. 変数定義
INSTALL_DIR=/usr/libexec/webmin        # Webmin 本体設置先
CONFIG_DIR=/etc/webmin                # 設定ディレクトリ
LOG_DIR=/lib/webmin                   # ログ出力先
PID_DIR=/var/run/webmin               # pid 保存先
USER=admin                            # 管理ユーザー名
PASS=$(tr -dc A-Za-z0-9 </dev/urandom | head -c12)   # ランダムパスワード
PORT=10000                            # リッスンポート

## 2. 依存パッケージのインストール(SSL 有効化に perl-net-ssleay)
opkg update
BASE_PKGS="
  tar gzip unzip shared-mime-info openssl-util
  coreutils coreutils-install coreutils-stty coreutils-df
  make gawk fdisk patch diffutils binutils-objdump
  perl perlbase perlbase-bignum perlbase-commons perlbase-time
  perl-test-warn perl-test-harness
"
PERLBASE_PKGS="$(opkg list | awk '/^perlbase-/{print $1}')"
opkg install $BASE_PKGS $PERLBASE_PKGS --force-overwrite
echo "依存パッケージのインストールが完了しました。"

## 3. グループ「bin」の確認/追加
grep -q '^bin:' /etc/group || echo 'bin:x:2:' >> /etc/group

## 4. ディレクトリ作成
mkdir -p ${INSTALL_DIR} ${CONFIG_DIR} ${LOG_DIR} ${PID_DIR}

## 5. Webmin ダウンロード&展開
wget --no-check-certificate -O /tmp/webmin.tar.gz https://www.webmin.com/download/webmin-current.tar.gz
tar xzf /tmp/webmin.tar.gz -C ${INSTALL_DIR} --strip-components=1

## 6. setup.sh の無人化パッチ
#  atboot=1 → 0(xinetd 非依存化)
#  makeboot=1 行削除
sed -i -e 's/^atboot=1/atboot=0/' -e '/^makeboot=1/d' ${INSTALL_DIR}/setup.sh

## 7. setup.sh を非対話で実行
perl_bin=$(which perl || echo /usr/bin/perl)
os_name="Generic Linux"
os_ver=$(uname -r)
/usr/bin/env bash <<EOF | ${INSTALL_DIR}/setup.sh ${INSTALL_DIR}

${LOG_DIR}
${perl_bin}
${os_name}
${os_ver}
${PORT}
${USER}
${PASS}
${PASS}
n
EOF

## 8. SSL 無効化(SSLeay ライブラリなしでも動くように)
sed -i -e 's/^ssl=1/ssl=0/' ${CONFIG_DIR}/miniserv.conf

## 9. procd/rc.common ベースの init スクリプト作成
cat << 'EOI' > /etc/init.d/webmin
#!/bin/sh /etc/rc.common
START=90
STOP=10
USE_PROCD=1

PIDFILE=/var/run/webmin/miniserv.pid
COMMAND=/etc/webmin/.start-init

start_service() {
    procd_open_instance
    procd_set_param command ${COMMAND}
    procd_set_param pidfile ${PIDFILE}
    procd_set_param respawn
    procd_close_instance
}

stop_service() {
    /etc/webmin/.stop-init
}

reload_service() {
    /etc/webmin/.reload-init
}
EOI

chmod +x /etc/init.d/webmin

## 10. サービス有効化&起動
/etc/init.d/webmin enable
/etc/init.d/webmin start

## 完了メッセージ
echo "-------------------------------------------------"
echo "Webmin Installed!"
echo "URL:   http://$(ip addr show dev br-lan | grep -Po 'inet \K[\d.]+'):${PORT}/"
echo "User:  ${USER}"
echo "Pass:  ${PASS}"
echo "Log:   ${LOG_DIR}/miniserv.log"
echo "-------------------------------------------------"


  • リムーブ
service webmin stop
rm -rf /etc/init.d/webmin
rm -rf /etc/init.d/webmin.old
sed -i "/bin:x:2:/d" /etc/group
sed -i "/webmin/d" /etc/services
/etc/webmin/uninstall.sh

テスト

iperf3

インストール
#!/bin/sh

TMP=/tmp/aios
mkdir -p "$TMP"
cat > "$TMP"/iperf3_setup.sh << 'SCRIPT_END'
#!/bin/sh

# Usage: ./iperf3_setup.sh [start|stop|restart|enable|disable|status|interactive]

SERVICE_FILE="/etc/init.d/iperf3"
PIDFILE="/var/run/iperf3.pid"
LAN="br-lan"

RED='\033[1;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
BLUE='\033[1;34m'
CYAN='\033[1;36m'
NC='\033[0m'

print_msg() { printf "${1}${2}${NC}\n"; }

get_iface_addrs() {
    local flag=0
    if ip -4 -o addr show dev "$LAN" scope global 2>/dev/null | grep -q 'inet '; then
        NET_ADDR=$(ip -4 -o addr show dev "$LAN" scope global | awk 'NR==1{sub(/\/.*/,"",$4); print $4}')
        flag=$((flag | 1))
    else
        printf "\033[1;33mWarning: No IPv4 address on %s\033[0m\n" "$LAN"
    fi
    
    if ip -6 -o addr show dev "$LAN" scope global 2>/dev/null | grep -q 'inet6 '; then
        NET_ADDR6_LIST=$(ip -6 -o addr show dev "$LAN" scope global | grep -v temporary | awk 'match($4,/^(2|fd|fc)/){sub(/\/.*/,"",$4); print $4;}')
        flag=$((flag | 2))
    else
        printf "\033[1;33mWarning: No IPv6 address on %s\033[0m\n" "$LAN"
    fi
    
    case $flag in
        3) FAMILY_TYPE=any ;;
        1) FAMILY_TYPE=ipv4 ;;
        2) FAMILY_TYPE=ipv6 ;;
        *) FAMILY_TYPE="" ;;
    esac
}

get_lan_ip() {
    get_iface_addrs
    if [ -n "$NET_ADDR" ]; then
        printf "${NET_ADDR}"
    else
        printf "192.168.1.1"
    fi
}

check_package() {
    command -v iperf3 >/dev/null 2>&1 || {
        command -v apk >/dev/null 2>&1 && apk info iperf3 >/dev/null 2>&1
    } || {
        command -v opkg >/dev/null 2>&1 && opkg list-installed | grep -q "^iperf3 "
    }
}

check_service() { [ -f "$SERVICE_FILE" ]; }

install_package(){
  PKGS="iperf3"
  print_msg "$BLUE" "Installing $PKGS package"
  command -v opkg >/dev/null 2>&1 && opkg update >/dev/null 2>&1 && opkg install $PKGS && return 0
  command -v apk  >/dev/null 2>&1 && apk update >/dev/null 2>&1 && apk add $PKGS && return 0
  print_msg "$RED" "No supported package manager found (opkg/apk)"
  return 1
}

create_service() {
    local ip
    ip=$(get_lan_ip)
    print_msg "$BLUE" "Creating iperf3 service for $ip:5201"
    
    cat > "$SERVICE_FILE" << 'SERVICEEOF'
#!/bin/sh /etc/rc.common
START=95
STOP=01
USE_PROCD=1
PROG=/usr/bin/iperf3
pidfile=/var/run/iperf3.pid

start_service() {
    local ip
    ip=$(ip -4 -o addr show dev br-lan scope global 2>/dev/null | awk 'NR==1{sub(/\/.*/,"",$4); print $4}')
    [ -z "$ip" ] && ip="192.168.1.1"
    
    printf "Starting iperf3 server on %s:5201\n" "$ip"
    procd_open_instance
    procd_set_param command "$PROG" --server --daemon --pidfile "$pidfile" --bind "$ip"
    procd_set_param pidfile "$pidfile"
    procd_set_param respawn
    procd_close_instance
}

stop_service() {
    printf "Stopping iperf3 server\n"
    [ -f "$pidfile" ] && {
        pid=$(cat "$pidfile" 2>/dev/null)
        [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null && {
            kill "$pid" 2>/dev/null && printf "iperf3 server stopped\n" || {
                printf "Failed to stop iperf3 server (PID: %s)\n" "$pid"; return 1
            }
        }
        rm -f "$pidfile"
    }
}

status() {
    local ip pid
    ip=$(ip -4 -o addr show dev br-lan scope global 2>/dev/null | awk 'NR==1{sub(/\/.*/,"",$4); print $4}')
    [ -z "$ip" ] && ip="192.168.1.1"
    
    [ -f "$pidfile" ] && {
        pid=$(cat "$pidfile" 2>/dev/null)
        [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null && {
            printf "iperf3 server is running (PID: %s) on %s:5201\n" "$pid" "$ip"; return 0
        }
        printf "iperf3 server is not running (stale pidfile)\n"; rm -f "$pidfile"; return 1
    } || { printf "iperf3 server is not running\n"; return 1; }
}
SERVICEEOF
    
    chmod +x "$SERVICE_FILE"
    print_msg "$GREEN" "Service configured for $ip:5201"
}

install_iperf3() {
  print_msg "$BLUE" "Installing iperf3"
  command -v iperf3 >/dev/null 2>&1 || install_package iperf3 || { print_msg "$RED" "Package installation failed"; return 1; }
  [ -f "$SERVICE_FILE" ]   || create_service  || { print_msg "$RED" "Service creation failed";  return 1; }
  print_msg "$GREEN" "Installation completed"
  printf "${CYAN}service iperf3 [enable|start|stop|status]${NC}\n"
  printf "${CYAN}Test: iperf3 -c $(get_lan_ip) -t 10${NC}\n"
}

remove_iperf3() {
    local auto="$1"
    print_msg "$BLUE" "Removing iperf3"
    
    local pkg=false svc=false
    check_package && pkg=true
    check_service && svc=true
    
    [ "$pkg" = "false" ] && [ "$svc" = "false" ] && { print_msg "$RED" "iperf3 not found"; return 1; }
    
    [ "$auto" != "auto" ] && {
        printf "Remove iperf3? (y/N): "
        read -r confirm
        case "$confirm" in 
            [yY]*) ;; 
            *) print_msg "$YELLOW" "Cancelled"; return 0;; 
        esac
    }
    
    [ "$svc" = "true" ] && {
        print_msg "$BLUE" "Removing service"
        service iperf3 stop 2>/dev/null || true
        service iperf3 disable 2>/dev/null || true
        rm -f "$SERVICE_FILE" "$PIDFILE"
        print_msg "$GREEN" "Service removed"
    }
    
    [ "$pkg" = "true" ] && {
        print_msg "$BLUE" "Removing package"
        if command -v apk >/dev/null 2>&1; then
            apk del iperf3 && print_msg "$GREEN" "Package removed" || { print_msg "$RED" "Remove failed"; return 1; }
        elif command -v opkg >/dev/null 2>&1; then
            opkg remove iperf3 && print_msg "$GREEN" "Package removed" || { print_msg "$RED" "Remove failed"; return 1; }
        else
            print_msg "$YELLOW" "Cannot remove package - no package manager"
        fi
    }
    
    print_msg "$GREEN" "Removal completed"
}

show_usage() {
    printf "Usage: %s [command]\n\n" "$0"
    printf "Commands:\n"
    printf "  start       - Start iperf3 service\n"
    printf "  stop        - Stop iperf3 service\n"
    printf "  restart     - Restart iperf3 service\n"
    printf "  enable      - Enable service at boot\n"
    printf "  disable     - Disable service at boot\n"
    printf "  status      - Show service status\n"
    printf "  interactive - Interactive mode (default)\n"
    printf "  help        - Show this help\n\n"
    printf "Note: Install/Uninstall is determined automatically\n"
}

interactive_mode() {
    while true; do
        printf "\n${BLUE}iperf3 Management${NC}\n"

        check_package && pkg=true || pkg=false
        check_service && svc=true || svc=false
        if [ "$svc" = "true" ]; then
            service iperf3 status >/dev/null 2>&1 && running=true || running=false
        else
            running=false
        fi

        if [ "$pkg" = "false" ] || [ "$svc" = "false" ]; then
            printf "[1] Install iperf3\n"
            printf "[2] Exit\n"
            printf "Please select (1-2): "
            read -r choice

            case "$choice" in
                1)
                    install_iperf3
                    ;;
                2)
                    print_msg "$GREEN" "Goodbye"
                    break
                    ;;
                *)
                    printf "${RED}Invalid selection: %s${NC}\n" "$choice"
                    ;;
            esac

        else
            printf "[1] Start service     [5] Disable service\n"
            printf "[2] Stop service      [6] Show status\n"
            printf "[3] Restart service   [7] Remove iperf3\n"
            printf "[4] Enable service    [8] Exit\n"
            printf "Please select (1-8): "
            read -r choice

            case "$choice" in
                1) service iperf3 start;;
                2) service iperf3 stop;;
                3) service iperf3 restart;;
                4)
                    service iperf3 enable
                    print_msg "$GREEN" "Enabled at boot"
                    ;;
                5)
                    service iperf3 disable
                    print_msg "$GREEN" "Disabled at boot"
                    ;;
                6)
                    service iperf3 status
                    ;;
                7)
                    remove_iperf3
                    ;;
                8)
                    print_msg "$GREEN" "Goodbye"
                    break
                    ;;
                *)
                    printf "${RED}Invalid selection: %s${NC}\n" "$choice"
                    ;;
            esac
        fi

        if [ "$choice" != "2" ] && [ "$choice" != "8" ]; then
            printf "\n${CYAN}Press Enter to continue${NC}"
            read -r dummy 2>/dev/null || true
        fi
    done
}

iperf3_main() {
    case "${1:-interactive}" in
        start|stop|restart)
            check_service || {
                print_msg "$RED" "Service not configured. Run script to install."
                exit 1
            }
            service iperf3 "$1"
            ;;

        enable|disable)
            check_service || {
                print_msg "$RED" "Service not configured. Run script to install."
                exit 1
            }
            service iperf3 "$1"
            print_msg "$GREEN" "Service ${1}d at boot"
            ;;

        status)
            check_service || {
                print_msg "$RED" "Service not configured"
                exit 1
            }
            service iperf3 status
            printf "\n${CYAN}Server: $(get_lan_ip):5201${NC}\n"
            printf "${CYAN}Test: iperf3 -c $(get_lan_ip) -t 10${NC}\n"
            ;;

        interactive)
            interactive_mode
            ;;

        auto-toggle)
            if check_package || check_service; then
                remove_iperf3
            else
                install_iperf3
            fi
            ;;

        help|-h|--help)
            show_usage
            ;;

        *)
            print_msg "$RED" "Unknown command: $1"
            show_usage
            exit 1
            ;;
    esac
}

[ "${0##*/}" = "iperf3_setup.sh" ] && iperf3_main "$@"
SCRIPT_END

chmod +x "$TMP"/iperf3_setup.sh
printf "\n${GREEN}=== iperf3 Setup Script Created ===${NC}\n"
printf "${CYAN}Location: $TMP/iperf3_setup.sh${NC}\n"
printf "${YELLOW}Usage: $TMP/iperf3_setup.sh [start|stop|status|help]${NC}\n"
printf "${YELLOW}Interactive: $TMP/iperf3_setup.sh${NC}\n"

printf "\n${BLUE}Running script in interactive mode${NC}\n"
sh "$TMP"/iperf3_setup.sh
  • サーバー起動 (2回目以降)
/etc/init.d/iperf3 start
  • クライアントで実行
$iperf3 = Get-Command iperf3.exe -ErrorAction SilentlyContinue
if (-not $iperf3) {
    $iperf3 = Get-ChildItem -Path $PWD -Filter iperf3.exe -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
    if ($iperf3) { $iperf3 = $iperf3.FullName }
    else {
        Write-Host "iperf3.exe が見つかりません。" -ForegroundColor Red
        exit 1
    }
} else {
    $iperf3 = $iperf3.Source
}

$server = (Get-DnsClientServerAddress -AddressFamily IPv4 | Select-Object -ExpandProperty ServerAddresses)[0]

& "$iperf3" -c $server -t 10
  • 追加テスト
& "$iperf3" -c $server -t 60 -P 16 -w 2M
  • リムーブ
sh /tmp/aios/iperf3_setup.sh auto-toggle

トラブル

既知の問題


初期化

ファクトリーリセット(初期化)

リセット
# 要注意
firstboot && reboot now

This will erase all settings and remove any installed packages. Are you sure? [N/y]

初期化:入力モード
y

デバイスリセットボタン

デバイスのリセットボタンを10秒(LEDが点滅するまで)押し続ける

http://10.10.10.254 でブラウザを開く

スクリーンショット 2025-06-28 111007.jpg

  • factory をアップロード
  • 数分待つ

あとがき

OSバージョン検証用に作りました
クライアントPCに直接続出来てSDカード交換(書換)で容易に検証環境を作れるUSBドングルなOpenWrt

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?