自宅サーバーにLAN内外からドメイン名でアクセスしたい
ファイルサーバーとかを自宅に建てて,httpsで自宅外(例えば仕事場)からアクセスできるようにしている人は結構いると思います.
MacBookを持ち歩くようなタイプの人間は,自宅の内外問わずMacBookを膝の上で使うと思います.
そんな時,自宅サーバーに対して外出先ではhogehoge.comでアクセスして,自宅ではサーバーのローカルIPでアクセスするなんていうめんどくさいことをしないといけないシチュエーションがあります.
自宅でも外出先でも,hogehoge.comでアクセスしたい! という人向けの記事です.
(こちらの方法が理想的だったのですが,できなかったので妥協案として.やりたいことは基本同じです.)
解決法:接続されたWi-FiのSSIDを検出して,自宅内外に応じたhostsファイルを切り替える
です.自宅のWi-Fiにつながっている(=サーバーと同一ネットワーク内にいる)時は,サーバーのローカルIPとドメイン名hogehoge.comを結びつけたhostsファイルを適用して,それ以外の時はその結びつきのないhostsファイルを適用することで,「自宅外からhogehoge.comでアクセスしようとしたときにローカルIPに向かってしまって正しくサーバーにアクセスできない」という事態を回避します.
MacOSでの方法を備忘録としてメモしておきます.
ざっくりした流れは下記の通り.
- hosts.local, hosts.externalを用意する(それぞれ自宅内外用)
- SSIDをに応じてhostsファイルを切り替えるシェルスクリプトを作る
- Wi-Fi接続が切り替わったタイミングで作動するlaunchdジョブを作る
です.
1. hosts.local, hosts.externalの作成
通常のhostsファイルをまずはhosts.localとhosts.externalに複製して,.localのほうののみ,下の通りサーバーのローカルIPとドメインの対応付けを追記します.
xxx.xxx.xx.xx(サーバーのローカルIP) hogehoge.com(ドメイン)
2. SSIDに応じてhostsファイルを切り替えるシェルスクリプト
airportというコマンドでSSIDを取得する方法があるみたいですが,2025年時点では非推奨っぽいので,別の方法.
こちらを使いました.
やってることとしては,「SSIDを取得して,自宅Wi-FiのSSIDだったら,hostsをhosts.localで置き換えて,自宅外のネットワークだったらhosts.externalで置き換える」 という処理です.
#!/bin/bash
TARGET_SSID="aterm-xxxxx(自宅のルーターのSSID)"
INTERFACE="en0(MacBookでWi-Fiなら大体これだと思います)"
#system_profilerを使った,現在接続されているWi-FiのSSID取得.
CURRENT_SSID=$(system_profiler SPAirPortDataType | awk '/Current Network/ {getline;$1=$1;print $0 | "tr -d ':'";exit}')
#SSIDに応じたhostsファイル切り替え
if [ "$CURRENT_SSID" = "$TARGET_SSID" ]; then
echo "Connected to LAN ($CURRENT_SSID): applying hosts.local"
sudo cp /etc/hosts.local /etc/hosts #<-hostsファイルの置き場.hosts.localは別の場所でもいいと思います.
else
echo "Connected to external ($CURRENT_SSID): applying hosts.external"
sudo cp /etc/hosts.external /etc/hosts #<-hosts.externalは上と同じくどこでもいいと思います.
fi
作成したshファイルには実行権限を与えておきましょう.
また,パスワードなしでこの処理ができるようにしておきます.
sudo visudo
で,
yourusername ALL=(ALL) NOPASSWD: /bin/cp /etc/hosts.local /etc/hosts, /bin/cp /etc/hosts.external /etc/hosts
と追記.yourusernameは自身のユーザー名に置き換えましょう.hosts.local, hosts.externalのパスも自分が配置した場所に
3. Wi-Fi接続が切り替わったタイミングで作動するlaunchdジョブ
MacOSでは,Wi-Fiが切り替わると,~/Library/Preferences/SystemConfiguration/内のファイルが更新されるみたいなので,それをトリガーとして利用します.
/Users/username/Library/LaunchAgents/に,次のようにジョブを作ります.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.switchhosts</string>
<key>ProgramArguments</key>
<array>
<!-- switch_hosts.shの場所 -->
<string>/path/to/switch_hosts.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<!-- SystemConfiguration/の変化検出 -->
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration</string>
</array>
<!-- ログの出力 -->
<key>StandardOutPath</key>
<string>/tmp/switchhosts.out</string>
<key>StandardErrorPath</key>
<string>/tmp/switchhosts.err</string>
</dict>
</plist>
そしたら
launchctl load ~/Library/LaunchAgents/com.user.switchhosts.plist
でジョブをロードします.
これで,Wi-Fiが切り替わったタイミングでジョブが実行され,ジョブに記載されたshが実行されることでhostsファイルが切り替わります.
以上
おわりに
多分,サーバーと同じネットワーク内に,DNSサーバーを建てたりするのが普通のやり方だと思うのですが,別にこれで困らないならそれでいいと思います.そんなにめんどくさくもなかったし.