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 VPN DDNS WireGuard DuckDNS

0
Last updated at Posted at 2025-11-06

:flag_jp: Japanese article
OpenWrt_icon.png

はじめに

記事について

WireGuard + DuckDNS(DDNS)を使った外部アクセス環境の構築ツールです

検証環境

ルーターA:ncp-hg100:OpenWrt 24.10.4

ルーターB:bpi-r4:OpenWrt 24.10.4

  • ISP:ドコモ光:MAP-E 1G
  • 役割:WireGuardクライアント

ダイナミックDNS

  • DuckDNS:無料、設定簡単、メンテナンス不要
  • No-IP:老舗、無料版は30日ごと確認必要
  • Cloudflare:独自ドメイン必要
  • FreeDNS:無料、多数のドメイン選択可

DuckDNS

セットアップ

変数を事前設定する場合(対話形式をスキップ)

# DuckDNS設定用変数
DDNS_SERVICE="duckdns.org"
DDNS_DOMAIN="myrouter"
DDNS_TOKEN="12345678-abcd-1234-abcd-123456789abc"
DDNS_INTERFACE="wan"
CHECK_INTERVAL="24"
CHECK_UNIT="hours"

セットアップ

(
#!/bin/sh

# 必要パッケージの自動インストール
echo "=========================================="
echo "必要パッケージの確認"
echo "=========================================="

# インストール済み言語パッケージから言語コードを検出
LANG_PKGS=""
INSTALLED_LANGS=""
command -v opkg >/dev/null 2>&1 && INSTALLED_LANGS=$(opkg list-installed | grep "^luci-i18n-base-" | sed 's/luci-i18n-base-//' | cut -d' ' -f1 | sort -u)
command -v apk  >/dev/null 2>&1 && INSTALLED_LANGS=$(apk list --installed 2>/dev/null | grep "^luci-i18n-base-" | sed 's/luci-i18n-base-//' | cut -d'-' -f1 | sort -u)

for lang in $INSTALLED_LANGS; do
    LANG_PKGS="$LANG_PKGS luci-i18n-ddns-$lang"
done

# パッケージリスト
BASE_PKGS="luci-app-ddns ddns-scripts"
PKGS="$BASE_PKGS $LANG_PKGS"

# インストール
command -v opkg && opkg update >/dev/null 2>&1 && opkg install $PKGS 2>&1 | grep "up to date" | sed 's/Package \(.*\) (.*/インストール済み: \1/'
command -v apk  && apk update >/dev/null 2>&1  && apk add $PKGS >/dev/null 2>&1

echo "=========================================="
echo ""

# ========================================
# グローバル変数(デフォルト値)
# ========================================
DDNS_SERVICE="${DDNS_SERVICE:-duckdns.org}"
DDNS_DOMAIN="${DDNS_DOMAIN:-}"
DDNS_TOKEN="${DDNS_TOKEN:-}"
DDNS_INTERFACE="${DDNS_INTERFACE:-wan}"
CHECK_INTERVAL="${CHECK_INTERVAL:-24}"
CHECK_UNIT="${CHECK_UNIT:-hours}"

# ========================================
# WANインターフェース検出関数
# ========================================
detect_wan_interface() {
    local iface proto
    for iface in $(uci show network | grep "=interface" | cut -d'.' -f2 | cut -d'=' -f1); do
        [ "$iface" = "loopback" ] && continue
        [ "$iface" = "lan" ] && continue
        [ "$(uci get network.$iface.disabled 2>/dev/null)" = "1" ] && continue
        
        proto=$(uci get network.$iface.proto 2>/dev/null)
        case "$proto" in
            pppoe|dhcp|static)
                echo "$iface"
                return 0
                ;;
        esac
    done
    echo "wan"
}

get_available_interfaces() {
    echo "利用可能なWANインターフェース:"
    for iface in $(uci show network | grep "=interface" | cut -d'.' -f2 | cut -d'=' -f1); do
        [ "$iface" = "loopback" ] && continue
        [ "$iface" = "lan" ] && continue
        proto=$(uci get network.$iface.proto 2>/dev/null)
        case "$proto" in
            pppoe|dhcp|static)
                echo "  $iface (proto: $proto)"
                ;;
        esac
    done
}

