コンテンツにスキップ

Troubleshoot

突然共有フォルダに繋がらなくなった時の話

なぜか同じサーバーのSMBファイル共有に繋がらなくなったので、トラブルシュート手順のメモ。

アクセス権を確認

Get-SmbShareAccess -Name "共有フォルダ名"
icacls "C:\共有フォルダのパス"

アクセス権は問題ない。

SMB設定を確認

Get-SmbServerConfiguration | Select EnableSMB1Protocol, EnableSMB2Protocol

これもSMB2だけが有効にできている。

Windowsアップデートを確認

Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 10

ちょうど問題が起きたあたりにアップデートがあり、再起動待ちだったので再起動するも解決せず。

Windowsイベントログを確認

Get-WinEvent -LogName "Microsoft-Windows-SmbServer/Operational" -MaxEvents 30 | Select-Object TimeCreated, Message | Format-List

失敗のログらしきものは見当たらない。

Windowsファイアウォールを確認

Get-NetFirewallRule -DisplayName "*ファイルとプリンターの共有*" | Select-Object DisplayName, Enabled, Direction

SMB 受信 (Inbound) のルールはTrueになっているので、ファイアウォールは一見問題なさそう…がこれが罠だった(後述)

NTLMv1設定を確認

WindowsUpdateが何か書き換えたのか?と疑って色々確認。

Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "LmCompatibilityLevel"

設定してないので出ない。

SMB用のポートを確認

netstat -an | findstr ":445"

LISTENINGになっている。

クライアントから確認

ここで端末がiPadだったので、 blink shell からping, nc -zv host 445 してもタイムアウトすることを確認。一方でSSH接続には問題ない。やっぱFirewallでは?

もう一度Firewallを確認

一度無効化すると、問題なく接続できることを確認できた。

Set-NetFirewallProfile -All -Enabled False

ので、いったん戻す。

Set-NetFirewallProfile -All -Enabled True

SMB 受信 のルールで確認すると、プライベートのネットワークのルールが無効化されていた。

Get-NetFirewallRule -DisplayName "*SMB 受信*" | Select-Object DisplayName, Enabled, Direction

プロファイルのルールを明示的に許可 → 解決!

いちおうプロファイルを確認しておいて、

Get-NetConnectionProfile
Get-NetFirewallProfile | Select-Object Name, Enabled

設定すると自分の接続しているプロファイルのルールが書き換わる。

Set-NetFirewallRule -DisplayName "ファイルとプリンターの共有 (SMB 受信)" -Enabled True

設定の直後にちゃんと通るようになった。

原因: ネットワークプロファイルを変更したから、別ルールの扱いになっていた

タイミング的にはWindowsアップデートかな?と思ったけど、一つ前のSSH接続の時にそういえばネットワークプロファイルをパブリックからプライベートに変えたなーと思い出した。 -DisplayName "*ファイルとプリンターの共有*" のルールセット上では問題なく許可できているように見えているが、実際のところ SMB 受信 ではパブリックのみ許可になっていたので、プライベートプロファイルにも許可することで通信が通るようになった。確かに最初よく考えずに一番厳しそうなパブリックにしとこ、みたいにやったなぁ。。。

おまけ: 明示的な新規ルール

明示的に新しいルールを作るときはプロファイルも指定して許可

New-NetFirewallRule -DisplayName "SMB Inbound Private" -Direction Inbound -Protocol TCP -LocalPort 445 -Action Allow -Profile Private

WindowsにSSH公開鍵認証でログインしようとしてハマった

WindowsにOpenSSHをインストールしてパスワードなしのSSH公開鍵認証を設定しようとしたところ、Linuxとは異なるいくつかの罠にはまったのでその記録。

環境

  • サーバー:Windows 11 Pro(OpenSSH for Windows 9.5)
  • クライアント:Debian Linux(OpenSSH 10.0)
  • ログインユーザー:ansible

基本的な設定手順

この手順で実行すれば成功する。

1. Windows側でユーザーを作成し、ログオン(重要)

ユーザー作成はコントロールパネルでもコンピューターの管理でもいいが、そのあと mkdir とかでユーザーディレクトリを作ってはいけない。 必ず一度対話型ログオンをしておくこと。

