VyOS で WireGuardによるVPN接続
検証環境として構築した仮想ネットワークに対して、自身のローカル端末からアクセスするために、ゲートウェイとなるVyOSのルータとWireGuardによるVPN接続を構築した際のメモとなります。
設定
キーペアの生成
VyOS上でVPNサーバのキーペアを生成。今回はサーバ側、クライアント側双方のキーペアの生成をVyOS側で実施。
サーバ用キーペア
$ generate wireguard named-keypairs <KEY_NAME>
生成されたキーの確認。
$ show wireguard keypairs pubkey <KEY_NAME> RvTYdrnV+80IP/8uXDdWD/sXzv+1H+xurzy6ZrNXhAw=
クライアント用キーペア
$ generate wireguard named-keypairs client01
インタフェース設定
VyOS(サーバ)側
set interfaces wireguard wg0 address '172.23.255.1/24' set interfaces wireguard wg0 peer client01 allowed-ips '172.23.255.0/24' set interfaces wireguard wg0 peer client01 pubkey <CLIENT_PUBLIC_KEY> set interfaces wireguard wg0 port 51820 set interfaces wireguard wg0 privatekey <KEY_NAME> set protocols static interface-route 10.2.0.0/24 next-hop-interface wg0
クライアント側
今回はmacOSにてコマンドラインで設定。
/usr/local/etc/wireguard/wg0.conf
[Interface] PrivateKey = <CLIENT_PRIVATE_KEY> Address = 172.23.255.2 [Peer] PublicKey = <SERVER_PUBLIC_KEY> AllowedIPs = 172.23.0.0/16 #VPN経由とするネットワーク EndPoint = <SERVER_ADDRESS>:51820
接続・確認
wg-quick でVPNのセッションを開始。
$ wg-quick up wg0
対向にping疎通が取れることを確認。
参考
Photon OS でDNSサーバをDocker + CoreDNSで構築する
前ポストに引き続き、検証環境構築メモとなります。
今回は検証環境の内部向けドメインのDNSサーバを構築します。
VyOSの構築メモ - passacaglia
Environment
- PhotonOS
- CoreDNS
add user
予めsudoグループに追加しておけば、sudersへの追加は不要。
# useradd -m -G sudo admin # passwd admin
disable iptables
デフォルトでは 22/tcpのみポート開放されている。必要なポートのみ開放することが望ましいが、一旦停止。
# systemctl stop iptables # systemctl disable iptables
docker
Photon OSでは、dockerが予めインストールされているが、無効化されているので、有効化して起動させる。
# systemctl enable docker # systemctl start docker
CoreDNS
coredns/Corefile
. { #log reload forward . <RESOLVER> } <LOCAL_DOMAIN> { log file /etc/coredns/zones/<LOCAL_DOMAIN>.zone }
BIND形式でのゾーンファイルを作成。
coredns/zones/zonefile
$ORIGIN <DOMAIN>. @ 3600 IN SOA mgmt.<DOMAIN>. admin.<DOMAIN>. ( 2020123100 7200 3600 1209600 3600 ) 3600 IN NS mgmt.<DOMAIN>. mgmt IN A 172.23.0.X
事前にCoreDNSのイメージをダウンロード。
docker pull coredns/coredns:1.7.0
今回はdocker-composeを利用してコンテナの管理を行うため、yamlファイルを用意。
version: '3' services: coredns: image: coredns/coredns:1.7.0 container_name: coredns restart: always network_mode: host command: -conf /etc/coredns/Corefile volumes: - coredns:/etc/coredns volumes: coredns: driver_opts: type: none device: <PATH_TO_COREDNS_DIR> o: bind
systemd-resolvedを停止する。
systemctl stop systemd-resolved systemctl disable systemd-resolved
corednsを起動
docker-compose up -d
設定したコンフィグで名前解決ができることを確認。
VyOSの構築メモ
仮想基盤の検証環境を構築するにあたり、仮想ネットワークのゲートウェイとしてVyOSをよく利用しています。複数の環境を構築することが多いため、定番の設定の流れを備忘録として残しておきます。
Install
isoから起動し、ディスクへインストール。
$ install image
Configuration
$ configure
Interface
初期状態ではネットワークが未設定のため、コンソールからインタフェースにIPアドレスとゲートウェイを設定。
# set interface ethernet eth0 address <ADDRESS>
Default Gateway
# set protocols static route 0.0.0.0/0 next-hop <GATEWAY>
ssh
sshを有効にして、リモートからログインして以降の設定作業を可能に。
# set service ssh port <PORT>
以下、流し込み。
set system host-name <HOSTNAME> set system name-server <NAMESERVER> delete system ntp server set system ntp server <NTPSERVER> set system time-zone Asia/Tokyo
2nd interface
1stインタフェースは物理ネットワークと接続し、2ndインタフェースを仮想ネットワークとの接続としています。 複数の仮想ネットワークに対してVLANで分割して接続します。ManagementネットワークはNative VLANとして、untaggedでの利用としています。
# set interface ethernet eth1 address <ADDRESS>
SNAT
仮想ネットワーク内から物理ネットワークへ抜ける際にSNAT。
set nat source rule 1 outbound-interface eth0 set nat source rule 1 source address 172.23.0.0/16 set nat source rule 1 translation address masquerade
Option
以降、必要に応じて設定。
DNS forwarder
set service dns forwarding allow-from 172.23.0.0/16 set service dns forwarding domain <DOMAIN> server <DNSSERVER> set dns forwarding listen-address '172.23.0.1' set dns forwarding name-server <DNSSERVER>
ESXiのインストール自動化(kickstartスクリプトの編集・ISO作成)
ESXiの構築で、何台もあるサーバーを1台ずつコンソール画面で設定するのは手間がかかってしまいます。 今回、kickstart インストールスクリプトによる作業の自動化と、それをデフォルトの動作とするためにカスタムISOの作成を行いました。
環境
- 作業 ESXi バージョン: ESXi 7.0
- 作業環境: Ubuntu 20.04 LTS
カスタムISOの作成
元のISOイメージのコピー
My VMware よりダウンロードしたESXiのインストールISOをマウントし、内容を編集するために任意のディレクトリへコピーします。コピーが完了すれば、元のイメージはもう利用しないのでアンマウントして大丈夫です。
# mount -o loop ./VMware-VMvisor-Installer-7.*.x86_64.iso /mnt/esxi # cp -r /mnt/esxi /tmp/esxi # umount /mnt/esxi
インストールスクリプト(ks.cfg)の用意
kickstart のインストールスクリプトである ks.cfg を、コピー先ディレクトリ内に用意します。
rootpw で指定するroot パスワードについては、平文でも可能ですが今回はISOに含めることもあり、暗号化して入力しました。パスワードの生成はmkpasswd
コマンドで行っています。
$ mkpasswd --method=sha-512
/tmp/esxi/ks.cfg
# VMware license agreementへの同意 vmaccepteula # root パスワードの設定 rootpw --iscrypted $6$zzw94gt90Tm$dtfuCgjBf1ambua0qxSnk/.rVVXOCM85iaJ/l384YYgMU.CZIP3OySqUQzQqaBGHqFUeNB1nfxv6W.EDzMP8n1 # 一番目のディスクへのインストールを行い、既にvmfsが作成されている場合は上書きする install --firstdisk --overwritevmfs # キーボードの配列設定 keyboard 'US Default' # vmnic0のインタフェースをDHCPで自動設定する network --bootproto=dhcp --device=vmnic0 # 完了後にリブートする reboot # 初回起動時の処理 %firstboot --interpreter=busybox # SSHとShellを有効化し、起動 vim-cmd hostsvc/enable_ssh vim-cmd hostsvc/start_ssh vim-cmd hostsvc/enable_esx_shell vim-cmd hostsvc/start_esx_shell
ブートパラメータの変更
起動時にこのインストールスクリプトを実行するため、boot.cfg を編集してブートパラメータの変更を行います。 BIOS環境とUEFI環境で boot.cfg の場所が異なるため、両方を修正します。
# sed -i -e "s/kernelopt=.*/kernelopt=ks=cdrom:\/KS.CFG/g" /tmp/esxi/boot.cfg # sed -i -e "s/kernelopt=.*/kernelopt=ks=cdrom:\/KS.CFG/g" /tmp/esxi/efi/boot/boot.cfg
ks.cfg の配置と boot.cfg の編集が完了したので、改めてISOイメージ化します。
ISOの作成
# mkisofs -relaxed-filenames -J -R -b isolinux.bin -c boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table \ -eltorito-alt-boot -e efiboot.img -boot-load-size 1 \ -no-emul-boot -o custom_esxi.iso /tmp/esxi
動作確認
作成した ISOイメージをVMware Fusion で動作確認しました。BIOSでもUEFIでも起動してインストールスクリプトが実行され、記載した内容の設定が自動で行わていることを確認しています。
これで、最低限ネットワークとSSHの設定が済んだ状態で起動させることができるようになりました。SSHさえできるようになれば、後の細かい設定はコマンドラインや自動化ツールで行えるので、あまり複雑なことはせず利用しています。
参考
Inkbird IBS-TH1 からBluetooth LEで温度・湿度情報を取得して可視化する
新型コロナウイルスの影響により、自宅で過ごす時間が長くなりました。これを機に生活環境の情報を取得・可視化しようと思い、Bluetooth対応の温湿度センサーを導入し、Linux機からPythonで収集したデータをPrometheusとGrafanaで可視化を行うことにしました。
- 環境
- 温湿度センサー / Inkbird IBS-TH1
- Bluetoothでのデータ取得
- Pythonからbluepyで温湿度を取得する
- Prometheusへデータをエクスポート
- Grafanaで時系列データの可視化
環境
温湿度センサー / Inkbird IBS-TH1
今回、InkbirdのIBS-TH1を導入しました。Inkbird IBS-TH1シリーズはこれ以外にも液晶画面付きで単体でも利用可能なIBS-TH1 PlusやIBS-TH1 Miniがありますが、今回購入したのは標準版です。
https://www.amazon.co.jp/dp/B0774BGBHS
Bluetoothでのデータ取得
既に同様のことをされている方がいらっしゃるので、下記を参考にIBS-TH1のMACアドレス確認とgattool
でのデータ取得確認を行いました。しかし、私の環境ではhandleに0x002d
を指定したところ、応答のバイト数が異なり温湿度のデータが含まれていないようでした。
handleに0x002d
を指定した場合。7バイトの応答を期待しているところ、5バイトの応答が返ってきていました。
$ gatttool -b XX:XX:XX:XX:XX:XX --char-read --handle=0x002d Characteristic value/descriptor: 02 2e 00 f4 ff
他のケースを探してみると、handleに0x0028
を利用している方もいて、今回はこちらでうまくいきました。
$ gatttool -b XX:XX:XX:XX:XX:XX --char-read --handle=0x0028 Characteristic value/descriptor: 0f 09 8e 19 00 18 26
1,2バイト目に温度、3,4バイト目に湿度がリトルエンディアンで格納されています。
Pythonからbluepyで温湿度を取得する
pythonからbluetoothデバイスへの通信はbluepyを利用しました。取得したデータのバイト列から整数値への変換は、Python 3.2以降で利用可能な、整数型のfrom_bytesメソッドが簡単でした。
python3ならintとbytesの変換が楽勝になる - BlankTar
from bluepy.btle import Peripheral, ADDR_TYPE_PUBLIC mac = "XX:XX:XX:XX:XX:XX" # IBS-TH1のMACアドレス peripheral = Peripheral(mac, addrType=ADDR_TYPE_PUBLIC) characteristic = peripheral.readCharacteristic(0x0028) temperature = int.from_bytes(characteristic[0:2], "little") / 100 humidity = int.from_bytes(characteristic[2:4], "little") / 100 print("Temperature: {} C".format(temperature)) print("Humidity: {} %".format(humidity))
Prometheusへデータをエクスポート
取得できるようになったデータをPrometheusで時系列に保存し、可視化できるようにします。 prometheusの公式のクライアントライブラリであるprometheus_clientを利用し、簡易なエクスポーターを作成しています。
import time from bluepy.btle import Peripheral, ADDR_TYPE_PUBLIC from prometheus_client import start_http_server, Gauge from prometheus_client import REGISTRY, PROCESS_COLLECTOR, PLATFORM_COLLECTOR, GC_COLLECTOR # 温湿度以外のメトリクスを非表示にする REGISTRY.unregister(PROCESS_COLLECTOR) REGISTRY.unregister(PLATFORM_COLLECTOR) REGISTRY.unregister(GC_COLLECTOR) # 温湿度のメトリクスを作成 TEMPERATURE = Gauge("inkbird_temperature", "current temperature", ["device"]) HUMIDITY = Gauge("inkbird_humidity", "current humidity", ["device"]) MAC = "XX:XX:XX:XX:XX:XX" # IBS-TH1のMACアドレス def run(): peripheral = Peripheral(MAC, addrType=ADDR_TYPE_PUBLIC) characteristic = peripheral.readCharacteristic(0x0028) temperature = int.from_bytes(characteristic[0:2], "little") / 100 humidity = int.from_bytes(characteristic[2:4], "little") / 100 TEMPERATURE.labels(MAC).set(temperature) HUMIDITY.labels(MAC).set(humidity) if __name__ == '__main__': start_http_server(8080) # サーバポートを指定してHTTPサーバを開始 while True: run() time.sleep(60) # 60秒毎にデータ更新
実行し、ホストの8080ポートへブラウザでアクセスすると、下記のような温度と湿度の情報が表示されると思います。
# HELP inkbird_temperature current temperature # TYPE inkbird_temperature gauge inkbird_temperature{device="XX:XX:XX:XX:XX:XX"} 23.06 # HELP inkbird_humidity current humidity # TYPE inkbird_humidity gauge inkbird_humidity{device="F8:30:02:FF:45:3F"} 47.58
これをPrometheusのターゲットとして登録し、定期的なデータ取得と保存が可能となりました。
Grafanaで時系列データの可視化
あとはPrometheusのデータをGrafanaでグラフ化します。以上で温湿度情報を可視化することができました。
Linux bridge、Tapインタフェースとは
VMやコンテナ等、仮想化関連を度々扱っています。仮想ネットワーク周りでtapインタフェースの概念を確認していたのですが、以前にも同じことを調べたのを忘れていたので、備忘録として改めて整理しておきます。
基本的に以下Blog記事の簡単な訳となります。
[Linux Bridge and Virtual Networking | http://www.innervoice.in/blogs/2013/12/02/linux-bridge-virtual-networking/]
[Tap Interfaces and Linux Bridge | http://www.innervoice.in/blogs/2013/12/08/tap-interfaces-linux-bridge/]
Linux bridge
ブリッジと呼ばれているが、正確には仮想スイッチであり、2.2カーネル以降でカーネルモジュールとして提供され、brctlコマンドによって管理される。
物理ネットワークと仮想ネットワーク
ネットワーク上に流れるデータトラフィックは、物理マシン上の物理イーサネットポートによって処理される。それは仮想マシンでも同様であり、トラフィックは仮想イーサネットポートによって処理される必要がある。仮想化の目的は物理エンティティをソフトウェアでエミュレートすることであり、"仮想マシンの仮想イーサネットポートが仮想スイッチへ接続される"状態を構築することをサポートしなければならない。
スイッチポート
Linux bridgeはLinuxカーネルに組み込まれたスイッチであり、物理スイッチと同様に入出力されるトラフィックを運ぶポートやインタフェースが必要となる。Linux bridgeは物理ポートと仮想ポートのどちらもサポートしていて、ブリッジに追加することができる。仮想ポートはソフトウェアエンティティであり、イーサネットフレームをその先の処理のために仮想スイッチへ転送するために利用される。イーサネットトラフィックでは、このLinux仮想ポートをtapインタフェースと呼ぶ。tapインタフェースによるアプローチによって、Linux bridgeは仮想世界から物理世界へパケットを転送することが可能となる。
tapインタフェースはなぜ必要か
物理マシンの場合と同様、仮想マシンのネットワークポートはイーサネットフレームのみを処理できる。非仮想化環境では、物理ネットワークインタフェースはイーサネットフレームを受信し、処理する。それは受信したフレームからイーサネット関連のヘッダを取り除き、ペイロード(IPパケット)を先のOSへ向けて転送することである。しかし仮想化環境では、仮想ネットワークインタフェースはイーサネットフレームを期待しているために、物理ネットワークインタフェースで処理されたペイロードを受け渡されても正しく動作しない。tapインタフェースは特別なソフトウェアエンティティであり、Linux bridgeにイーサネットフレームをそのまま転送するように指示をする。つまり、tapインタフェースに接続された仮想マシンは生のイーサネットフレームを受信できるようになる。それによって、仮想マシンはネットワークの視点からは物理マシンであるかのように動作することが可能となる。
仮想RJ45ケーブルも同様に存在するのか
簡単に言うと無いが、仮想マシンの仮想マシンイーサネットポートをLinux bridgeのtapインタフェースへ接続する必要はある。この接続はプログラム的に行われ、libvirtのようなアプリケーションがtapインタフェースの利用するファイルディスクリプタを作成する。Linux bridgeがイーサネットフレームをtapインタフェースへ送信するとき、正確にはファイルディスクリプタへバイトを送信している。QEMUのようなエミュレータでは、このファイルディスクリプタからバイトを読み込み、仮想マシンの仮想ネットワークインタフェースを通して内部のゲストOSへ渡している。