# ========================================
# 対話形式入力関数
# ========================================
ask_input() {
    local var_name="$1"
    local prompt="$2"
    local default="$3"
    local current_value="$4"
    
    # 既に値が設定されている場合はスキップ
    if [ -n "$current_value" ]; then
        echo "[設定済み] $prompt: $current_value"
        return 0
    fi
    
    # デフォルト値の表示
    if [ -n "$default" ]; then
        echo -n "$prompt [$default]: "
    else
        echo -n "$prompt: "
    fi
    
    read input
    
    # 入力がなければデフォルト値を使用
    if [ -z "$input" ] && [ -n "$default" ]; then
        input="$default"
    fi
    
    # 必須項目のチェック
    if [ -z "$input" ]; then
        echo "エラー: この項目は必須です"
        return 1
    fi
    
    eval "$var_name='$input'"
    return 0
}

# ========================================
# メイン処理開始
# ========================================
echo "=========================================="
echo "DuckDNS設定スクリプト"
echo "=========================================="
echo ""

# DDNSサービスプロバイダー
ask_input "DDNS_SERVICE" "DDNSサービスプロバイダー" "duckdns.org" "$DDNS_SERVICE" || exit 1

# ドメイン名
echo ""
while true; do
    ask_input "DDNS_DOMAIN" "ドメイン名(.duckdns.org の前の部分)" "" "$DDNS_DOMAIN" || exit 1
    if [ -n "$DDNS_DOMAIN" ]; then
        break
    fi
done

# トークン
echo ""
while true; do
    ask_input "DDNS_TOKEN" "DuckDNSトークン" "" "$DDNS_TOKEN" || exit 1
    if [ -n "$DDNS_TOKEN" ]; then
        break
    fi
done

# WANインターフェース
echo ""
if [ -z "$DDNS_INTERFACE" ] || [ "$DDNS_INTERFACE" = "wan" ]; then
    echo "=========================================="
    get_available_interfaces
    echo ""
    detected_iface=$(detect_wan_interface)
    echo "自動検出されたWANインターフェース: $detected_iface"
    echo "=========================================="
    echo ""
    DDNS_INTERFACE="$detected_iface"
fi
ask_input "DDNS_INTERFACE" "WANインターフェース名" "$DDNS_INTERFACE" "$DDNS_INTERFACE" || exit 1

# 更新間隔
echo ""
ask_input "CHECK_INTERVAL" "更新チェック間隔(数値)" "24" "$CHECK_INTERVAL" || exit 1

# 更新間隔の単位
echo ""
ask_input "CHECK_UNIT" "更新チェック間隔の単位" "hours" "$CHECK_UNIT" || exit 1

# 設定内容の確認
echo ""
echo "=========================================="
echo "設定内容の確認"
echo "=========================================="
echo "サービス: $DDNS_SERVICE"
echo "ドメイン: ${DDNS_DOMAIN}.duckdns.org"
echo "トークン: ${DDNS_TOKEN:0:8}... (省略表示)"
echo "WANインターフェース: $DDNS_INTERFACE"
echo "更新間隔: $CHECK_INTERVAL $CHECK_UNIT"
echo ""
echo -n "この設定で進めますか? [Y/n]: "
read confirm

if [ "$confirm" = "n" ] || [ "$confirm" = "N" ]; then
    echo "設定をキャンセルしました"
    exit 0
fi

# ========================================
# DDNS設定の適用
# ========================================
echo ""
echo "=========================================="
echo "DDNS設定を適用中..."
echo "=========================================="

# 既存のDDNS設定を削除(クリーンインストール)
echo "既存のDDNS設定を削除..."
while uci delete ddns.@service[0] 2>/dev/null; do :; done
uci delete ddns.myddns_ipv4 2>/dev/null
uci delete ddns.myddns_ipv6 2>/dev/null
uci commit ddns

# 新規DDNS設定を追加
echo "DuckDNS設定を追加..."