2. クライアント側で鍵ペアを生成

ssh-keygen -t ed25519

3. SSHサーバーをインストール

名前を確認してから Add-WindowsCapability でインストール

Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
Add-WindowsCapability -online -name OpenSSH.Server~~~~0.0.1.0

サービスの状態を確認しつつ起動し、自動開始に設定する。

Get-Service -Name sshd
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'

4. sshd_configの確認

C:\ProgramData\ssh\sshd_config で以下を確認する。

PermitRootLogin no # お好みで
PubkeyAuthentication yes
PasswordAuthentication no # お好みで
AuthorizedKeysFile .ssh/authorized_keys

また、管理者ユーザーの場合は末尾の以下のブロックをコメントアウトしておく。
コメントアウトしないと authorized_keys の参照先が別のパスになってしまう。

# Match Group administrators
#     AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

書き換えた後はサービスを再起動

Start-Service sshd

5. 公開鍵の登録

ssh-copy-id はWindows Serverに対して使えないので(後述)、以下のコマンドで直接コピーする。

cat ~/.ssh/id_ed25519.pub | ssh user@server "powershell -Command \"\$input | Out-File -Encoding utf8 -FilePath 'C:\\Users\\ansible\\.ssh\\authorized_keys' -Append\""

6. 権限の設定

.ssh ディレクトリと authorized_keys の両方から余計な権限を取り除く。

icacls "C:\Users\ansible\.ssh" /inheritance:r `
    /grant "NT AUTHORITY\SYSTEM:(OI)(CI)(F)" `
    /grant "BUILTIN\Administrators:(OI)(CI)(F)"

icacls "C:\Users\ansible\.ssh\authorized_keys" /inheritance:r `
    /grant "NT AUTHORITY\SYSTEM:(F)" `
    /grant "BUILTIN\Administrators:(F)"

ハマりポイント

① 手動でプロファイルディレクトリを作ってはいけない

ansibleユーザーを作成する前に(あるいは作成直後に)C:\Users\ansible を手動で作成しておくと、ユーザーの初回ログオン時にWindowsがそのディレクトリが既に存在することを検知し、C:\Users\ansible.hostname(ホスト名サフィックス付き)という別のディレクトリをプロファイルとして作成してしまう。

SSHデーモンは実際のプロファイルディレクトリを参照するため、C:\Users\ansible\.ssh\authorized_keys に鍵を置いても読まれない。

対策: ユーザー作成後はWindowsの初回ログオン時にプロファイルディレクトリを自動生成させる。手動では作らない。

ssh-copy-id はWindows Serverに対して使えない

ssh-copy-id は内部で exec sh を実行しようとするが、Windows側にshellがないためコマンドが失敗する。厄介なことに、エラーメッセージが出ていても最終的に「Number of key(s) added: 1」と表示されるため成功したように見えてしまう。実際にはファイルは作成されていない。

'exec' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
Number of key(s) added: 1   ← 嘘

対策: PowerShellのコマンドを直接実行して公開鍵をコピーする。

.ssh ディレクトリ自体の権限も厳格に管理される

authorized_keys の権限だけ絞っても、親の .ssh ディレクトリに UsersEveryone が残っていると認証が拒否される。ディレクトリと authorized_keys の両方の権限を設定する必要がある。


トラブルシュートのコツ

認証が通らないときはクライアント側で -v オプションをつけて接続する。

ssh -v ansible@server

Offering public key の直後に Authentications that can continue が出て鍵が拒否されている場合は、サーバー側のイベントログを確認する。

Get-WinEvent -LogName "OpenSSH/Operational" -MaxEvents 30 | Select-Object TimeCreated, Message | Format-List

Raspberry Pi 3B + Trixie で Wi-Fi が突然認識されなくなった話

環境

  • ボード: Raspberry Pi 3B
  • OS: Raspberry Pi OS Trixie (Debian 13ベース)

症状

新規インストールして apt upgrade 後に Wi-Fi が接続されなくなった。

経緯: sudo apt upgradeしたらハングした

新規セットアップし、Wi-Fiも繋いで sudo apt update && sudo apt upgrade をした。時間がかかったので放置して置いたらセッションが切れてしまい、再ログインしようとするとWi-Fiに割り当てたはずの固定IPでログインできない。

