#はじめに
VPNプロトコルとしてWiregardがLinuxカーネル5.6にマージされました。
PPTPよりセキュアでIPSecより簡易なようで、今後使う機会が出てくるかもしれないと思い、余っていたRaspberry pi 2 model B rev1.1でVPNサーバーを作ってみます。
raspbian-buster-liteの2020-02-13版を使用します。
SDboot+USBroot化
一応サーバーなのでSDカードで運用するのは不安がありますので、SSDなどをUSBに接続してUSBブートにしておきたいです。
しかし、2020/5/10時点で正式にUSBブート出来るRaspberry piは以下のものになります。
- Raspberry pi 2 model B rev 1.2
- Raspberry pi 3 model B/B+
今回使用しようとしているボードはこれに当てはまりません。
なお、リビジョンなど不明な場合は、以下のコマンドで確認出来ますので、適当にraspbianを起動して確認して下さい。
pi@raspberrypi:~ $ cat /proc/device-tree/model
Raspberry Pi 2 Model B Rev 1.1
対応出来ないとあきらめるて、高品質SDで運用してもいいですが、わざわざ追加投資したくないので、Raspberry pi 1 の頃から多々事例のあるSDカードでブートし、root領域を別ストレージにする方法を適用しようと思います。
(なお、この手法はRaspberry pi4にも適用出来るはずです。[未確認])
準備
いろいろ手順がありますが、今回は以下の手順で行います。
- SDカードで通常起動
- USBストレージ準備
- USBストレージ内の領域をroot領域にする
raspbianのサイズから、SDカードは2GB以上のものが最初に必要になります。
(boot用のSDカードは、boot領域のみ必要ですので、bootのみの256MB程度のSDカードに差し替える事も出来ます。今回はやりません。)
今回は手元にあった2BGのSDカードと4GBのUSBメモリで手順を進めます。
SDカードで起動
SDカードにraspbianを書き込み、USBメモリを接続して起動します。
(私はsshを有効化し、ディスプレイなどは無しにしています。このあたりの操作は解説しませんので、何らかの方法でログインし、コマンドを実行できるようにして下さい。)
SDカードは/dev/mmcblk0、USBメモリは私の環境では/dev/sdaになりましたので、コマンドはこれに合わせています。
USBストレージ準備
USBストレージの全領域をpartedコマンドでext4パーティションにします。
(すでに使用した事があるUSBメモリでは、パーティションの削除などを行って下さい。)
pi@raspberrypi:~ $ sudo parted /dev/sda
GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) mklabel gpt
Warning: The existing disk label on /dev/sda will be destroyed and all data on this disk will be lost. Do you want to
continue?
Yes/No? yes
(parted) mkpart primary ext4 0% 100%
(parted) p
Model: Generic USB Flash Disk (scsi)
Disk /dev/sda: 4074MB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 1049kB 4073MB 4072MB ext4 primary
(parted) q
Information: You may need to update /etc/fstab.
作成した領域に、SDカードのroot領域である/dev/mmcblk0p2をコピーします。
(ddを使用しますので要注意、ifとofの指定を間違えるとデータが消え、書き込みからやり直しになります。)
pi@raspberrypi:~ $ sudo dd if=/dev/mmcblk0p2 of=/dev/sda1 bs=32M conv=noerror,sync status=progress
1711276032 bytes (1.7 GB, 1.6 GiB) copied, 280 s, 6.1 MB/s
50+1 records in
51+0 records out
1711276032 bytes (1.7 GB, 1.6 GiB) copied, 315.463 s, 5.4 MB/s
サイズの違うパーティションのデータをコピーしたので、サイズ情報などがずれた状態になっています。
これをe2fsckとresize2fsで修復します。
pi@raspberrypi:~ $ sudo e2fsck -f /dev/sda1
e2fsck 1.44.5 (15-Dec-2018)
rootfs: recovering journal
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Free blocks count wrong (122034, counted=81319).
proc /proc proc defaults 0 0
Fix<y>? yes
console=serial0,115200 console=tty1 root=PARTUUID=e68eb608-224a-4209-bcb8-16a11bce5c55 rootfstype=ext4 elevator=deadlineFree inodes count wrong (59995, counted=59936).
Fix<y>? yes
rootfs: ***** FILE SYSTEM WAS MODIFIED *****
rootfs: 44480/104416 files (0.3% non-contiguous), 332377/413696 blocks
pi@raspberrypi:~ $ sudo resize2fs /dev/sda1
resize2fs 1.44.5 (15-Dec-2018)
Resizing the filesystem on /dev/sda1 to 994048 (4k) blocks.
The filesystem on /dev/sda1 is now 994048 (4k) blocks long.
e2fsckは何度か「Fix<y>?
」と問い合わせが発生しますので、発生する都度「y(yes)」を入力して下さい。
USBストレージ内の領域をroot領域にする
データ領域は準備出来ましたので、/dev/sda1をroot領域にする様操作します。
まず、パーティションのuuidを確認します。
pi@raspberrypi:~ $ ls -l /dev/disk/by-partuuid/
total 0
lrwxrwxrwx 1 root root 15 Feb 13 16:10 738a4d67-01 -> ../../mmcblk0p1
lrwxrwxrwx 1 root root 15 Feb 13 16:10 738a4d67-02 -> ../../mmcblk0p2
lrwxrwxrwx 1 root root 10 May 10 09:21 e68eb608-224a-4209-bcb8-16a11bce5c55 -> ../../sda1
このuuidを使用して/boot/cmdline.txtを修正します。
pi@raspberrypi:~ $ sudo vi /boot/cmdline.txt
console=tty1 root=PARTUUID=738a4d67-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
↓
console=tty1 root=PARTUUID=e68eb608-224a-4209-bcb8-16a11bce5c55 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
「root=PARTUUID=738a4d67-02」を「root=PARTUUID=e68eb608-224a-4209-bcb8-16a11bce5c55」に変更します。
再起動してデータ領域を確認すると以下の様になっています。
pi@raspberrypi:~ $ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 3.8G 1.3G 2.3G 35% /
devtmpfs 459M 0 459M 0% /dev
tmpfs 464M 0 464M 0% /dev/shm
tmpfs 464M 18M 446M 4% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 464M 0 464M 0% /sys/fs/cgroup
/dev/mmcblk0p1 253M 53M 200M 21% /boot
tmpfs 93M 0 93M 0% /run/user/1000
このままでも問題はないようですが、念のため/etc/fstabも修正します。
pi@raspberrypi:~ $ sudo vi /etc/fstab
proc /proc proc defaults 0 0
PARTUUID=738a4d67-01 /boot vfat defaults 0 2
PARTUUID=738a4d67-02 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off] for that
↓
proc /proc proc defaults 0 0
PARTUUID=738a4d67-01 /boot vfat defaults 0 2
PARTUUID=e68eb608-224a-4209-bcb8-16a11bce5c55 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off] for that
「PARTUUID=738a4d67-02」を「PARTUUID=e68eb608-224a-4209-bcb8-16a11bce5c55」に修正します。
問題なく再起動出来たら、「raspi-config」などを使用し、必要な初期設定を行って下さい。
IPアドレス固定と、ホスト名変更は行う事をお勧めします。
wireguard(サーバー)
インストール
各種 OS のインストール方法は公式サイトで紹介されています。
https://www.wireguard.com/install/
raspbianは正規リポジトリにパッケージがありませんので、公式ドキュメントには説明が内容です。
他に参考にできるドキュメントを探すと、denianのリポジトリを使用する方法をいろいろな方が実践しているようです。
私はその中で以下のドキュメントを参考にしました。
https://github.com/adrianmihalko/raspberrypiwireguard
(Raspberry Pi 2 v1.2 and above)となっていますが特に問題ないようです。
pi@raspberrypi:~ $ sudo apt-get update
pi@raspberrypi:~ $ sudo apt-get upgrade
pi@raspberrypi:~ $ sudo apt-get install raspberrypi-kernel-headers
pi@raspberrypi:~ $ echo "deb http://deb.debian.org/debian/ unstable main" | sudo tee --append /etc/apt/sources.list.d/unstable.list
pi@raspberrypi:~ $ sudo apt-get install dirmngr
pi@raspberrypi:~ $ wget -O - https://ftp-master.debian.org/keys/archive-key-$(lsb_release -sr).asc | sudo apt-key add -
pi@raspberrypi:~ $ printf 'Package: *\nPin: release a=unstable\nPin-Priority: 150\n' | sudo tee --append /etc/apt/preferences.d/limit-unstable
pi@raspberrypi:~ $ sudo apt-get update
pi@raspberrypi:~ $ sudo apt-get install wireguard
pi@raspberrypi:~ $ sudo reboot
/etc/sysctl.conf を編集し、「net.ipv4.ip_forward」の項目を 1 にする。
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
鍵作成
サーバー側とクライアント用の秘密鍵と公開鍵を作成します。
ファイルの置き場所はsshと分けるので、「~/wgkeys」に生成します。
pi@raspberrypi:~ $ mkdir wgkeys
pi@raspberrypi:~ $ cd wgkeys
pi@raspberrypi:~/wgkeys $ wg genkey > server_private.key
Warning: writing to world accessible file.
Consider setting the umask to 077 and trying again.
pi@raspberrypi:~/wgkeys $ wg pubkey > server_public.key < server_private.key
pi@raspberrypi:~/wgkeys $ wg genkey > client1_private.key
Warning: writing to world accessible file.
Consider setting the umask to 077 and trying again.
pi@raspberrypi:~/wgkeys $ wg pubkey > client1_public.key < client1_private.key
pi@raspberrypi:~/wgkeys $ ls
client1_private.key client1_public.key server_private.key server_public.key
次の作業で必要になるので、各鍵の中身を確認します。
pi@raspberrypi:~/wgkeys $ cat server_private.key
yBjQRFeYKDocbXwvFaeJIGZlxncgz5UBTkQynxvAtHs=
pi@raspberrypi:~/wgkeys $ cat server_public.key
xKA7PQDN/+eIPaSO9gxnIgeyqtEeLkpMLLhD/YnAewQ=
pi@raspberrypi:~/wgkeys $ cat client1_private.key
0GUNsRgb/j428Ftkh1v0KcshtWyIskkjOzNsTYheQXc=
pi@raspberrypi:~/wgkeys $ cat client1_public.key
QYieIYVjL6FUe+PEK+PYfTvMeq+jNJOaLe/ZX8+aznI=
サーバー設定ファイル
設定ファイル/etc/wireguard/wg0.conf
を作成します。
pi@raspberrypi:~/wgkeys $ sudo vi /etc/wireguard/wg0.conf
[Interface]
#自分のIPアドレスを指定
Address = 192.168.200.1/24
#待ち受けポート
ListenPort = 51820
#サーバー側秘密鍵
PrivateKey = yBjQRFeYKDocbXwvFaeJIGZlxncgz5UBTkQynxvAtHs=
#replace eth0 with the interface open to the internet (e.g might be wlan0 if wifi)
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
#Client1の公開鍵
PublicKey = QYieIYVjL6FUe+PEK+PYfTvMeq+jNJOaLe/ZX8+aznI=
#WireGuard経由で通信するネットワーク
AllowedIPs = 192.168.200.215/32
Address
については、元々のLANと違うサブネットになる様にする。
同一にした場合、接続元LANと区別がつかずルーティングに支障が出るようで通信不全になってしまう。
今回は元々のアドレスは192.168.25.96/24
、VPNアドレスは192.168.200.1/24
として設定します。
サーバー起動(wg0インターフェース起動)
wg-quick
コマンドでサーバーを起動。
pi@raspberrypi:~/wgkeys $ sudo wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 192.168.200.1 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] ip -4 route add 192.168.200.215/32 dev wg0
[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
wg
コマンドでサーバーの状態を確認。
pi@raspberrypi:~/wgkeys $ sudo wg
interface: wg0
public key: xKA7PQDN/+eIPaSO9gxnIgeyqtEeLkpMLLhD/YnAewQ==
private key: (hidden)
listening port: 51820
peer: QYieIYVjL6FUe+PEK+PYfTvMeq+jNJOaLe/ZX8+aznI=
allowed ips: 192.168.200.215/32
起動している事を確認出来たら、サービスに登録。
pi@raspberrypi:~/wgkeys $ sudo systemctl enable wg-quick@wg0
Created symlink /etc/systemd/system/multi-user.target.wants/wg-quick@wg0.service → /lib/systemd/system/wg-quick@.service.
wireguard(クライアント)
Linuxをクライアントにする方法は、公式ドキュメントや各解説記事が充実していますので割愛します。
windows10とAndroidについては、公式アプリに設定ファイルを読み込ませるだけですので、難しくはありませんが、Windows10について設定法を記載します。
クライアント設定ファイル
設定ファイルclientwg.conf
を作成します。
クライアントマシン上に作成して下さい。
[Interface]
#Client1の秘密鍵
PrivateKey = 0GUNsRgb/j428Ftkh1v0KcshtWyxxskjOzNsTYheQXc=
#Client1に付与するIPアドレス
Address = 192.168.200.215/24
[Peer]
#サーバーの公開鍵
PublicKey = xKA7PQDN/+eIPaSO9gxnIgeyqtEevLpMLLhD/YnAewQ=
#サーバーのアドレスまたはドメイン名とポート番号
Endpoint = 192.168.25.96:51820
# or
Endpoint = example.com:51820
#WireGuard経由で通信するネットワーク
AllowedIPs = 192.168.25.0/24,192.168.200.0/24
このファイルはWindows/Linux/Androidで使用出来ます。
(MacOS/iOSは環境がないため未確認です。)
クライアント設定
クライアントソフトをインストールして起動します。
以下の画面が表示されるので、右下にある「トンネル追加」ボタンをクリックして下さい。
ファイル選択画面になりますので、作成したclientwg.conf
を選択して下さい。
ファイルが読み込まれると、以下の様にトンネルの設定が行われます。
インターフェースに表示されている「有効化」ボタンで有効化します。
成功すると以下の画面になります。
失敗する場合、サーバー・クライアントの設定を再度確認して下さい。
接続成功したらコマンドプロンプトかpwoershellでipconfig
を実行すると、以下の様な情報を取得出来ます。
> ipconfig
・・・・・
不明なアダプター clientwg:
接続固有の DNS サフィックス . . . . .:
IPv4 アドレス . . . . . . . . . . . .: 192.168.200.215
サブネット マスク . . . . . . . . . .: 255.255.255.0
デフォルト ゲートウェイ . . . . . . .:
・・・・・
これでクライアントからIPベースアクセスでLAN内と通信する事が出来る様になります。
#おわりに
単純に接続するだけであればIPsecよりかなり簡単にVPN接続出来たと思います。
今回出来なかった点としては、以下などがあります。
- DHCPと連携させる事が出来ず、固定IP環境になる
- ホスト名ではなくIPアドレスでアクセスする必要がある
- 共有鍵では無いので、クライアントを追加するたび設定ファイルを修正する必要がある
今後解消出来たら、続編を書くかもしれません。