# DDNSセクションの作成
uci add ddns service
uci set ddns.@service[-1].enabled='1'
uci set ddns.@service[-1].service_name="${DDNS_SERVICE}"
uci set ddns.@service[-1].lookup_host="${DDNS_DOMAIN}.duckdns.org"
uci set ddns.@service[-1].domain="${DDNS_DOMAIN}"
uci set ddns.@service[-1].username="${DDNS_DOMAIN}"
uci set ddns.@service[-1].password="${DDNS_TOKEN}"
uci set ddns.@service[-1].interface="${DDNS_INTERFACE}"
uci set ddns.@service[-1].ip_source='network'
uci set ddns.@service[-1].ip_network="${DDNS_INTERFACE}"
uci set ddns.@service[-1].use_ipv6='0'
uci set ddns.@service[-1].check_interval="${CHECK_INTERVAL}"
uci set ddns.@service[-1].check_unit="${CHECK_UNIT}"
uci set ddns.@service[-1].force_interval='72'
uci set ddns.@service[-1].force_unit='hours'
uci set ddns.@service[-1].retry_count='5'
uci set ddns.@service[-1].retry_interval='60'

# 設定をコミット
echo "設定をコミット..."
uci commit ddns

# DDNS設定の表示
echo ""
echo "=========================================="
echo "設定内容の確認"
echo "=========================================="
uci show ddns

# DDNSサービスを再起動
echo ""
echo "=========================================="
echo "DDNSサービスを再起動"
echo "=========================================="
/etc/init.d/ddns restart

# 起動設定を有効化
echo "DDNSサービスの自動起動を有効化..."
/etc/init.d/ddns enable

# ステータス確認
echo ""
echo "=========================================="
echo "DDNSサービスのステータス"
echo "=========================================="
sleep 3
/etc/init.d/ddns status

# ログ確認(最後の10行)
echo ""
echo "=========================================="
echo "DDNSログ(最後の10行)"
echo "=========================================="
logread | grep -i ddns | tail -10

echo ""
echo "=========================================="
echo "設定完了!"
echo "=========================================="
echo "ドメイン名: ${DDNS_DOMAIN}.duckdns.org"
echo "更新間隔: ${CHECK_INTERVAL} ${CHECK_UNIT}"
echo ""
echo "数分待ってから以下のコマンドで確認してください:"
echo "  nslookup ${DDNS_DOMAIN}.duckdns.org"
echo ""
)

VPN

OpenWrtで利用可能な主なVPNプロトコル:

  • WireGuard:高速、軽量、設定シンプル、モダンな暗号技術
  • OpenVPN:老舗、汎用性高い、多機能、クライアント対応広い
  • Tailscale:WireGuardベース、メッシュVPN、NAT越え自動、無料枠あり
  • ZeroTier:仮想LAN、メッシュネットワーク、無料枠あり
  • Headscale:Tailscaleのセルフホスト版、オープンソース

Wireguard

公式

サーバーセットアップ

変数を事前設定する場合(対話形式をスキップ)

# Wireguardサーバー設定用変数
WG_PORT="51820"
WG_ADDRESS="10.8.0.1/24"
WG_INTERFACE="wg0"
WG_CLIENT_IP="10.8.0.2"
WG_CLIENT_LAN="192.168.0.0/24"

サーバーセットアップ

