Raspberry Piでサーバを作る

Raspberry Piで作ったサーバを自宅のルータに接続して、グローバルの固定IPアドレスを取得せずにダイナミックDNSドメイン名を割り当て、IPアドレスを固定せずにUPnPでポートを開放して、外部に公開してみる。
Raspberry Piをサーバにするために、OSとしてDebian GNU/LinuxベースのRaspbianをインストールする。
サーバとして使うので、インストールのためだけにディスプレイやキーボードを繋ぎたくないが、RaspbianのmicroSDカードにsshの名前で空のファイルを作成しておけば、LANケーブルを接続するだけでSSH接続によるリモート操作やファイル転送ができる。
当然ながら、Raspberry Pi Zero等はLANケーブルを接続するためにUSB LANアダプタを使う必要がある。

OSのダウンロードと解凍

Raspberry Pi公式サイト(英語)の「DOWNLOADS」→「RASPBIAN」→「RASPBIAN STRETCH LITE」の「Download ZIP」で「2018-06-27-raspbian-stretch-lite.zip」をダウンロードしたら解凍して「2018-04-18-raspbian-stretch-lite.img」を取り出す。
Windowsの場合は「2018-06-27-raspbian-stretch-lite.zip」を右クリック→すべて展開→展開で解凍できる。尚、この後にEtcherでmicroSDカードに書き込む場合は解凍せずにzipファイルを直接指定することも出来る。

  • ※STRETCH(コードネーム)や2018-06-27(日付)の部分は新しいバージョンが公開されるごとに変わる。

microSDカードにOSを書き込む

2GB以上のmicroSDカードを取り付けて、ddコマンド等で「2018-06-27-raspbian-stretch-lite.img」をmicroSDカードに書き込む。
Windowsの場合は、Raspberry Pi公式サイト(英語)の「DOWNLOADS」→「RASPBIAN」→「installation guide」→「Etcher」で、ETCHER公式サイト(英語)の「Download for Windows x64」*1で64ビット版Windowsインストーラーをダウンロードしたら、「Etcher-Setup-1.4.4-x64.exe」を実行→ライセンス契約書が出たら、同意する。
Etcherが起動したら、Select image→先ほど解凍した「2018-06-27-raspbian-stretch-lite.img」を選択して、開く→microSDカード以外が選択されていたら、Changeで変更→Flash!→このアプリがデバイスに変更を加えることを許可しますか?が出たら、はい→Flash Complete!が出たら、Etcherを閉じる。

SSH接続の設定

一旦、microSDカードを取り外して、再度取り付けたら、先頭のFATパーティション(ボリュームラベルがbootのドライブ)にsshの名前(拡張子なし)で空のファイルを作成する。
Windowsの場合は、スタートメニューを右クリック→ファイル名を指定して実行→名前に「CMD /C "COPY NUL D:\ssh"」と入力して、OK(「D:」の部分はボリュームラベルがbootのドライブ名)で空のファイルを作成する。

SSH接続

Raspberry PimicroSDカードとLANケーブルとACアダプタを取り付けて電源を入れると、SSHクライアントおよびSFTPクライアントから接続先ホスト名にraspberrypi.local、接続先ユーザー名にpi、接続先パスワードにraspberryを指定することでSSH接続できる。
Windowsの場合はmDNSでRaspberry Piのホスト名の名前解決ができないのでiTunesもしくはBonjour Print Servicesを予めインストールしておく。
Windows 10のsshコマンドは、コマンド プロンプト(スタートメニューを右クリック→ファイル名を指定して実行→名前に「cmd」を入力して、OK)を開き、ssh 接続先ユーザー名@接続先ホスト名(例:「ssh pi@raspberrypi.local」)でSSH接続、sftp 接続先ユーザー名@接続先ホスト名でSFTP接続できる(接続できない場合はユーザーフォルダ直下の.sshフォルダ内を削除(例:「DEL %USERPROFILE%\.ssh」)する)。初回のみ「Are you sure you want to continue connecting (yes/no)? 」が表示されるので「yes」と入力する。「接続先ユーザー名@接続先ホスト名's password: 」が出たら接続先パスワードを入力する。
sftpコマンドは、lsでファイルやディレクトリの一覧表示、cdで指定したディレクトリへ移動、getで指定したファイルを受信、putで指定したファイルを送信、exitでsftpコマンドの終了となる。
Windows 10 Fall Creators Update(バージョン 1709)の場合は標準でsshコマンドやsftpコマンドが入っていないので、スタートメニュー→設定→アプリ→アプリと機能→オプション機能の管理→機能の追加→OpenSSH Client (Beta)→インストールで、インストールした後に再起動する。
他のWindowsの場合は、PuTTY-ranvis等のSSHクライアントやWinSCP等のSFTPクライアントをインストールして使用する。
Raspberry PiSSH接続した後、「exit」でSSH接続終了、「sudo reboot」で再起動、「sudo poweroff」で電源が切れる。