取り急ぎ有線でログインして様子を見ようとしたものの、sudoできなくなっている。プロセスを見ると前日実行した sudo apt updgrade がそのまま残っていたので、まずこれを kill

$ ps aux | grep apt 
root 2067 0.0 0.6 20580 6336 ? S Apr01 0:00 sudo apt upgrade 
root 2069 0.0 0.2 20580 2300 ? Ss Apr01 0:00 sudo apt upgrade 
root 2070 0.1 11.5 126508 107308 ? S Apr01 0:44 apt upgrade 

$ sudo kill -9 2067 2069 2070

終わったらロックファイルを削除:

sudo rm /var/lib/dpkg/lock-frontend
sudo rm /var/lib/dpkg/lock
sudo rm /var/cache/apt/archives/lock

dpkbの状態を修復してから:

$ sudo dpkg --configure -a

Setting up rpi-chromium-mods (20260211) ... Configuration file '/etc/chromium/master_preferences' ==> Modified (by you or by a script) since installation. ==> Package distributor has shipped an updated version. What would you like to do about it ? Your options are: Y or I : install the package maintainer's version N or O : keep your currently-installed version D : show the differences between the versions Z : start a shell to examine the situation The default action is to keep your current version. *** master_preferences (Y/I/N/O/D/Z) [default=N] ? 

# Yで続行

改めてアップグレード:

sudo apt upgrade

Wi-Fiが繋がらなくなった

ここでWi-Fiの様子を見る

$ ip a show wlan0
Device "wlan0" does not exist.

nmcli connection show では接続プロファイル(netplan-wlan0-homewifi)は存在しているのに、デバイス自体が見えていない。なんでや


調査の経緯

1. nmcli で状態確認

nmcli connection show
nmcli device status

接続プロファイルは存在しているが、wlan0 デバイスは --(未接続)。

ip link show

loeth0docker0 のみ表示され、wlan0 が存在しない。

3. dmesg でドライバ確認

ここからはClaudeちゃんに相談。

Linuxカーネルは起動時からずっと、ハードウェアの検出・ドライバのロード・デバイスの初期化などのログを内部バッファに記録し続けています。dmesg はそのバッファの内容を表示します。

とのことで、 dmesg をチェック。

このラズパイのWi-FiドライバはBroadcom製だそうで、 brcm で検索。

dmesg | grep -i brcm
dmesg | grep -i firmware

Bluetoothドライバはロードされているが、Wi-Fiドライバがロードされていない。

dmesg | grep -i brcmfmac
usbcore: registered new interface driver brcmfmac

Wi-Fi ドライバ brcmfmac が USB ドライバとしてのみ登録されており、本来あるべき SDIO ドライバとして認識されていない

4. mmc ログ確認

Claude曰く、

MMC は MultiMediaCard の略で、SDカードなどのストレージ規格のことです。
ただしLinuxカーネルでは意味が少し広く、SDカード・eMMC・SDIOデバイスをまとめてMMCサブシステムとして管理しています。

Pi 3Bの場合:

デバイス 用途
mmc0 SDカードスロット(OSが入っているやつ)
mmc1 Wi-Fi/BluetoothチップへのSDIOバス

SDIO(Secure Digital Input/Output)はSDカードの規格を拡張したもので、ストレージだけでなくWi-FiやBluetoothなどの通信チップを接続するためにも使われています。Pi 3BのWi-Fiチップ(BCM43430)はSDカードと同じバスに繋がっていて、カーネルからは mmc1 として見えています。

というわけでこれを探してみる。

dmesg | grep -i mmc
[ 2.672012] mmc-bcm2835 3f300000.mmcnr: mmc_debug:0 mmc_debug2:0 
[ 2.672035] mmc-bcm2835 3f300000.mmcnr: DMA channel allocated
mmc1: Failed to initialize a non-removable card

Wi-Fi チップが接続されている mmc1(SDIOスロット)の初期化に失敗していたことがわかる。このFailedは起動時の一回だけ出る。

5. デバイスツリーで status 確認

cat /proc/device-tree/model
ls /proc/device-tree/soc/

ここで mmc@7e202000mmcnr@7e300000 の両方が見えており