(
#!/bin/sh
# WireGuard サーバー設定スクリプト
# ========================================
# 必要パッケージの自動インストール
# ========================================
echo "=========================================="
echo "必要パッケージの確認"
echo "=========================================="

# インストール済み言語パッケージから言語コードを検出
LANG_PKGS=""
INSTALLED_LANGS=""
command -v opkg >/dev/null 2>&1 && INSTALLED_LANGS=$(opkg list-installed | grep "^luci-i18n-base-" | sed 's/luci-i18n-base-//' | cut -d' ' -f1 | sort -u)
command -v apk  >/dev/null 2>&1 && INSTALLED_LANGS=$(apk list --installed 2>/dev/null | grep "^luci-i18n-base-" | sed 's/luci-i18n-base-//' | cut -d'-' -f1 | sort -u)

for lang in $INSTALLED_LANGS; do
    LANG_PKGS="$LANG_PKGS luci-i18n-wireguard-$lang"
done

# パッケージリスト
PKGS="wireguard-tools luci-proto-wireguard"

# インストール
command -v opkg >/dev/null 2>&1 && opkg update >/dev/null 2>&1 && opkg install $PKGS 2>&1 | grep "up to date" | sed 's/Package \(.*\) (.*/インストール済み: \1/'
command -v apk  >/dev/null 2>&1 && apk update >/dev/null 2>&1 && apk add $PKGS

# wgコマンド確認
if ! command -v wg >/dev/null 2>&1; then
    echo "エラー: wireguard-tools のインストールに失敗しました"
    exit 1
fi

echo "=========================================="
echo ""

# ========================================
# グローバル変数(デフォルト値)
# ========================================
WG_PORT="${WG_PORT:-51820}"
WG_ADDRESS="${WG_ADDRESS:-10.8.0.1/24}"
WG_INTERFACE="${WG_INTERFACE:-wg0}"
WG_CLIENT_IP="${WG_CLIENT_IP:-10.8.0.2}"
WG_CLIENT_LAN="${WG_CLIENT_LAN:-192.168.0.0/24}"

# ========================================
# 対話形式入力関数
# ========================================
ask_input() {
    local var_name="$1"
    local prompt="$2"
    local default="$3"
    local current_value="$4"
    
    if [ -n "$current_value" ]; then
        echo "[設定済み] $prompt: $current_value"
        return 0
    fi
    
    if [ -n "$default" ]; then
        echo -n "$prompt [$default]: "
    else
        echo -n "$prompt: "
    fi
    
    read input
    
    if [ -z "$input" ] && [ -n "$default" ]; then
        input="$default"
    fi
    
    if [ -z "$input" ]; then
        echo "エラー: この項目は必須です"
        return 1
    fi
    
    eval "$var_name='$input'"
    return 0
}

# ========================================
# メイン処理開始
# ========================================
echo "=========================================="
echo "WireGuard サーバー設定スクリプト"
echo "=========================================="
echo ""

# WireGuardポート番号
ask_input "WG_PORT" "WireGuardリスニングポート(UDP)" "51820" "$WG_PORT" || exit 1

# WireGuard VPNネットワークアドレス
echo ""
ask_input "WG_ADDRESS" "WireGuard VPNネットワークアドレス" "10.8.0.1/24" "$WG_ADDRESS" || exit 1

# WireGuardインターフェース名
echo ""

# 空いているインターフェース名を検出
WG_BASE="${WG_INTERFACE:-wg0}"
WG_INTERFACE="$WG_BASE"
WG_NUM=$(echo "$WG_BASE" | sed 's/[^0-9]//g')
WG_NUM=${WG_NUM:-0}

while uci show network.$WG_INTERFACE >/dev/null 2>&1; do
    WG_NUM=$((WG_NUM+1))
    WG_PREFIX=$(echo "$WG_BASE" | sed 's/[0-9]*$//')
    WG_INTERFACE="${WG_PREFIX}${WG_NUM}"
done

ask_input "WG_INTERFACE" "WireGuardインターフェース名" "$WG_INTERFACE" "" || exit 1

# クライアントIPアドレス
echo ""
ask_input "WG_CLIENT_IP" "クライアントIPアドレス" "10.8.0.2" "$WG_CLIENT_IP" || exit 1

# クライアント側LANネットワーク
echo ""
ask_input "WG_CLIENT_LAN" "クライアント側LANネットワーク" "192.168.0.0/24" "$WG_CLIENT_LAN" || exit 1

# 設定内容の確認
echo ""
echo "=========================================="
echo "設定内容の確認"
echo "=========================================="
echo "リスニングポート: $WG_PORT (UDP)"
echo "VPNネットワーク: $WG_ADDRESS"
echo "インターフェース: $WG_INTERFACE"
echo "クライアントIP: $WG_CLIENT_IP"
echo "クライアントLAN: $WG_CLIENT_LAN"
echo ""
echo -n "この設定で進めますか? [Y/n]: "
read confirm

if [ "$confirm" = "n" ] || [ "$confirm" = "N" ]; then
    echo "設定をキャンセルしました"
    exit 0
fi

# ========================================
# WireGuard設定の適用
# ========================================
echo ""
echo "=========================================="
echo "WireGuard設定を適用中..."
echo "=========================================="

# 鍵ペアの生成
echo "鍵ペアを生成中..."
WG_PRIVKEY=$(wg genkey)
WG_PUBKEY=$(echo "$WG_PRIVKEY" | wg pubkey)

echo "サーバー公開鍵: $WG_PUBKEY"

# WireGuardインターフェースの作成
echo "WireGuardインターフェースを作成中..."

uci set network.${WG_INTERFACE}=interface
uci set network.${WG_INTERFACE}.proto='wireguard'
uci set network.${WG_INTERFACE}.private_key="$WG_PRIVKEY"
uci set network.${WG_INTERFACE}.listen_port="$WG_PORT"
uci add_list network.${WG_INTERFACE}.addresses="$WG_ADDRESS"
uci set network.${WG_INTERFACE}.metric='128' 

uci commit network

# ファイアウォールゾーンの作成
echo "ファイアウォールゾーンを作成中..."

uci add firewall zone
uci set firewall.@zone[-1].name='wg'
uci set firewall.@zone[-1].input='ACCEPT'
uci set firewall.@zone[-1].output='ACCEPT'
uci set firewall.@zone[-1].forward='ACCEPT'
uci set firewall.@zone[-1].masq='1'
uci add_list firewall.@zone[-1].network="${WG_INTERFACE}"

# WANからWireGuardポートへのアクセス許可
echo "ファイアウォールルールを追加中..."

uci add firewall rule
uci set firewall.@rule[-1].name='Allow-WireGuard'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].dest_port="$WG_PORT"
uci set firewall.@rule[-1].proto='udp'
uci set firewall.@rule[-1].target='ACCEPT'

