メインコンテンツへスキップ
見出し画像

デジタルモード限定・アマチュア局の遠隔操作に対応する その2 DNS設定編

    自宅VPNサーバを立てて、自宅外から遠隔操作できるようになりました。ただし、機器をIPアドレスで指定しているのが若干イケていません。ホスト名で指定できるようにすべく、自前でDNSを立ててしまいましょう。

    ※実際に無線機を遠隔操作するためには局免の変更申請が必要です。
    ※表題画像はChatGPTに生成させました。無線風味がありませんね。

    DNS

    ここまでの設定で、VPNを通して自宅LANに参加できるようになりました。LANだけであればmDNSでホスト名を解決できていたのですが、WireGuard VPNはL3なのでUDPのマルチキャストが届きません。という訳で、自前でDNSを立てることにしました。

    dnsmasq

    WireGuardをインストールしたRasPiに、ローカルに向けたDNSを立ててみましょう。軽量DNSの定番、dnsmasqです。

    $ sudo apt install dnsmasq
    $ sudo systemctl start dnsmasq
    $ sudo systemctl enable dnsmasq

    これだけで、/etc/hostsのエントリを参照したDNSが立ち上がります。

    ホスト

    無線局っぽい雰囲気を重視して、ホスト名はフォネティックコードにしました。LAN側のアドレス (192.168.10.191〜195) はルータのDHCPで固定的に割り当てるよう設定してあります。

    • alpha: VPNサーバ・DNSサーバ: 192.168.10.191, 10.0.0.1

    • bravo: VNCクライアント: 192.168.10.192, 10.0.0.2

    • charlie: 自宅LAN外VNCクライアント: -, 10.0.0.3

    • delta: WSJT-X/MSHV, 192.168.10.194, 10.0.0.4

    • echo: RUMlogNG: 192.168.10.195, 10.0.0.5

    charlieは自宅LAN内にはありませんが、内部的には192.168.10.193を割り当てます。


    設定失敗

    ChatGPTに相談しながら設定してみましたが、結論から言えば期待通りには動作しませんでした。備忘のために残しておきますが、失敗に興味のない方は成功例まで読み飛ばして下さい。

    方針

    • LAN側からの問い合わせ → LAN側のアドレスを返す

    • VPN側からの問い合わせ → VPN側のアドレスを返す

    設定例 (失敗)

    以下に、ChatGPTが提案してきた内容を示します。この通りに設定しても、期待通りには動作しません。

    $ sudo vi /etc/dnsmasq.d/home.conf
     
    domain=home
    local=/home/
    
    listen-address=127.0.0.1
    listen-address=192.168.10.191
    listen-address=10.0.0.1
    #bind-interfaces
    bind-dynamic
    
    cache-size=1000
    domain-needed
    bogus-priv
    
    localise-queries
    
    # WireGuard VPN, DNS, RasPi5
    host-record=alpha,alpha.home,192.168.10.191,10.0.0.1
    
    # VNC client, MacBook Air
    host-record=bravo,bravo.home,192.168.10.192,10.0.0.2
    
    # VNC client, Mac mini
    host-record=charlie,charlie.home,192.168.10.193,10.0.0.3
    
    # WSJT-X/MSHV, Debian trixie
    host-record=delta,delta.home,192.168.10.194,10.0.0.4
    
    # RUMlogNG, Mac mini @home
    host-record=echo,echo.home,192.168.10.195,10.0.0.5
    
    # CNAME
    cname=vpn.home,alpha.home
    cname=wsjtx.home,delta.home
    cname=rumlog.home,echo.home

    何点かキーポイントがありますので、それらをメインに解説します。

    listen-addressとbind-dynamic

    問い合わせを受け付けるIPアドレスを指定します。これら以外のアドレス宛てのリクエストは受け付けません。一般的にはbind-interfaces指定でネットワークインタフェース/IPアドレスとの紐付けをしますが、dnsmasqより後にWireGuardが立ち上がる可能性があります。

    実際に立ち上がり順はdnsmasqが先だったため、bind-interfaces設定のままではdnsmasqlの起動に失敗しました。

    systemctlでサービスの依存関係 (起動順) を調整することでも解決できますが、今回はbind-dynamic指定で、後から (動的に) バインドできるようにしました。

    localise-queriesとhost-record

    一般的なdnsmasqの設定では /etc/hosts ファイルにIPアドレスとホスト名を列挙していきます。今回は、localise-queriesを指定し、VPN接続している端末からの問い合わせに対してはVPN側のIPアドレス (10.0.0.0/24) を、通常のLANからの端末に対してはLAN側のIPアドレス (192.168.10.0/24) を返すようにします。

    ホスト名とIPアドレスの紐付けは以下のような形式になります。

    host-record=ホスト名(,ホスト名),IPアドレス(,IPアドレス)

    今回はドメインなしのホスト名、ローカルドメインありのホスト名、LAN側のアドレス、VPN側のアドレスがありますので、上記の設定ファイルのようになります。

    なお、問い合わせ元のネットワークと合致するレコードがない場合は応答しないようです。

    cname

    いわゆるエイリアス、別名です。host-recordに実体を定義し、cnameで別名を定義します。こうすることで、物理名と論理名を分離して管理することができるようになります。

    例えば、ここでの設定例ではechoの別名にrumlogを設定しています。WSJT-XでUDPサーバにrumlogを指定しておけば、echoが壊れてbravoのRUMlogNGでログ受信するよう変更する場合に、DNS側でbraboの別名をrumlogを変更すれば、WSJT-X側は何も手を加える必要がない、という訳です。

    設定したら再起動です。

    $ sudo systemctl restart dnsmasq

    動作確認

    VPNに繋がない状態でdigを実行してみます。

    $ dig bravo +short
    10.0.0.2

    あれ? VPN側のアドレスが返ってきました。LAN側アドレス (192.168.10.192) が返ってきて欲しかったのですが……

    ChatGPTを詰めたところ、localise-queriesではhost-recordに設定されたアドレスがいずれもローカルネットワークの場合、どちらのネットワークを選択すればいいのか分からなくなることが判明。いやいやいやいや、そういうことは最初から言えよ > ChatGPT


    設定成功

    改めて、ネットワークインタフェースごとにDNSインスタンスを起動することにしました。ここではローカル側 (eth0; 192.168.10.1/24)  またはVPN側 (10.0.0.0/24) の二つのインスタンスを立ち上げることになります。どこから問い合わせたかではなく、誰に問い合わせたかによって応答を切り替える訳です。

    方針

    • LAN側のインスタンス (eth0, 192.168.10.191:53) に問い合わせ → LAN側のアドレスを返す

    • VPN側のインスタンス (wg0, 10.0.0.1:53) に問い合わせ → VPN側のアドレスを返す

    設定ファイル

    まずはLAN側の設定ファイルから。interfaceでLAN側NIC (eth0) を指定しています。追加で no-hosts を入れていますが、これがないと /etc/hosts を読み込んで127.0.1.1 のレコードを返してしまいます。

    $ sudo vi /etc/dnsmasq-lan.conf
    domain=home
    local=/home/
    expand-hosts
    
    no-hosts
    
    interface=eth0
    listen-address=127.0.0.1
    listen-address=192.168.10.191
    bind-dynamic
    
    cache-size=1000
    domain-needed
    bogus-priv
    
    # 上流DNSを使うなら必要に応じて追加
    # no-resolv
    # server=192.168.10.1
    
    # WireGuard VPN, DNS, RasPi5
    host-record=alpha,alpha.home,192.168.10.191
    
    # VNC client, MacBook Air
    host-record=bravo,bravo.home,192.168.10.192
    
    # VNC client, Mac mini @office
    host-record=charlie,charlie.home,192.168.10.193
    
    # WSJT-X/MSHV, GMKtec
    host-record=delta,delta.home,192.168.10.194
    
    # RUMlogNG, Mac mini @home
    host-record=echo,echo.home,192.168.10.195
    
    # CNAME
    cname=vpn.home,alpha.home
    cname=wsjtx.home,delta.home
    cname=rumlog.home,echo.home

    続いてVPN側インスタンスの設定ファイル。LAN側との違いはinterfaceと、except-interfaceでlo (ループバックデバイス) を指定していることです。これがないと127.0.0.1にbindしようとしてLAN側のインスタンスと衝突して起動に失敗します。

    $ sudo vi /etc/dnsmasq-vpn.conf
    domain=home
    local=/home/
    expand-hosts
    
    no-hosts
    
    interface=wg0
    except-interface=lo
    listen-address=10.0.0.1
    bind-dynamic
    
    cache-size=1000
    domain-needed
    bogus-priv
    
    # 上流DNSを使うなら必要に応じて追加
    # no-resolv
    # server=192.168.10.1
    
    # WireGuard VPN, DNS, RasPi5
    host-record=alpha,alpha.home,10.0.0.1
    
    # VNC client, MacBook Air
    host-record=bravo,bravo.home,10.0.0.2
    
    # VNC client, Mac mini @office
    host-record=charlie,charlie.home,10.0.0.3
    
    # WSJT-X/MSHV, GMKtec
    host-record=delta,delta.home,10.0.0.4
    
    # RUMlogNG, Mac mini @home
    host-record=echo,echo.home,10.0.0.5
    
    # CNAME
    cname=vpn.home,alpha.home
    cname=wsjtx.home,delta.home
    cname=rumlog.home,echo.home

    serviceファイル

    dnsmasq標準のserviceファイルは使えないので、自前で用意します。まずはLAN側のserviceファイルです。eth0が立ち上がってからサービスが起動するようにしています。

    $ sudo vi /etc/systemd/system/dnsmasq-lan.service 
    [Unit]
    Description=dnsmasq (LAN)
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=simple
    ExecStartPre=/usr/sbin/dnsmasq --test --conf-file=/etc/dnsmasq-lan.conf
    ExecStart=/usr/sbin/dnsmasq --keep-in-foreground --conf-file=/etc/dnsmasq-lan.conf
    ExecReload=/bin/kill -HUP $MAINPID
    Restart=on-failure
    RestartSec=2
    
    [Install]
    WantedBy=multi-user.target

    続いてVPN側のserviceファイル。こちらはWireGuardのwg0が立ち上がってからサービスが起動するようにしてあります。

    $ sudo vi /etc/systemd/system/dnsmasq-vpn.service 
    [Unit]
    Description=dnsmasq (VPN)
    After=network-online.target wg-quick@wg0.service
    Wants=network-online.target
    Requires=wg-quick@wg0.service
    
    [Service]
    Type=simple
    ExecStartPre=/usr/sbin/dnsmasq --test --conf-file=/etc/dnsmasq-vpn.conf
    ExecStart=/usr/sbin/dnsmasq --keep-in-foreground --conf-file=/etc/dnsmasq-vpn.conf
    ExecReload=/bin/kill -HUP $MAINPID
    Restart=on-failure
    RestartSec=2
    
    [Install]
    WantedBy=multi-user.target

    起動

    標準のdnsmasqを停止し、新たに設定した2つのインスタンスを起動します。

    $ sudo systemctl disable --now dnsmasq
    $ sudo systemctl enable --now dnsmasq-lan
    $ sudo systemctl enable --now dnsmasq-vpn

    確認

    digコマンドで確認してみます。

    $ dig @192.168.10.191 alpha +short
    192.168.10.191
    $ dig @192.168.10.191 bravo +short
    192.168.10.192
    $ dig @192.168.10.191 charlie +short
    192.168.10.193

    LAN側は問題なし。続いてVPN側です。

    $ dig @10.0.0.1 alpha +short
    10.0.0.1
    $ dig @10.0.0.1 bravo +short
    10.0.0.2
    $ dig @10.0.0.1 charlie +short
    10.0.0.3

    こちらも問題なさそうですね。これでようやく期待通りの動作になりました。


    VPNサーバ設定

    ファイアウォール設定

    DNS問い合わせに使われる53番ポートだけ開いておきたいところですが、ここでも設定をパス。ルータのファイアウォールに頑張ってもらいます。

    ※26/03/21追記: ufwの設定について個別に記事を起こしました;


    DHCPクライアント設定

    LAN側DNS

    プライマリDNSサーバとして、DHCPサーバから自動的に割り当てられるDNSサーバではなく、今回立てたLAN側のDNS (192.168.10.191) を参照するよう設定します。


    VPNクライアント設定

    VPN側DNS

    VPN接続したらVPN側のDNS (10.0.0.1) を参照するよう、VPN (WireGuard) クライアントの設定を変更します。具体的には、[Interface]の項にDNSを追記します。LinuxのNetworkManagerの場合はGUIから設定できます。

    [Interface]
    PrivateKey = (VPNサーバ公開鍵)
    Address = 10.0.0.2/24
    DNS = 10.0.0.1
    ...

    VPNを一旦切断して再接続します。VPNに再接続できたらIPアドレスではなくホスト名でpingを打ってみましょう。

    % ping alpha
    PING alpha (10.0.0.1): 56 data bytes
    64 bytes from 10.0.0.1: icmp_seq=0 ttl=64 time=15.563 ms
    64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=19.801 ms
    64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=20.965 ms
    64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=17.072 ms
    ...

    VPNから切断するとLAN側のDNSが有効になります。これで接続しているネットワークに合わせてホスト名を解決できるようになりました。


    WSJT-X設定

    UDPサーバ

    RUMlogNGホストをIPアドレス (10.0.0.5) で指定していた箇所をホスト名 (この例であれば echo.home) で指定できるようになりました。

    ただし、dnsmasqのcname設定の項でも説明した通り、後々のことを考慮すると、論理名の rumlog.home で指定した方がよいかと思います。


    改善

    もうちょっとだけ続くんじゃ。


     
     
    2024年5月に神戸市西区で開局した2アマのJQ3JUKです。アマチュア無線に関連する記事を掲載しています。FT8をメインにPOTA運用を行う合間を縫ってアパマン+移動運用でDXCC 200狙っています。響P。 https://www.qrz.com/db/jq3juk

    あなたへのおすすめ