mmcnr@7e3000007e300000 はBCM2835(Pi 3Bのチップ)のメモリマップで mmcnr(MMC Non-Removable)に割り当てられた番地です。dmesg でも同じアドレスが出ていました:

mmc-bcm2835 3f300000.mmcnr: ...

3f7eは同じ物理アドレスを別の視点から見たもの)
また、 mmcnrnrNon-Removable の略です。取り外せないMMCデバイス=Wi-Fiチップのことだと推測できます。SDカードスロットは取り外し可能なので mmc@7e202000 の方です。

mmcnr@7e300000 がWi-Fi用のSDIOスロットのはず、ということで

ls /proc/device-tree/soc/mmcnr@7e300000/

を見ると中に wifi@1 が見えて、デバイスツリー上はWi-Fiノードが存在しているということがわかる。

cat /proc/device-tree/soc/mmcnr@7e300000/status

を見ると返るのが

disabled

デバイスツリー上で Wi-Fi が disabled になっていた。 なんでや

ここで更にClaudeからDTBを見るよう言われる:

DTB は Device Tree Blob の略で、ハードウェアの構成情報をバイナリ形式で記述したファイルです。
Linuxカーネルは起動時に「このボードにはどんなハードウェアが繋がっているか」を知る必要があります。x86 PC はその情報を BIOS/UEFI から得ますが、Raspberry Pi のような組み込みボードには BIOS がないので、代わりに DTB をカーネルに渡して教えています。
関連する用語を整理するとこうなります:

用語 意味
DTS Device Tree Source。人間が読めるテキスト形式
DTB Device Tree Blob。DTSをコンパイルしたバイナリ形式
dtc DTSとDTBを相互変換するコンパイラ
dtoverlay 起動時にDTBの一部を上書きするパッチ
# dtc -I dtb -O dts /boot/firmware/bcm2710-rpi-3-b.dtb 
#     ^^^^^^^ ^^^^^^ 
#     入力DTB 出力DTS(人間が読めるテキストに変換)
dtc -I dtb -O dts /boot/firmware/bcm2710-rpi-3-b.dtb 2>/dev/null \
  | grep -A20 "mmcnr@7e300000 {" | grep status
# → status = "okay";

ベースの DTB ファイルでは okay になっているにもかかわらず、 実際に起動時に適用されたデバイスツリー /proc/device-tree/ では disabled ...起動時に何かが書き換えている?

6. Bluetooth との競合が原因と判明

もうさっぱり分らんのでClaudeちゃんに推測してもらう。

Raspberry Pi 3B は Bluetooth と Wi-Fi が同じ SDIO バスを共有しているapt upgrade によって Bluetooth 関連パッケージが更新され、リソース割り当てが変わったことで Wi-Fi の SDIO 初期化が失敗するようになったと考えられる。

わかるか、そんなもの!


解決方法

結局Bluetoothを無効にするしかないっぽいので、そのようにする。いずれ修正されるであろう。。。

/boot/firmware/config.txt[all] セクションに以下を追加:

dtoverlay=disable-bt
sudo nano /boot/firmware/config.txt
[all]
enable_uart=1
dtoverlay=disable-bt   # ← これを追加

保存して再起動:

sudo reboot

再起動後、wlan0 が正常に認識され、Wi-Fi に接続できた。

$ ip a show wlan0
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
    inet 192.168.1.95/24 ...

原因まとめ

項目 内容
直接原因 mmcnr@7e300000(Wi-Fi の SDIO スロット)が起動時に disabled になる
根本原因 Bluetooth と Wi-Fi の SDIO バス競合
トリガー apt upgrade による Bluetooth 関連パッケージの更新
解決策 dtoverlay=disable-bt で Bluetooth を無効化し競合を解消

補足

disable-bt を追加した場合、enable_uart=1 はそのまま残して問題ない。むしろこの2つはセットで使われることが多い組み合わせ。

ヘッドレスサーバー用途で不要だったので今回はBluetoothを潰して対応したが、どっちも必要な場合の対策は不明。

この記事はかなりClaudeにお世話になりました。直面した課題に適した未知のコマンドや結果の読み方を教えてくれるので、実に助かっています。