# WGゾーンからLANへのフォワーディング許可
uci add firewall forwarding
uci set firewall.@forwarding[-1].src='wg'
uci set firewall.@forwarding[-1].dest='lan'

# LANからWGへのフォワーディング許可
uci add firewall forwarding
uci set firewall.@forwarding[-1].src='lan'
uci set firewall.@forwarding[-1].dest='wg'

uci commit firewall

# ttydがある場合、WireGuard経由のアクセスを許可
if command -v ttyd >/dev/null 2>&1; then
    echo "ttyd設定を更新中..."
    uci delete ttyd.@ttyd[0].interface 2>/dev/null
    uci commit ttyd
    /etc/init.d/ttyd restart
fi

# 設定の表示
echo ""
echo "=========================================="
echo "設定完了!"
echo "=========================================="
echo ""
echo "【重要】設定を反映するには再起動してください:"
echo "  reboot"
echo ""
echo "【サーバー情報】"
echo "インターフェース: $WG_INTERFACE"
echo "リスニングポート: $WG_PORT (UDP)"
echo "VPNネットワーク: $WG_ADDRESS"
echo ""
echo "【サーバー鍵情報】"
echo "公開鍵: $WG_PUBKEY"
echo ""
echo "【既存のWireGuardインターフェース】"
uci show network | grep "=interface" | cut -d'.' -f2 | cut -d'=' -f1 | while read iface; do
    proto=$(uci get network.$iface.proto 2>/dev/null)
    if [ "$proto" = "wireguard" ]; then
        addr=$(uci get network.$iface.addresses 2>/dev/null | head -1)
        if [ "$iface" = "$WG_INTERFACE" ]; then
            echo "  ★ $iface ($addr) ← 今回作成"
        else
            echo "    $iface ($addr)"
        fi
    fi
done
echo ""
echo "【次のステップ】"
echo "1. クライアント側の設定を行ってください"
echo "2. クライアントの公開鍵を取得してください"
echo "3. 以下のコマンドでピア(クライアント)を追加してください:"
echo ""
echo "uci add network wireguard_${WG_INTERFACE}"
echo "uci set network.@wireguard_${WG_INTERFACE}[-1].public_key='<クライアント公開鍵>'"
echo "uci set network.@wireguard_${WG_INTERFACE}[-1].description='クライアント'"
echo "uci add_list network.@wireguard_${WG_INTERFACE}[-1].allowed_ips='${WG_CLIENT_IP}/32'"
echo "uci add_list network.@wireguard_${WG_INTERFACE}[-1].allowed_ips='${WG_CLIENT_LAN}'"
echo "uci commit network"
echo "reboot"
echo ""
echo "【動作確認】"
echo "wg show"
echo "ip addr show $WG_INTERFACE"
echo ""
)