MyDNS.JPに登録してドメインを設定

  1. MyDNS.JPの「JOIN US」(ユーザー登録)
  2. 「氏名」、「住所」、「電話番号」、「メール1」、「確認用キー」を入力して「CHECK」
  3. 「以下の内容でよろしければ、OKボタンを押してください。」が出たら「OK」
  4. 「ご登録ありがとうございました。」が出たら、先ほど入力したメールアドレスに届いたメールでマスターIDとパスワードを確認
  5. 「User Login」から「MasterID」と「Password」を入力して「LOG IN」
  6. 「DOMAIN INFO」
  7. 「Domain」に「example.mydns.jp」を入力して「CHECK」
  8. 「以下の内容でよろしければ、OKボタンを押してください。」が出たら「OK」
  • ※example.mydns.jpの部分は任意のドメイン名に置き換える。独自ドメインを持っている場合は、それを使うことも出来る。MyDNS.JPで無料のサブドメインを利用する場合、example.mydns.jp、example.mydns.bz、example.mydns.vc、example.mydns.tw、example.0am.jp、example.0g0.jp、example.0j0.jp、example.0t0.jp、example.pgw.jp、example.wjg.jp、example.server-on.net、example.live-on.net、example.keyword-on.net、example.dix.asia、example.daemon.asiaが利用できるので、exampleの部分は取得したい名前に置き換える。

パッケージの更新、別ユーザの作成、タイムゾーン、言語、ホスト名の変更と再起動

piユーザでSSH接続後、下記コマンドでパッケージ一覧の更新、インストール済みパッケージの更新、別のユーザの作成、別のユーザのパスワードを設定、タイムゾーンの変更、言語の変更、ホスト名の変更を行い、再起動する。

sudo apt-get update
sudo apt-get upgrade -y
sudo useradd -m -G sudo -s /bin/bash tmpuser
cat << EOT | sudo passwd tmpuser
tmppass
tmppass
EOT
history -c
sudo raspi-config nonint do_change_timezone Asia/Tokyo
sudo raspi-config nonint do_change_locale ja_JP.UTF-8
sudo raspi-config nonint do_hostname example
sudo reboot
  • ※tmpuser、tmppassの部分は一時的に作成する任意のユーザ名とパスワードに置き換える。
  • ※exampleの部分は任意のホスト名に置き換える。例えば、MyDNS.JPでexample.mydns.jpを設定した場合は、exampleをホスト名にする。
  • ※~/.bash_historyにパスワードが記載されてしまうので「history -c」でコマンド履歴を削除している。

ユーザ名、パスワードの変更、ファームウェアの更新と再起動

一時的に作成したユーザでSSH接続後、下記コマンドでpiユーザのパスワード無しsudo設定を削除、piユーザのユーザ名、ホームディレクトリ、グループ名、パスワードの変更、Raspberry Piファームウェアの更新を行い、再起動する。

sudo rm /etc/sudoers.d/010_pi-nopasswd
sudo usermod -l chguser pi
sudo usermod -d /home/chguser -m chguser
sudo groupmod -n chguser pi
cat << EOT | sudo passwd chguser
chgpass
chgpass
EOT
history -c
sudo rpi-update
sudo reboot
  • ※sudoコマンド実行時、「[sudo] tmpuser のパスワード:」(tmpuserの部分は一時的に作成したユーザ名)が出たら、一時的に作成したユーザのパスワードを入力する。
  • ※chguser、chgpassの部分はpiユーザから変更する任意のユーザ名とパスワードに置き換える。
  • ※~/.bash_historyにパスワードが記載されてしまうので「history -c」でコマンド履歴を削除している。