クライアントセットアップ

変数を事前設定する場合(対話形式をスキップ)

# WireGuardクライアント設定用変数
WG_SERVER_ENDPOINT="myrouter.duckdns.org:51820"
WG_SERVER_PUBKEY="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
WG_CLIENT_ADDRESS="10.8.0.2/24"
WG_INTERFACE="wg0"
WG_PERSISTENT_KEEPALIVE="25"
WG_VPN_NETWORK="10.8.0.0/24"
WG_SERVER_LAN="192.168.10.0/24"

クライアントセットアップ

(
#!/bin/sh
# WireGuard クライアント設定スクリプト
# ========================================
# 必要パッケージの自動インストール
# ========================================
echo "=========================================="
echo "必要パッケージの確認"
echo "=========================================="

# インストール済み言語パッケージから言語コードを検出
LANG_PKGS=""
INSTALLED_LANGS=""
command -v opkg >/dev/null 2>&1 && INSTALLED_LANGS=$(opkg list-installed | grep "^luci-i18n-base-" | sed 's/luci-i18n-base-//' | cut -d' ' -f1 | sort -u)
command -v apk  >/dev/null 2>&1 && INSTALLED_LANGS=$(apk list --installed 2>/dev/null | grep "^luci-i18n-base-" | sed 's/luci-i18n-base-//' | cut -d'-' -f1 | sort -u)

for lang in $INSTALLED_LANGS; do
    LANG_PKGS="$LANG_PKGS luci-i18n-wireguard-$lang"
done

# パッケージリスト
PKGS="wireguard-tools luci-proto-wireguard"

# インストール
command -v opkg >/dev/null 2>&1 && opkg update >/dev/null 2>&1 && opkg install $PKGS 2>&1 | grep "up to date" | sed 's/Package \(.*\) (.*/インストール済み: \1/'
command -v apk  >/dev/null 2>&1 && apk update >/dev/null 2>&1 && apk add $PKGS

# wgコマンド確認
if ! command -v wg >/dev/null 2>&1; then
    echo "エラー: wireguard-tools のインストールに失敗しました"
    exit 1
fi

echo "=========================================="
echo ""

# ========================================
# グローバル変数(デフォルト値)
# ========================================
WG_SERVER_ENDPOINT="${WG_SERVER_ENDPOINT:-}"
WG_SERVER_PUBKEY="${WG_SERVER_PUBKEY:-}"
WG_CLIENT_ADDRESS="${WG_CLIENT_ADDRESS:-10.8.0.2/24}"
WG_INTERFACE="${WG_INTERFACE:-wg0}"
WG_PERSISTENT_KEEPALIVE="${WG_PERSISTENT_KEEPALIVE:-25}"
WG_VPN_NETWORK="${WG_VPN_NETWORK:-10.8.0.0/24}"
WG_SERVER_LAN="${WG_SERVER_LAN:-192.168.10.0/24}"

# ========================================
# 対話形式入力関数
# ========================================
ask_input() {
    local var_name="$1"
    local prompt="$2"
    local default="$3"
    local current_value="$4"
    
    if [ -n "$current_value" ]; then
        echo "[設定済み] $prompt: $current_value"
        return 0
    fi
    
    if [ -n "$default" ]; then
        echo -n "$prompt [$default]: "
    else
        echo -n "$prompt: "
    fi
    
    read input
    
    if [ -z "$input" ] && [ -n "$default" ]; then
        input="$default"
    fi
    
    if [ -z "$input" ]; then
        echo "エラー: この項目は必須です"
        return 1
    fi
    
    eval "$var_name='$input'"
    return 0
}

# ========================================
# メイン処理開始
# ========================================
echo "=========================================="
echo "WireGuard クライアント設定スクリプト"
echo "=========================================="
echo ""

# サーバーエンドポイント
while true; do
    ask_input "WG_SERVER_ENDPOINT" "サーバーエンドポイント(例: example.duckdns.org:51820)" "" "$WG_SERVER_ENDPOINT" || exit 1
    if [ -n "$WG_SERVER_ENDPOINT" ]; then
        break
    fi
done

# サーバー公開鍵
echo ""
while true; do
    ask_input "WG_SERVER_PUBKEY" "サーバー公開鍵" "" "$WG_SERVER_PUBKEY" || exit 1
    if [ -n "$WG_SERVER_PUBKEY" ]; then
        break
    fi
done

# クライアントVPNアドレス
echo ""
ask_input "WG_CLIENT_ADDRESS" "クライアントVPNアドレス" "10.8.0.2/24" "$WG_CLIENT_ADDRESS" || exit 1

# WireGuardインターフェース名
echo ""

# 空いているインターフェース名を検出
WG_BASE="${WG_INTERFACE:-wg0}"
WG_INTERFACE="$WG_BASE"
WG_NUM=$(echo "$WG_BASE" | sed 's/[^0-9]//g')
WG_NUM=${WG_NUM:-0}

while uci show network.$WG_INTERFACE >/dev/null 2>&1; do
    WG_NUM=$((WG_NUM+1))
    WG_PREFIX=$(echo "$WG_BASE" | sed 's/[0-9]*$//')
    WG_INTERFACE="${WG_PREFIX}${WG_NUM}"
done

ask_input "WG_INTERFACE" "WireGuardインターフェース名" "$WG_INTERFACE" "" || exit 1

# Persistent Keepalive
echo ""
ask_input "WG_PERSISTENT_KEEPALIVE" "Persistent Keepalive(秒)" "25" "$WG_PERSISTENT_KEEPALIVE" || exit 1

# VPNネットワーク
echo ""
ask_input "WG_VPN_NETWORK" "VPNネットワーク" "10.8.0.0/24" "$WG_VPN_NETWORK" || exit 1

# サーバー側LANネットワーク
echo ""
ask_input "WG_SERVER_LAN" "サーバー側LANネットワーク" "192.168.10.0/24" "$WG_SERVER_LAN" || exit 1

# 設定内容の確認
echo ""
echo "=========================================="
echo "設定内容の確認"
echo "=========================================="
echo "サーバーエンドポイント: $WG_SERVER_ENDPOINT"
echo "サーバー公開鍵: ${WG_SERVER_PUBKEY:0:20}..."
echo "クライアントVPNアドレス: $WG_CLIENT_ADDRESS"
echo "インターフェース: $WG_INTERFACE"
echo "Keepalive: $WG_PERSISTENT_KEEPALIVE 秒"
echo "VPNネットワーク: $WG_VPN_NETWORK"
echo "サーバーLAN: $WG_SERVER_LAN"
echo ""
echo -n "この設定で進めますか? [Y/n]: "
read confirm

if [ "$confirm" = "n" ] || [ "$confirm" = "N" ]; then
    echo "設定をキャンセルしました"
    exit 0
fi

# ========================================
# WireGuard設定の適用
# ========================================
echo ""
echo "=========================================="
echo "WireGuard設定を適用中..."
echo "=========================================="

# 鍵ペアの生成
echo "鍵ペアを生成中..."
WG_PRIVKEY=$(wg genkey)
WG_PUBKEY=$(echo "$WG_PRIVKEY" | wg pubkey)

echo "クライアント公開鍵: $WG_PUBKEY"

# クライアントIPアドレスを抽出
CLIENT_IP=$(echo $WG_CLIENT_ADDRESS | cut -d'/' -f1)

# WireGuardインターフェースの作成
echo "WireGuardインターフェースを作成中..."

uci set network.${WG_INTERFACE}=interface
uci set network.${WG_INTERFACE}.proto='wireguard'
uci set network.${WG_INTERFACE}.private_key="$WG_PRIVKEY"
uci add_list network.${WG_INTERFACE}.addresses="$WG_CLIENT_ADDRESS"
uci set network.${WG_INTERFACE}.metric='128' 

# サーバーピアの設定
uci add network wireguard_${WG_INTERFACE}
uci set network.@wireguard_${WG_INTERFACE}[-1].public_key="$WG_SERVER_PUBKEY"
uci set network.@wireguard_${WG_INTERFACE}[-1].endpoint_host="$(echo $WG_SERVER_ENDPOINT | cut -d':' -f1)"
uci set network.@wireguard_${WG_INTERFACE}[-1].endpoint_port="$(echo $WG_SERVER_ENDPOINT | cut -d':' -f2)"
uci set network.@wireguard_${WG_INTERFACE}[-1].route_allowed_ips='1'
uci set network.@wireguard_${WG_INTERFACE}[-1].persistent_keepalive="$WG_PERSISTENT_KEEPALIVE"
uci add_list network.@wireguard_${WG_INTERFACE}[-1].allowed_ips="${WG_VPN_NETWORK}"
uci add_list network.@wireguard_${WG_INTERFACE}[-1].allowed_ips="${WG_SERVER_LAN}"

uci commit network

# ファイアウォールゾーンの作成
echo "ファイアウォールゾーンを作成中..."

uci add firewall zone
uci set firewall.@zone[-1].name='wg'
uci set firewall.@zone[-1].input='ACCEPT'
uci set firewall.@zone[-1].output='ACCEPT'
uci set firewall.@zone[-1].forward='ACCEPT'
uci set firewall.@zone[-1].masq='1'
uci add_list firewall.@zone[-1].network="${WG_INTERFACE}"

# WGゾーンからLANへのフォワーディング許可
uci add firewall forwarding
uci set firewall.@forwarding[-1].src='wg'
uci set firewall.@forwarding[-1].dest='lan'

# LANからWGへのフォワーディング許可
uci add firewall forwarding
uci set firewall.@forwarding[-1].src='lan'
uci set firewall.@forwarding[-1].dest='wg'

uci commit firewall

# ttydがある場合、WireGuard経由のアクセスを許可
if command -v ttyd >/dev/null 2>&1; then
    echo "ttyd設定を更新中..."
    uci delete ttyd.@ttyd[0].interface 2>/dev/null
    uci commit ttyd
    /etc/init.d/ttyd restart
fi

# 設定の表示
echo ""
echo "=========================================="
echo "設定完了!"
echo "=========================================="
echo ""
echo "【クライアント情報】"
echo "インターフェース: $WG_INTERFACE"
echo "VPNアドレス: $WG_CLIENT_ADDRESS"
echo "公開鍵: $WG_PUBKEY"
echo ""
echo "【既存のWireGuardインターフェース】"
uci show network | grep "=interface" | cut -d'.' -f2 | cut -d'=' -f1 | while read iface; do
    proto=$(uci get network.$iface.proto 2>/dev/null)
    if [ "$proto" = "wireguard" ]; then
        addr=$(uci get network.$iface.addresses 2>/dev/null | head -1)
        if [ "$iface" = "$WG_INTERFACE" ]; then
            echo "  ★ $iface ($addr) ← 今回作成"
        else
            echo "    $iface ($addr)"
        fi
    fi
done
echo ""
# クライアント側LANネットワークを検出
CLIENT_LAN=$(ip -o -4 addr show br-lan 2>/dev/null | awk '{print $4}' | head -1 | sed 's/\.[0-9]*\//.0\//')
[ -z "$CLIENT_LAN" ] && CLIENT_LAN="<要手動設定>"

echo "=========================================="
echo "【重要】サーバー側で以下をコピー&ペーストして実行"
echo "=========================================="
echo ""
cat << EOF
uci add network wireguard_${WG_INTERFACE}
uci set network.@wireguard_${WG_INTERFACE}[-1].public_key='$WG_PUBKEY'
uci set network.@wireguard_${WG_INTERFACE}[-1].description='クライアント'
uci add_list network.@wireguard_${WG_INTERFACE}[-1].allowed_ips='${CLIENT_IP}/32'
uci add_list network.@wireguard_${WG_INTERFACE}[-1].allowed_ips='${CLIENT_LAN}'
uci commit network
reboot
EOF
echo ""
echo "=========================================="
echo ""
echo "【サーバー・クライアント両側を再起動】"
echo "  reboot"
echo ""
)

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

aios.png

あとがき

0
0
0

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?