別のユーザの削除、NTPのインストール、ポート開放ツールのインストール、ポート開放スクリプトの作成、ポート開放cronジョブの作成

piユーザから変更したユーザでSSH接続後、下記コマンドで別のユーザを削除、時計をNTPサーバで同期させるためにNTPをインストール、ポート開放ツールのMiniUPnPをインストール、現在のIPアドレスを取得して開放しようとしているポートが既に他のIPアドレスで開かれていたら閉鎖、その後にポートを開放して、MyDNS.JPのダイナミックDNSを更新するシェルスクリプトを作成し、パスワードを含むシェルスクリプトを他のユーザから見えないようにパーミッションを設定し、これを5分ごとに実行するcronジョブを作成する。

sudo userdel -r tmpuser
sudo apt-get install -y ntp
sudo apt-get install -y miniupnpc
cat << 'EOT' | sudo tee /usr/local/bin/mydnsupdate.sh
#!/bin/sh
tmpfile=`mktemp`
upnpc -l > $tmpfile 2>&1
nowip=`sed -n -e "s/Local LAN ip address : //p" $tmpfile`
for port in 22; do
oldip=`sed -n -e "s/.*TCP *$port->\([0-9.]*\).*/\1/p" $tmpfile`
if [ -n "$oldip" -a "$oldip" != "$nowip" ]; then upnpc -d $port TCP > /dev/null 2>&1; fi
upnpc -a $nowip $port $port TCP > /dev/null 2>&1
done
rm $tmpfile
wget -O - https://mydns123456:abcDEFghi7G@ipv4.mydns.jp/login.html > /dev/null 2>&1
wget -O - https://mydns123456:abcDEFghi7G@ipv6.mydns.jp/login.html > /dev/null 2>&1
EOT
history -c
sudo chmod 700 /usr/local/bin/mydnsupdate.sh
sudo sh -c 'echo "*/5 * * * *  root  /usr/local/bin/mydnsupdate.sh" > /etc/cron.d/mydnsupdate'
  • ※sudoコマンド実行時、「[sudo] chguser のパスワード:」(chguserの部分はpiユーザから変更したユーザ名)が出たら、piユーザから変更したユーザのパスワードを入力する。
  • ※tmpuserの部分は一時的に作成したユーザ名に置き換える。
  • ※mydns123456とabcDEFghi7Gの部分は、MyDNS.JP登録時にメールで届いたマスターIDとパスワードに置き換える。
  • ※~/.bash_historyにパスワードが記載されてしまうので「history -c」でコマンド履歴を削除している。

以後、5分以内にポート開放が行われ、外部からMyDNS.JPに設定したドメインをホスト名として外部からSSHクライアントやSFTPクライアントで接続できるようになる。

Sambaのインストールと共有フォルダの作成

下記コマンドでSambaをインストールする。

sudo apt-get install -y samba

以後、example.localのように末尾に.localを付けなくても、ホスト名(例:example)だけでWindowsからアクセス出来るようになり、iTunesBonjourも不要となる。
下記コマンドでSambaの設定ファイルにRaspbian側の文字コードUTF-8Windows側の文字コードをCP932とする設定を追加し、ユーザのホームディレクトリを共有フォルダとする設定を追加して、Sambaを再起動する。

sudo sed -i -e '/^\[global\]/a\   unix charset = UTF-8\n   dos charset = CP932' /etc/samba/smb.conf
sudo sh -c "echo '[chguser]' >> /etc/samba/smb.conf"
sudo sh -c "echo '   path = /home/chguser' >> /etc/samba/smb.conf"
sudo sh -c "echo '   guest ok = yes' >> /etc/samba/smb.conf"
sudo sh -c "echo '   read only = no' >> /etc/samba/smb.conf"
sudo sh -c "echo '   force user = chguser' >> /etc/samba/smb.conf"
sudo systemctl restart smbd
  • ※chguserの部分はpiユーザから変更したユーザ名に置き換える。
  • ※[chguser]の部分が共有フォルダ名、path = /home/chguserの部分が共有フォルダにするディレクトリ、force user = chguserの部分が共有フォルダにアクセスする際のユーザ名となる。

*1:32ビット版Windowsの場合は「Download for Windows x64」右隣の「▼」から「Etcher for Windows x86 (32-bit) (Installer)」を選択してダウンロードする