NanoPi R4S + OpenWrtでv6プラス固定IPを使ってみる
- NanoPi R4S
- OpenWrt
- 初期設定
- パッケージの更新・追加
- IPv6パススルーの設定
- WAN6のインターフェイスIDの固定化
- IPv4 over IPv6の設定
- スナップショットのアップグレード
- 速度測定
NanoPi R4S
Gigabit LAN x 2 で映像出力なしというミニルータに特化したようなデバイスで4G RAMモデルと1G RAMモデルがあり、今回は4Gでケース付きを購入した。
ストレージはSBCらしくmicro SDカードで、無線LANはついていない。
CPUはRockchipのarmv8でRK3399というものらしい。
OpenWrt
市販のルータで動作できるほど軽量なLinux distributionで、市販のルータの真の力を解放するらしい。
しかし残念ながら、NanoPi R4S向けにはstable releaseされておらず開発版のsnapshotを使う必要がある。
追記 2022/9/6 22.03がリリースされ、NanoPi R4S向けのイメージがstable releaseとして出ました。
初期設定
OS書き込み
downloads.openwrt.org
から
openwrt-22.03.0-rockchip-armv8-friendlyarm_nanopi-r4s-squashfs-sysupgrade.img.gz
をダウンロードし、適当なライターでmicroSDに書き込む。
microSDをNanoPiに挿し電源をつけてLANポートとPCを有線で繋ぐと、DHCPで192.168.1.0/24のアドレスが降ってくる。
$ ssh root@192.168.1.1
sshで繋ぐとパスワードなしにログインできるので、すかさず
root@OpenWrt:~# passwd
パスワードの設定をする。
一旦exitでPCに戻りssh-keyの設定をする(OpenWrtで使われているSSHサーバであるdropbearはyubikeyで使ってるecdsaに対応していないため、新たにed25519で鍵を作る必要があり、ここで結構ハマった…)。
ssh-copy-idを使うとdropbearに合わせた設定をしてくれるので便利(~/.ssh/authorized_keyではなく/etc/dropbear/authorized_keysに追記する必要がある)。
$ cd ~/.ssh $ ssh-keygen -t ed25519 $ ssh-copy-id -i id_ed25519 root@192.168.1.1
これで
$ ssh root@192.168.1.1
でパスワードなしでログインできるようになった。
ネットワークの初期設定
OpenWrtでは各種設定は/etc/config/以下に保存されておりuciコマンドで操作することができる。
例えばネットワークに関する設定は/etc/config/networkにあり、初期状態ではこのようになってる
root@OpenWrt:~# cat /etc/config/network
config interface 'loopback'
option device 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fd56:d548:f6c2::/48'
config device
option name 'br-lan'
option type 'bridge'
list ports 'eth1'
config device
option name 'eth1'
option macaddr 'ab:cd:ef:gh:ij:kl'
config interface 'lan'
option device 'br-lan'
option proto 'static'
option ipaddr '192.168.1.1'
option netmask '255.255.255.0'
option ip6assign '60'
config device
option name 'eth0'
option macaddr '12:34:56:78:90:ab'
config interface 'wan'
option device 'eth0'
option proto 'dhcp'
config interface 'wan6'
option device 'eth0'
option proto 'dhcpv6'
このファイルをuciコマンド経由で見ると
root@OpenWrt:~# uci show network network.loopback=interface network.loopback.device='lo' network.loopback.proto='static' network.loopback.ipaddr='127.0.0.1' network.loopback.netmask='255.0.0.0' network.globals=globals network.globals.ula_prefix='fd56:d548:f6c2::/48' network.@device[0]=device network.@device[0].name='br-lan' network.@device[0].type='bridge' network.@device[0].ports='eth1' network.@device[1]=device network.@device[1].name='eth1' network.@device[1].macaddr='ab:cd:ef:gh:ij:kl' network.lan=interface network.lan.device='br-lan' network.lan.proto='static' network.lan.ipaddr='192.168.1.1' network.lan.netmask='255.255.255.0' network.lan.ip6assign='60' network.@device[2]=device network.@device[2].name='eth0' network.@device[2].macaddr='12:34:56:78:90:ab' network.wan=interface network.wan.device='eth0' network.wan.proto='dhcp' network.wan6=interface network.wan6.device='eth0' network.wan6.proto='dhcpv6'
このようになる。
OpenWrtはデフォルトでLANデバイスとWLANデバイスをブリッジしているため、br-lanというデバイスが定義されており、それがlanインターフェイスとなっている。
しかし、NanoPi R4SにはWLANデバイスはないためこのブリッジデバイスを削除しておく。
ファイルを直接編集してもいいしuciコマンドで設定してもいいが、今回はuciコマンドで設定を行う。
ついでにlanにあるipv6の設定も消しておく。
root@OpenWrt:~# uci delete network.@device[0] root@OpenWrt:~# uci set network.lan.device=eth1 root@OpenWrt:~# uci delete network.lan.ip6assign='60' root@OpenWrt:~# uci show network network.loopback=interface network.loopback.device='lo' network.loopback.proto='static' network.loopback.ipaddr='127.0.0.1' network.loopback.netmask='255.0.0.0' network.globals=globals network.globals.ula_prefix='fd56:d548:f6c2::/48 network.@device[0]=device network.@device[0].name='eth1' network.@device[0].macaddr='ab:cd:ef:gh:ij:kl' network.lan=interface network.lan.device='eth1' network.lan.proto='static' network.lan.ipaddr='192.168.1.1' network.lan.netmask='255.255.255.0' network.@device[1]=device network.@device[1].name='eth0' network.@device[1].macaddr='12:34:56:78:90:ab' network.wan=interface network.wan.device='eth0' network.wan.proto='dhcp' network.wan6=interface network.wan6.device='eth0' network.wan6.proto='dhcpv6
commitを行うことにより設定ファイルが更新される。
root@OpenWrt:~# uci commit network
root@OpenWrt:~# cat /etc/config/network
config interface 'loopback'
option device 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fd56:d548:f6c2::/48'
config device
option name 'eth1'
option macaddr 'ab:cd:ef:gh:ij:kl'
config interface 'lan'
option device 'eth1'
option proto 'static'
option ipaddr '192.168.1.1'
option netmask '255.255.255.0'
config device
option name 'eth0'
option macaddr '12:34:56:78:90:ab'
config interface 'wan'
option device 'eth0'
option proto 'dhcp'
config interface 'wan6'
option device 'eth0'
option proto 'dhcpv6'
パッケージの更新・追加
ここでNanoPiのWANポートに既存インターネット(DHCPでアドレスが割り当てられる)を接続する。
# 初回は証明書が切れてたりするためチェックをせずに行う root@OpenWrt:~# opkg update --no-check-certificate # Webインターフェイス root@OpenWrt:~# opkg install luci-ssl
IPIP6パッケージの作成
v6プラス固定IPで使用するIPIP6トンネルに関するパッケージは公式にはないため、 github.com こちらを使用させていただいた。
カスタムビルドするのはかなり手間なのでパッケージを手作りすることにした。
# ipip6パッケージ作成
$ mkdir ipip6
$ cd ipip6
## control.tar.gzの作成
$ mkdir control
$ cd control
$ cat << EOS > ./control
Package: ipip6
Version: 0.1
Depends: libc, kmod-ip6-tunnel, resolveip
Source: feeds/base/package/network/ipv6/ipip6
SourceName: ipip6
License: GPL-2.0
Section: net
SourceDateEpoch: 1641284700
Maintainer: kenjiuno <ku@digitaldolphins.jp>
Architecture: all
Installed-Size: 2716
Description: Provides support for ipip6 (RFC2473) in /etc/config/network.
EOS
$ cat << EOS > ./postinst
#!/bin/sh
[ "${IPKG_NO_SCRIPT}" = "1" ] && exit 0
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
. ${IPKG_INSTROOT}/lib/functions.sh
default_postinst $0 $@
EOS
$ cat << EOS > ./postinst-pkg
[ -n "${IPKG_INSTROOT}" ] || { rm -f /tmp/luci-indexcache
rm -rf /tmp/luci-modulecache/
killall -HUP rpcd 2>/dev/null
exit 0
}
EOS
$ cat << EOS > ./prerm
#!/bin/sh
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
. ${IPKG_INSTROOT}/lib/functions.sh
default_prerm $0 $@
EOS
$ chmod +x postinst postinst-pkg prerm
$ tar --numeric-owner --group=0 --owner=0 -czf ../control.tar.gz ./
$ cd ..
## data.tar.gzの作成
$ mkdir data
$ cd data
$ mkdir -p ./lib/netifd/proto
$ mkdir -p ./www/luci-static/resources/protocol
$ wget -O ./lib/netifd/proto/ipip6.sh https://github.com/HiraokaHyperTools/openwrt-ipip6/raw/main/net/ipv6/ipip6/files/ipip6.sh
$ wget -O ./www/luci-static/resources/protocol/ipip6.js https://github.com/HiraokaHyperTools/openwrt-ipip6/raw/main/net/ipv6/ipip6/files/ipip6.js
$ chmod +x ./lib/netifd/proto/ipip6.sh
$ tar --numeric-owner --group=0 --owner=0 -czf ../data.tar.gz ./
$ cd ..
## debian-binaryの作成
$ cat << EOS > ./debian-binary
2.0
EOS
## ipip6_0.1_all.ipkの作成
$ tar --numeric-owner --group=0 --owner=0 -czf ./ipip6_0.1_all.tar.gz ./debian-binary ./data.tar.gz ./control.tar.gz
$ mv ipip6_0.1_all.tar.gz ../ipip6_0.1_all.ipk
出来上がった、ipip6_0.1_all.ipkをNanoPiに持っていき、インストールする。
root@OpenWrt:~# opkg install ./ipip6_0.1_all.ipk
ここでNanoPiを再起動し、WANに挿していたケーブルをONU直結へと変える。
IPv6パススルーの設定
Webインターフェイス(https://192.168.1.1)を開き、Network->InterfaceにいきWAN6をEditする。
DHCP Serverのタブに行き、Set up DHCP Serverを押す。

IPv6 Settingsのタブに行き、Designated masterにチェックを入れ、全てrelay modeにする。

同様にLANも設定する。
今度はDHCPv6 Serviceのみserver modeにし、それ以外はrelay modeにする。
Announced IPv6 DNS serversにPublic DNSサーバのIPv6アドレスを入れる。
- 2001:4860:4860::8888 # Google
- 2606:4700:4700::1111 # CloudFlare
NDP-Proxy slaveにはチェックを入れない

次にAdvanced Settingsのタブに行きDHCP伝えるDNSサーバの設定をする
。
DHCP-Optionsのところに 6,8.8.8.8,1.1.1.1と入れる。
6がDNSの設定でそれ以降にコンマ区切りで、アドレスを入れる。

これでLAN側につなげたPCからIPv6アクセスが可能となる。
WAN6のインターフェイスIDの固定化
固定IPサービスのIPIP6トンネルを張るにはローカル(自身)のIPv6アドレスのインターフェイスIDが指定されたものでないといけないので上書きする。
root@OpenWrt:~# uci set network.wan6.ifaceid='::[ISPから通知されたインターフェイスID]' root@OpenWrt:~# uci commit network
IPv4 over IPv6の設定
Add new interface...を押し、Protocolを IPv4 over IPv6 (ipip6)を選択する。

Tunnel remote IPv6 addressにv6プラスのBRのアドレスを入れる。
Your global IPv4 addressにはISPから通知された固定IPv4アドレスを入れる。
Local IPv6 addressは空にする(スクリーンショットでは例示用アドレスを入れてある)。

Firewall Settingsのタブでwanゾーンに適応する。

これで、IPv4でのアクセスが可能となる。
スナップショットのアップグレード
アップグレードを行うと設定は保持されるが、パッケージは初期状態になるので再度インストールする。
root@OpenWrt:~# wget https://downloads.openwrt.org/releases/22.03.0/targets/rockchip/armv8/openwrt-22.03.0-rockchip-armv8-friendlyarm_nanopi-r4s-squashfs-sysupgrade.img.gz root@OpenWrt:~# sysupgrade -v ./openwrt-22.03.0-rockchip-armv8-friendlyarm_nanopi-r4s-squashfs-sysupgrade.img.gz # 再起動がかかり更新される root@OpenWrt:~# opkg update root@OpenWrt:~# wget https://static.akashisn.info/packages/openwrt/ipip6_0.1_all.ipk root@OpenWrt:~# opkg install ./ipip6_0.1_all.ipk root@OpenWrt:~# opkg install luci-ssl luci-i18n-base-ja luci-i18n-firewall-ja luci-i18n-opkg-ja # 以下お好みで root@OpenWrt:~# opkg install map ds-lite iptables-mod-ipopt root@OpenWrt:~# opkg install ca-certificates root@OpenWrt:~# opkg install qrencode wireguard-tools luci-proto-wireguard luci-app-wireguard luci-i18n-wireguard-ja root@OpenWrt:~# opkg install openvpn-openssl kmod-ovpn-dco openvpn-easy-rsa luci-app-openvpn luci-i18n-openvpn-ja root@OpenWrt:~# opkg install ddns-scripts-cloudflare luci-app-ddns luci-i18n-ddns-ja root@OpenWrt:~# opkg install acme acme-dnsapi luci-app-acme luci-i18n-acme-ja root@OpenWrt:~# reboot
速度測定
2スレッドしか使われていないようだが、


十分に速度が出ている。

Ubuntu 20.04でIPoE + v6プラス固定IPルータをつくる
Edgerouterではなぜかhwnatを有効化するとipipトンネルがおかしくなるみたいでhardware offloadを無効化していたのだが、やはりCPU性能がボトルネックになっていたのでノートパソコン(XPS13)でルータを作ってみた。
前回の記事での「RA Prefixの取得」を行って、
$ sudo apt install radvdump
を取得しているものとする。
環境
Ubuntu 20.04 Desktop XPS13-9360
- eth0: ONUに直結
- eth1: LAN側 (10.10.0.1/24)
Ubuntu Serverではないため、Network Managerが入っているがこれは以下で設定するnetplanと競合してしまったりするためアンインストールしておく。
$ sudo apt purge network-manager
(ここで再起動しておいたほうがいいかも)
Netplanを使用したIPアドレスとIPIPトンネリング
eth0に取得したIPv6 Prefix (240b:xxxx:xxxx:xxxx) とISPから通知されたインターフェイスID (yyyy:yyyy:yyyy:yyyy) を連結させたものをセットする。
IPv6のデフォルトゲートウェイを隣ルータのリンクローカルアドレス (fe80::xxxx:xxxx:xxxx:xxxx) とする。
IPIPトンネルにはISPから通知された固定IP情報に記載されている[固定IPアドレス]と[BRアドレス]を使用する。 IPv4はこのトンネルを使用するようにする。
/etc/netplan/01-netcfg.yamlを以下の内容で作成。
(このディレクトリにある他の設定ファイルは拡張子を変えるとかして無効化しておく)
network: version: 2 ethernets: eth0: accept-ra: false dhcp4: false dhcp6: false addresses: - 240b:xxxx:xxxx:xxxx:yyyy:yyyy:yyyy:yyyy/64 routes: - to: ::/0 via: fe80::xxxx:xxxx:xxxx:xxxx eth1: accept-ra: false addresses: - 10.10.0.1/24 - 240b:xxxx:xxxx:xxxx::1/64 nameservers: addresses: - 8.8.8.8 - 2001:4860:4860::8888 tunnels: ip6tnl1: mode: ipip6 addresses: - [固定IPアドレス] remote: [BRアドレス] local: 240b:xxxx:xxxx:xxxx:yyyy:yyyy:yyyy:yyyy routes: - to: 0.0.0.0/0 scope: link
Forwardingの設定
IPパケットの転送を有効化する。
/etc/sysctl.confを編集。以下のコメントを外す。
# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1
↓
net.ipv4.ip_forward=1
# Uncomment the next line to enable packet forwarding for IPv6
# Enabling this option disables Stateless Address Autoconfiguration
# based on Router Advertisements for this host
#net.ipv6.conf.all.forwarding=1
↓
net.ipv6.conf.all.forwarding=1
$ sudo sysctl -p
ufwの設定
/etc/default/ufwを編集。DEFAULT_FORWARD_POLICYをACCEPTにする。
# Set the default forward policy to ACCEPT, DROP or REJECT. Please note that
# if you change this you will most likely want to adjust your rules
DEFAULT_FORWARD_POLICY="DROP"
↓
DEFAULT_FORWARD_POLICY="ACCEPT"
/etc/ufw/before.rulesを編集。最初の部分に以下を追加。
# # rules.before # # Rules that should be run before the ufw command line added rules. Custom # rules should be added to one of these chains: # ufw-before-input # ufw-before-output # ufw-before-forward # # ここから # Masquarade *nat :POSTROUTING ACCEPT [0:0] :PREROUTING ACCEPT [0:0] -A POSTROUTING -s 10.10.0.0/24 -j MASQUERADE COMMIT # don't delete the 'COMMIT' line or these rules won't be processed # ここまで追加
/etc/ufw/after.rulesと/etc/ufw/after6.rulesを同じように編集。最初の部分に以下を追加。
# # rules.input-after # # Rules that should be run after the ufw command line added rules. Custom # rules should be added to one of these chains: # ufw-after-input # ufw-after-output # ufw-after-forward # # ここから *mangle :POSTROUTING ACCEPT [0:0] :PREROUTING ACCEPT [0:0] -A FORWARD -o ip6tnl1 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1412 COMMIT # don't delete the 'COMMIT' line or these rules won't be processed # ここまで追加
ufwを有効化する
$ sudo ufw enable
LANからLocalへのアクセスを許可する
$ sudo ufw allow from 10.10.0.0/24
DHCPサーバ・RAの設定
IPv4アドレスはDHCPサーバで配布して、IPv6アドレスはNDProxy+RAによる告知を行う。
isc-dhcp-serverの設定
$ sudo apt install isc-dhcp-server
/etc/default/isc-dhcp-serverを編集。DHCPv4サーバがlistenするインターフェイスを指定。
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
# Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACESv4=""
INTERFACESv6=""
↓
INTERFACESv4="eth1"
#INTERFACESv6=""
/lib/systemd/system/isc-dhcp-server.serviceを編集。PIDファイルのパスを/var/run/dhcpd.pidへ変更。
exec dhcpd -user dhcpd -group dhcpd -f -4 -pf /run/dhcp-server/dhcpd.pid -cf $CONFIG_FILE $INTERFACESv4'
↓
exec dhcpd -user dhcpd -group dhcpd -f -4 -pf /var/run/dhcpd.pid -cf $CONFIG_FILE $INTERFACESv4'
$ sudo systemctl daemon-reload
最初からある設定ファイルの名前を変えておく。
$ sudo mv /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.sample
/etc/dhcp/dhcpd.confを以下の内容で作成。
# default
default-lease-time 600;
max-lease-time 7200;
ddns-update-style none;
authoritative;
subnet 10.10.0.0 netmask 255.255.255.0 {
range 10.10.0.30 10.10.0.199;
option routers 10.10.0.1;
option domain-name-servers 1.1.1.1, 8.8.8.8;
default-lease-time 3600;
max-lease-time 7200;
}
radvdの設定
/etc/radvd.confを以下の内容で作成。
interface eth1
{
AdvCurHopLimit 64;
AdvLinkMTU 1500;
AdvManagedFlag off;
AdvOtherConfigFlag off;
AdvReachableTime 0;
AdvRetransTimer 0;
AdvSendAdvert on;
MaxRtrAdvInterval 600;
prefix 240b:xxxx:xxxx:xxxx::/64
{
AdvAutonomous on;
AdvOnLink on;
AdvValidLifetime 2592000;
};
RDNSS 2606:4700:4700::1111 2001:4860:4860::8888
{
};
};
$ sudo apt install radvd
ndppdの設定
/etc/ndppd.confを以下の内容で作成。
proxy eth0 {
router no
timeout 500
autowire yes
keepalive yes
retries 3
ttl 30000
240b:xxxx:xxxx:xxxx::/64 {
iface eth1
}
}
$ sudo apt install ndppd
$ sudo systemctl enable ndppd.service
ここで再起動する
速度計測


十分に速くなった!
Edgerouter Xでv6プラス固定IPを使う
目次
- 目次
- 環境
- 前提
- RA Prefixの取得
- 内部LAN側のIPv6アドレスの定義
- IPIPトンネルを張る
- NAT・ルーティングの設定
- mss-clampの設定
- NDProxyによるIPv6環境
- 速度測定
環境
脱PPPoEをするためにIPv4 over IPv6を使おうと思うのだが、一般に広く使われているv6プラス(MAP-E)や、transix(DS-Lite)などは、一つのIPv4アドレスを複数の契約者で共有するため利用できるポートが限られてしまう。 *1
そこで、固定IPオプションをつけることにより一つのIPv4アドレスを占有することができ任意のポートを使用できる。
これらは全てNGN網から固定IP終端装置に対してIPIPトンネルを張る。
v6プラス固定IP、transix固定IPのどちらかを選ぶことになるのだが、どうやら transix固定IPでは制限がかけられているらしいのでv6プラス固定IPを使用する。
しかし、v6プラス固定IPサービスを提供している事業者は数少ない。
今回引っ越した新居には光コンセントがあったので小型ONUを簡単に出してくれるらしいフレッツコラボのenひかりを契約した。
前提
今回は光電話を契約しなかったため、/64プレフィックスがRAにより配布されているため、EdgerouterでNDproxyを導入する必要がある。
説明に用いている表記は、
# (configureモード) $ (通常モード)
となっていて、configureモードから通常モードに移行した際はcommit; save; exitをしている。
RA Prefixの取得
回線の開通が済んだら、IPv6のPrefixを取得する。 ここで必要になるのは、
の二つ。
$ sudo radvdump
#
# radvd configuration generated by radvdump 2.16
# based on Router Advertisement from fe80::xxxx:xxxx:xxxx:xxxx
# received by interface eth0
#
interface eth0
{
AdvSendAdvert on;
# Note: {Min,Max}RtrAdvInterval cannot be obtained with radvdump
AdvManagedFlag off;
AdvOtherConfigFlag on;
AdvReachableTime 300000;
AdvRetransTimer 10000;
AdvCurHopLimit 64;
AdvDefaultLifetime 1800;
AdvHomeAgentFlag off;
AdvDefaultPreference medium;
AdvSourceLLAddress on;
prefix 240b:xxxx:xxxx:xxxx::/64
{
AdvValidLifetime 2592000;
AdvPreferredLifetime 604800;
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
}; # End of prefix definition
}; # End of interface definition
内部LAN側のIPv6アドレスの定義
enひかりから通知された固定IP情報に記載されているインターフェイスIDをyyyy:yyyy:yyyy:yyyyとすると、内部LANのアドレスは240b:xxxx:xxxx:xxxx:yyyy:yyyy:yyyy:yyyy/64となる。
# set interfaces switch switch0 address '240b:xxxx:xxxx:xxxx:yyyy:yyyy:yyyy:yyyy/64' # set interfaces switch switch0 description Local # set interfaces switch switch0 ipv6 dup-addr-detect-transmits 1 # set interfaces switch switch0 ipv6 router-advert cur-hop-limit 64 # set interfaces switch switch0 ipv6 router-advert link-mtu 1500 # set interfaces switch switch0 ipv6 router-advert managed-flag false # set interfaces switch switch0 ipv6 router-advert max-interval 600 # set interfaces switch switch0 ipv6 router-advert other-config-flag true # set interfaces switch switch0 ipv6 router-advert prefix '240b:xxxx:xxxx:xxxx::/64' autonomous-flag true # set interfaces switch switch0 ipv6 router-advert prefix '240b:xxxx:xxxx:xxxx::/64' on-link-flag true # set interfaces switch switch0 ipv6 router-advert prefix '240b:xxxx:xxxx:xxxx::/64' valid-lifetime 2592000 # set interfaces switch switch0 ipv6 router-advert reachable-time 0 # set interfaces switch switch0 ipv6 router-advert retrans-timer 0 # set interfaces switch switch0 ipv6 router-advert send-advert true
IPv6のデフォルトゲートウェイを対岸のルータとする。
set protocols static route6 '::/0' next-hop 'fe80::xxxx:xxxx:xxxx:xxxx' interface eth0
IPIPトンネルを張る
enひかりから通知された固定IP情報に記載されている[固定IPアドレス]と[BRアドレス]を使用する。
# set interfaces ipv6-tunnel v6tun0 address [固定IPアドレス] # set interfaces ipv6-tunnel v6tun0 description v6plus-static # set interfaces ipv6-tunnel v6tun0 encapsulation ipip6 # set interfaces ipv6-tunnel v6tun0 firewall in name WAN_IN # set interfaces ipv6-tunnel v6tun0 firewall local name WAN_LOCAL # set interfaces ipv6-tunnel v6tun0 local-ip '240b:xxxx:xxxx:xxxx:yyyy:yyyy:yyyy:yyyy' # set interfaces ipv6-tunnel v6tun0 mtu 1452 # set interfaces ipv6-tunnel v6tun0 multicast disable # set interfaces ipv6-tunnel v6tun0 remote-ip '[BRアドレス]' # set interfaces ipv6-tunnel v6tun0 ttl 64
NAT・ルーティングの設定
set service nat rule 5010 outbound-interface v6tun0 set service nat rule 5010 type masquerade set protocols static interface-route 0.0.0.0/0 next-hop-interface v6tun0
mss-clampの設定
set firewall options mss-clamp interface-type all set firewall options mss-clamp mss 1412
NDProxyによるIPv6環境
以下を参考にndppdを導入する
速度測定

EdgerouterのCPU性能がボトルネックになってるよう...

次はx86_64なPCでVyOSを使ってやってみたいな
*1:自宅鯖(80/443)や一部のゲームで使用できない場合があるそう
最近のLaTeX事情
以前各環境でTeX Liveをインストールする記事を書いたのですが、最近はもっぱらDockerを使ってどの環境でも同じようにを書いてるのでそれの紹介をします。
VS Code + Remote Containers
VS CodeのRemote Development機能を使っての環境とおなじみのLaTeX WorkshopをContainerの中に閉じ込めていつでも同じ環境で作業することが出来ます。
Remote Developmentのインストール
Remote Developmentは、
の3つがセットになってるのでContainer機能だけでいい場合はRemote - Containersをインストールします。
いつものように拡張機能からインストールします。

使い方
準備
VS Codeでのプロジェクトルートとなるフォルダを開きます。
ルートディレクトリに .devcontainer と言うフォルダを作ってその中に devcontainer.json と docker-compose.yml と言うファイルを作ります。

そしてそれぞれ以下の内容を貼り付けます。
Dockerで使うイメージを今回は
arkark様のlatexmk-docker
を少しカスタマイズした
を使ってますが、の環境があれば何でもいいです。
devcontainer.json
- name: このDevContainerの名前
- dockerComposeFile: DevContainerの元となるイメージを指定するためのComposeファイル
- extensions: Containerの中にインストールするVS Codeプラグイン
- service: このDevContainerの中で動かすComposeサービスの名前
- settings: Containerの中で有効なVS Codeの設定
- workspaceFolder: WorkDirの設定(Dockerイメージと合わせる)
- shutdownAction: DevContainerを停止するときにする動作
次に、 latexmkの設定をする。
フォルダルートに .latexmkrc と言うファイルを以下の内容で作成します。
これで準備完了
Containerの中に入る
左下の緑のところを押して

Reopen in Containerを選ぶ

すると、DockerのイメージをダウンロードしてContainerを実行してくれます。
左下の緑のところが "Dev Container:" となっていればContaeinrを開いています。

ビルド

TeXファイルを開いて左の端にあるを押して "Build LaTex project" を押すとデフォルトの uplatex によるビルドが始まります。
そして、その下にある "View LaTeX PDF" を押すと、タブが別れてPDFのプレビューが表示されます。

ビルドされたPDFは、 out フォルダ以下に生成されます。
また、 lualatex でビルドしたいときは、

Ctrl + Shift + P を押して "LaTeX Workshop: Build with recipe" を選択して、

"latexmk with lualatex" を選択すると lualatex によるビルドが始まります。

一回ビルドを行うと保存を行うたびに再度ビルドがかかってプレビューも更新されるので便利
Edgerouter XでIPv6 IPoE + IPv4 over IPv6 (transix) と IPv4 PPPoEを併用する
目次
環境
大学の学生宿舎にて有料で提供されているインターネット接続サービスであるDoCanvasが、IPv6 IPoE と IPv4 over IPv6 に対応するようになるとのニュースがあったためEdgerouter Xで設定を行う。
また、オプションでグローバルIPアドレスサービスにも加入しているため、PPPoEのユーザ情報が手元にあり、今まで使っていた。
しかし、DoCanvasのPPPoEは通信速度が遅いのはまぁ許せるのですが、時々PPPoEのセッションが切れしばらく再接続されないみたいな状況が続いていた。 そのときにIPv6サービスの提供の話があり、これはやってみるしかないとなった。
また、自宅鯖を外部に公開するためにPPPoEは残しておいてPBR(Policy-Based Routing)により使い分ける。
前提
共用部で光終端装置とルータがあり、グローバルIPアドレスサービスを契約していない人でも各部屋までは来ているLANポートに指せば使えるようになっているため、もちろんDoCanvasには光電話のサービスはない。
そのため、共用部のルータから /64 のIPv6プレフィクスがRAにより配布されている。
また、配布されたIPv6プレフィックスを調べてみるとInternet Multifeedの物だったので transix のサービスが使えると思われる。
また、EdgerouterではRAをLAN側にも通知するためのNDProxy機能が標準では搭載されていないため、自前でビルドする必要がある。
説明に用いている表記は、
# (configureモード) $ (通常モード)
となっていて、configureモードから通常モードに移行した際はcommit; save; exitをしている物とする。
PPPoEとDSLite(transix)によるIPv4環境
PPPoEの設定
まずは普通にPPPoEの設定をする
# set interfaces ethernet eth0 pppoe 0 default-route none
# set interfaces ethernet eth0 pppoe 0 description PPPoE
# set interfaces ethernet eth0 pppoe 0 mtu 1452
# set interfaces ethernet eth0 pppoe 0 name-server auto
# set interfaces ethernet eth0 pppoe 0 password ${PPPoE_PASS}
# set interfaces ethernet eth0 pppoe 0 user-id ${PPPoE_USER}
ここで重要なのがdefault-route noneとすること
こうしないとPPPoEによる通信が優先されてしまう
NATの設定もする
# set service nat rule 5010 description 'masquerade for WAN(PPPoE)' # set service nat rule 5010 outbound-interface pppoe0 # set service nat rule 5010 type masquerade
IPv6のプレフィックスを調べる
プレフィックスを調べるためautoconfによりアドレスの自動設定を行う。
# set interfaces ethernet eth0 ipv6 address autoconf # set interfaces ethernet eth0 ipv6 dup-addr-detect-transmits 1
$ ip -6 address show dev eth0
4: eth0@itf0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 24XX:XXXX:XXXX:XXXX:xxxx:xxxx:xxxx:xxxx/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::aaaa:bbbb:cccc/64 scope link
valid_lft forever preferred_lft forever
eth0にリンクローカルアドレス(fe80::%)ではなく24XXから始まるグローバルアドレスが割り当てられたら、アドレスの上位64bit(24XX:XXXX:XXXX:XXXX)をメモしておく。
$ ip -6 neigh show dev eth0 fe80::feed lladdr 00:60:b9:aa:bb:cc router REACHABLE
また、対岸のルータのリンクローカルアドレス(fe80::feed)もメモしておく。
IPv6アドレスを静的設定する
EdgeOSではipip6トンネルを作成する際のローカルアドレスは手動設定であるため、先ほど割り当てられたプレフィックスから好きなtokenを設定する。
また、このアドレスを設定するのはLAN側のインターフェイスであるswitch0であることに注意する。
今回はIPv4アドレスに合わせて、::100:1というtokenを使用する。
# delete interfaces ethernet eth0 ipv6 # set interfaces switch switch0 address 172.16.100.1/24 # set interfaces switch switch0 address '24XX:XXXX:XXXX:XXXX::100:1/64'
IPv6のdefault routeを設定する
このままではswitch0は外部と繋がっていなく、通信できないためeth0を経由して先ほど調べた対岸のルータのリンクローカルアドレスをネクストホップとして設定する。
# set protocols static route6 '::/0' next-hop 'fe80::feed' interface eth0
DSLiteの設定
# set interfaces ipv6-tunnel v6tun0 description DSLite # set interfaces ipv6-tunnel v6tun0 encapsulation ipip6 # set interfaces ipv6-tunnel v6tun0 local-ip '24XX:XXXX:XXXX:XXXX::100:1' # set interfaces ipv6-tunnel v6tun0 mtu 1452 # set interfaces ipv6-tunnel v6tun0 multicast disable # set interfaces ipv6-tunnel v6tun0 remote-ip '2404:8e01::feed:100' # set interfaces ipv6-tunnel v6tun0 ttl 64
local-ipには先ほど設定したswitch0の静的アドレスを設定する。
remote-ipにはtransixのAFTRのアドレスを設定する。
NTT西日本エリア
- 2404:8e01::feed:100
- 2404:8e01::feed:101
NTT東日本エリア
- 2404:8e00::feed:100
- 2404:8e00::feed:101
ここで、v6tun0に対するNATの設定を行うと通信が不安定になるため行わない
ルーティングテーブルの設定
PBR(Policy-Based Routing)により、送信元IPアドレスによりどちらを経由して通信を行うかを設定するために、ルーティングテーブルを設定する。
# set protocols static table 1 interface-route 0.0.0.0/0 next-hop-interface pppoe0 # set protocols static table 2 interface-route 0.0.0.0/0 next-hop-interface v6tun0
Policy-Based Routingの設定
Policy-Based Routingはfirewallのmodifyで設定する。
IPアドレスが172.16.100.1-172.16.100.10の範囲をサーバセグメントとして、PPPoEによる通信を行い、 それ以外の172.16.100.11-172.16.100.254ではDSLiteによる通信を行うように設定する。
# set firewall modify LAN_PBR rule 10 action modify # set firewall modify LAN_PBR rule 10 description 'LAN to WAN(PPPoE)' # set firewall modify LAN_PBR rule 10 destination address '!172.16.100.0/24' # set firewall modify LAN_PBR rule 10 modify table 1 # set firewall modify LAN_PBR rule 10 source address 172.16.100.1-172.16.100.10 # set firewall modify LAN_PBR rule 20 action modify # set firewall modify LAN_PBR rule 20 description 'LAN to WAN(DSLite)' # set firewall modify LAN_PBR rule 20 destination address '!172.16.100.0/24' # set firewall modify LAN_PBR rule 20 modify table 2 # set firewall modify LAN_PBR rule 20 source address 172.16.100.11-172.16.100.254
# set interfaces switch switch0 firewall in modify LAN_PBR
switch0インターフェイスにこのルールを適応する。
これでIPアドレスにより、DSLiteとPPPoEによる通信を併用することが出来る。
NDProxyによるIPv6環境
LANにRAを配布する
# set interfaces switch switch0 ipv6 dup-addr-detect-transmits 1 # set interfaces switch switch0 ipv6 router-advert cur-hop-limit 64 # set interfaces switch switch0 ipv6 router-advert link-mtu 1500 # set interfaces switch switch0 ipv6 router-advert managed-flag false # set interfaces switch switch0 ipv6 router-advert max-interval 600 # set interfaces switch switch0 ipv6 router-advert other-config-flag true # set interfaces switch switch0 ipv6 router-advert prefix '::/64' autonomous-flag true # set interfaces switch switch0 ipv6 router-advert prefix '::/64' on-link-flag true # set interfaces switch switch0 ipv6 router-advert prefix '::/64' valid-lifetime 2592000 # set interfaces switch switch0 ipv6 router-advert reachable-time 0 # set interfaces switch switch0 ipv6 router-advert retrans-timer 0 # set interfaces switch switch0 ipv6 router-advert send-advert true
これにより、クライアントにIPv6アドレスが割り当てられる
NDProxyのクロスコンパイル
この実装を用いる
ローカルのコンピュータでDockerを用いてクロスコンパイルを行う
EdgeRouter Xはmipselで、EdgeRouter Lite 3はmipsであるため、それぞれの環境にあったコンパイラをインストールする
FROM debian:stretch RUN apt-get update -y RUN apt-get install -y g++-mipsel-linux-gnu g++-mips-linux-gnu make file CMD ["/bin/bash"]
$ sudo docker buld -t mips .
ndppdをcloneする
$ git clone https://github.com/DanielAdolfsson/ndppd.git $ cd ndppd
以下のように mipsel.Makefileを作成する
CXX = /usr/bin/mipsel-linux-gnu-g++ CXXFLAGS = -O2 -s LDFLAGS = -s
ビルドする
(Local)$ sudo docker run --rm -it -v `pwd`:/ndppd mips (docker)# cd /ndppd (docker)# make -f mipsel.Makefile -f Makefile (docker)# file ndppd ndppd: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, BuildID[sha1]=a2a060155ad0e5b70791ea5c06526695126abba7, for GNU/Linux 3.2.0, stripped (docker)# exit (Local)$ scp ndppd er-x:
カレントディレクトリにndppdが生成されるのでscp等でEdgerouterに持って行く
NDProxyの設定
先ほど持ってきたndppdを/config/user-data/ndppdに移動させる
$ sudo mv ndppd /config/user-data/ndppd
/config以下に配置することでファームウェアの更新の際も残る
それぞれ以下のようにファイルを作成する。
/config/user-data/ndppd.conf
proxy eth0 {
router no
timeout 500
autowire yes
keepalive yes
retries 3
ttl 30000
rule ::/0 {
iface switch0
}
}
proxy switch0 {
router yes
timeout 500
autowire yes
keepalive yes
retries 3
ttl 30000
rule ::/0 {
auto
}
}
/config/user-data/ndppd.service
[Unit] Description=ndp_proxy_daemon Wants=network-online.target After=network-online.target [Service] ExecStart=/usr/sbin/ndppd -d -p /run/ndppd.pid Type=forking PIDFile=/run/ndppd.pid [Install] WantedBy=multi-user.target
/config/user-data/setup_ndppd.sh
#!/bin/sh ln -s /config/user-data/ndppd /usr/sbin/ndppd ln -s /config/user-data/ndppd.conf /etc/ndppd.conf ln -s /config/user-data/ndppd.service /etc/systemd/system/ndppd.service systemctl daemon-reload systemctl start ndppd.service systemctl enable ndppd.service
セットアップを行う。
$ sudo /bin/sh /config/user-data/setup_ndppd.sh
/config/user-data/setup_ndppd.shはファームウェアの更新などによって消えてしまった際に実行することでセットアップを行うことが出来る。
再起動を行い、クライアントからもIPv6によるアクセスが出来ることを確認する。
$ reboot


この通りかなりの改善をすることが出来た。
ファイアウォールの設定
このままでは危ないのでファイアウォールの設定行う
set firewall ipv6-name WANv6_IN default-action drop set firewall ipv6-name WANv6_IN description 'WANv6 to LAN' set firewall ipv6-name WANv6_IN enable-default-log set firewall ipv6-name WANv6_IN rule 10 action accept set firewall ipv6-name WANv6_IN rule 10 description 'Allow established/related' set firewall ipv6-name WANv6_IN rule 10 state established enable set firewall ipv6-name WANv6_IN rule 10 state related enable set firewall ipv6-name WANv6_IN rule 20 action accept set firewall ipv6-name WANv6_IN rule 20 description 'Allow IPv6 ICMP' set firewall ipv6-name WANv6_IN rule 20 protocol ipv6-icmp set firewall ipv6-name WANv6_IN rule 30 action drop set firewall ipv6-name WANv6_IN rule 30 description 'Drop invalid state' set firewall ipv6-name WANv6_IN rule 30 state invalid enable set firewall ipv6-name WANv6_LOCAL default-action drop set firewall ipv6-name WANv6_LOCAL description 'WANv6 to Router' set firewall ipv6-name WANv6_LOCAL enable-default-log set firewall ipv6-name WANv6_LOCAL rule 10 action accept set firewall ipv6-name WANv6_LOCAL rule 10 description 'Allow established/related' set firewall ipv6-name WANv6_LOCAL rule 10 state established enable set firewall ipv6-name WANv6_LOCAL rule 10 state related enable set firewall ipv6-name WANv6_LOCAL rule 20 action accept set firewall ipv6-name WANv6_LOCAL rule 20 description 'Allow IPv6 ICMP' set firewall ipv6-name WANv6_LOCAL rule 20 protocol ipv6-icmp set firewall ipv6-name WANv6_LOCAL rule 30 action accept set firewall ipv6-name WANv6_LOCAL rule 30 description 'Allow DHCPv6' set firewall ipv6-name WANv6_LOCAL rule 30 destination port 546 set firewall ipv6-name WANv6_LOCAL rule 30 protocol udp set firewall ipv6-name WANv6_LOCAL rule 40 action accept set firewall ipv6-name WANv6_LOCAL rule 40 description 'Allow DSLite' set firewall ipv6-name WANv6_LOCAL rule 40 protocol ipip set firewall ipv6-name WANv6_LOCAL rule 50 action drop set firewall ipv6-name WANv6_LOCAL rule 50 description 'Drop invalid state' set firewall ipv6-name WANv6_LOCAL rule 50 state invalid enable set interfaces ethernet eth0 firewall in ipv6-name WANv6_IN set interfaces ethernet eth0 firewall local ipv6-name WANv6_LOCAL set firewall name DSLite_IN default-action drop set firewall name DSLite_IN description 'WAN(DSLite) to LAN' set firewall name DSLite_IN rule 10 action accept set firewall name DSLite_IN rule 10 description 'Allow established/related' set firewall name DSLite_IN rule 10 state established enable set firewall name DSLite_IN rule 10 state related enable set firewall name DSLite_IN rule 20 action drop set firewall name DSLite_IN rule 20 description 'Drop invalid state' set firewall name DSLite_IN rule 20 state invalid enable set firewall name DSLite_LOCAL default-action drop set firewall name DSLite_LOCAL description 'WAN(DSLite) to Router' set firewall name DSLite_LOCAL rule 10 action accept set firewall name DSLite_LOCAL rule 10 description 'Allow established/related' set firewall name DSLite_LOCAL rule 10 state established enable set firewall name DSLite_LOCAL rule 10 state related enable set firewall name DSLite_LOCAL rule 20 action drop set firewall name DSLite_LOCAL rule 20 description 'Drop invalid state' set firewall name DSLite_LOCAL rule 20 state invalid enable set interfaces ipv6-tunnel v6tun0 firewall in name DSLite_IN set interfaces ipv6-tunnel v6tun0 firewall local name DSLite_LOCAL set firewall name PPPoE_IN default-action drop set firewall name PPPoE_IN description 'WAN(PPPoE) to LAN' set firewall name PPPoE_IN rule 10 action accept set firewall name PPPoE_IN rule 10 description 'Allow established/related' set firewall name PPPoE_IN rule 10 state established enable set firewall name PPPoE_IN rule 10 state related enable set firewall name PPPoE_IN rule 20 action drop set firewall name PPPoE_IN rule 20 description 'Drop invalid state' set firewall name PPPoE_IN rule 20 state invalid enable set firewall name PPPoE_LOCAL default-action drop set firewall name PPPoE_LOCAL description 'WAN(PPPoE) to Router' set firewall name PPPoE_LOCAL rule 10 action accept set firewall name PPPoE_LOCAL rule 10 description 'Allow established/related' set firewall name PPPoE_LOCAL rule 10 state established enable set firewall name PPPoE_LOCAL rule 10 state related enable set firewall name PPPoE_LOCAL rule 20 action accept set firewall name PPPoE_LOCAL rule 20 description 'Allow ping' set firewall name PPPoE_LOCAL rule 20 destination group address-group ADDRv4_pppoe0 set firewall name PPPoE_LOCAL rule 20 log disable set firewall name PPPoE_LOCAL rule 20 protocol icmp set firewall name PPPoE_LOCAL rule 30 action drop set firewall name PPPoE_LOCAL rule 30 description 'Drop invalid state' set firewall name PPPoE_LOCAL rule 30 state invalid enable set interfaces ethernet eth0 pppoe 0 firewall in name PPPoE_IN set interfaces ethernet eth0 pppoe 0 firewall local name PPPoE_LOCAL set firewall options mss-clamp interface-type pppoe set firewall options mss-clamp mss 1412
WindowsでYubikey5を使ってみる
前提条件
GPGキーを作成し、Yubikeyに移動させた状態とする。
まだの場合は以下を参照してください。 akashisn.hatenablog.com akashisn.hatenablog.com
環境
- Windows 10 Pro (20H2 - 19042.685)
Gpg4winのインストール
https://files.gpg4win.org/ から最新版をダウンロードする。
Kleopatra と GpgEX にチェックを入れてインストールする。

公開鍵のインポート
公開鍵のエクスポート でエクスポートした公開鍵をインポートする。
> gpg --import .\gpg-BF8A708B020A19BB-2020-12-09.txt gpg: 鍵BF8A708B020A19BB: 公開鍵"<名前> <メールアドレス>"をインポートしました gpg: 処理数の合計: 1 gpg: インポート: 1
インポートした公開鍵を究極的に信用する(自分の物のため)。
trust -> 5 -> y と入力する。
> gpg --edit-key BF8A708B020A19BB
gpg (GnuPG) 2.2.25; Copyright (C) 2020 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
pub nistp521/BF8A708B020A19BB
作成: 2020-12-09 有効期限: 無期限 利用法: C
信用: 不明の 有効性: 不明の
sub nistp521/983982062E1BB33D
作成: 2020-12-09 有効期限: 無期限 利用法: S
sub nistp521/008734F36B087C1C
作成: 2020-12-09 有効期限: 無期限 利用法: E
sub nistp521/26BAE38657860920
作成: 2020-12-09 有効期限: 無期限 利用法: A
[ 不明 ] (1). <名前> <メールアドレス>
gpg> trust
pub nistp521/BF8A708B020A19BB
作成: 2020-12-09 有効期限: 無期限 利用法: C
信用: 不明の 有効性: 不明の
sub nistp521/983982062E1BB33D
作成: 2020-12-09 有効期限: 無期限 利用法: S
sub nistp521/008734F36B087C1C
作成: 2020-12-09 有効期限: 無期限 利用法: E
sub nistp521/26BAE38657860920
作成: 2020-12-09 有効期限: 無期限 利用法: A
[ 不明 ] (1). <名前> <メールアドレス>
他のユーザの鍵を正しく検証するために、このユーザの信用度を決めてください
(パスポートを見せてもらったり、他から得たフィンガープリントを検査したり、などなど)
1 = 知らない、または何とも言えない
2 = 信用し ない
3 = まぁまぁ信用する
4 = 充分に信用する
5 = 究極的に信用する
m = メーン・メニューに戻る
あなたの決定は? 5
本当にこの鍵を究極的に信用しますか? (y/N) y
pub nistp521/BF8A708B020A19BB
作成: 2020-12-09 有効期限: 無期限 利用法: C
信用: 究極 有効性: 不明の
sub nistp521/983982062E1BB33D
作成: 2020-12-09 有効期限: 無期限 利用法: S
sub nistp521/008734F36B087C1C
作成: 2020-12-09 有効期限: 無期限 利用法: E
sub nistp521/26BAE38657860920
作成: 2020-12-09 有効期限: 無期限 利用法: A
[ 不明 ] (1). <名前> <メールアドレス>
プログラムを再起動するまで、表示された鍵の有効性は正しくないかもしれない、
ということを念頭においてください。
gpg> q
SSHキーとして使う
GPGの認証SubキーをSSHキーの代わりに使うことができる。 そのため、今まで複数の鍵を管理していたのをYubikeyにある取り出せない秘密鍵に集約することが出来るため利便性も向上しセキュリティ的にも良い感じになる。
scdaemonの設定
Windows10には既に仮想スマートカードリーダ(Windows Helloなど)がインストールされているため、scdaemonがちゃんとYubikeyを使用するようにする必要がある。
Yubikeyがささった状態で以下でデバイスを取得することが出来るので、 デバイス名を%APPDATA%\gnupg\scdaemon.conf に設定してあげる。
> Get-PnpDevice -Class SoftwareDevice | Where-Object {$_.FriendlyName -like "*YubiKey*"} | Select-Object -ExpandProperty FriendlyName
Yubico YubiKey OTP+FIDO+CCID 0
reader-port Yubico YubiKey OTP+FIDO+CCID 0
gpg-agentの設定
gpg-agentはssh-agentとしても動作することが出来るので、
%APPDATA%\gnupg\gpg-agent.confに設定する。
enable-ssh-support enable-putty-support
設定を適応するためにagentを再起動する
> gpg-connect-agent killagent /bye OK closing connection > gpg-connect-agent /bye gpg-connect-agent: gpg-agentが実行されていません - 'C:\Program Files (x86)\GnuPG\bin\gpg-agent.exe'を開始します gpg-connect-agent: agent の起動のため、5秒待ちます... gpg-connect-agent: agent への接続が確立しました。
認識しているかを確認する。
> gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID 0
Application ID ...: Dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: xxxxxxxx
Name of cardholder: <名><姓>
Language prefs ...: ja
Salutation .......:
URL of public key :
Login data .......: <Email等>
Signature PIN ....: 強制なし
Key attributes ...: nistp521 nistp521 nistp521
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 9
KDF setting ......: off
Signature key ....: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
created ....: 2020-12-09 14:35:35
Encryption key....: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
created ....: 2020-12-09 14:36:18
Authentication key: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
created ....: 2020-12-09 14:37:21
General key info..: sub nistp521/983982062E1BB33D 2020-12-09 <名前> <メールアドレス>
sec# nistp521/BF8A708B020A19BB 作成: 2020-12-09 有効期限: 無期限
ssb> nistp521/983982062E1BB33D 作成: 2020-12-09 有効期限: 無期限
カード番号: 0006 xxxxxxxxx
ssb> nistp521/008734F36B087C1C 作成: 2020-12-09 有効期限: 無期限
カード番号: 0006 xxxxxxxxx
ssb> nistp521/26BAE38657860920 作成: 2020-12-09 有効期限: 無期限
カード番号: 0006 xxxxxxxxx
SSH形式の公開鍵に変換する
> gpg --export-ssh-key BF8A708B020A19BB > ~/.ssh/gpg-BF8A708B020A19BB.pub
作成した公開鍵は普通のSSHの公開鍵と同じように扱う。
つまり、接続先の~/.ssh/authorized_keysに追記する。
agent socketのproxyを行う
Windows 10にネイティブにあるOpenSSHではGnuPGが出力するsocketをうまく扱えないようなので、 github.com
socketファイルをWindowsの名前付きパイプにプロキシしてくれるプログラムを使用する。
最新版の wsl2-gpg-agent.exe を適当なところ(今回は C:\tools\utils\wsl2-gpg-agent\wsl2-gpg-agent.exe においた) にコピーする。
> wsl2-gpg-agent.exe --winssh ssh-pageant
と実行するとpageantを\\.\pipe\ssh-pageantにプロキシした状態でシステムトレイに常駐するようになる。
この状態で、SSH_AUTH_SOCK=\\.\pipe\ssh-pageantという環境変数をセットすることによりsshクライアントはプロキシされたgpg-agentを参照するようになる
接続テストをするために既存の ~/.ssh/configでの設定をコメントアウトしておく。
> ssh git@github.com PTY allocation request failed on channel 0 Hi AkashiSN! You've successfully authenticated, but GitHub does not provide shell access. Connection to github.com closed.

github.comにsshをすると、このようにPINを聞かれてちゃんと接続できることが確認できる。
設定の永続化
自動起動の設定
$UserProperty = $(Get-ItemProperty 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders') $WsShell = New-Object -ComObject WScript.Shell $Shortcut = $WsShell.CreateShortcut($UserProperty.Startup+"\wsl2-gpg-agent.exe.lnk") $Shortcut.TargetPath = "C:\tools\utils\wsl2-gpg-agent\wsl2-gpg-agent.exe" $Shortcut.Arguments = "--winssh ssh-pageant" $Shortcut.WorkingDirectory = "C:\tools\utils\wsl2-gpg-agent" $Shortcut.IconLocation = "C:\tools\utils\wsl2-gpg-agent\wsl2-gpg-agent.exe" $Shortcut.Save()
環境変数の設定
環境変数も設定しておく
SSH_AUTH_SOCK=\\.\pipe\ssh-pageant

SSHの設定
~/.ssh/config で何か設定するときは、
Host github.com
HostName github.com
IdentityFile ~/.ssh/gpg-BF8A708B020A19BB.pub
IdentitiesOnly yes
このように、IdentityFile に先ほど作成した公開鍵を設定すると良い。
Git for Windowsの設定
Git for Windowsにはsshコマンドが付属しているため、WindowsネイティブのSSHを使うように設定しないとうまく動かない。
> git config --global core.sshCommand 'C:/Windows/System32/OpenSSH/ssh.exe'
GitHubでのコミット署名
gpg-BF8A708B020A19BB-2020-12-09.txt の公開鍵を https://github.com/settings/keys に設定する。
Gitの設定を行う。
> git config --global user.signingkey BF8A708B020A19BB > git config --global gpg.program 'C:/Program Files (x86)/gnupg/bin/gpg.exe'
デフォルトで署名するには以下を実行する。
> git config --global commit.gpgsign true
手動でコミットに署名をするときは -S オプションを加える。
$ git commit -S -m your commit message
このときOpenPGPのPINを求められる。

ちゃんと署名できていればこんな感じにVerifyマークがつく
WSL2で使う
WSL2ではUSBシリアルをサポートしていないため直接Yubikeyに接続することは出来ない。
そこで、Windowsの名前付きパイプをUnixソケットへプロキシしてAgent転送を行うことでWSL2でもYubikeyを使うことが出来る。
先ほどの wsl2-gpg-agent.exe を使う。
公開鍵のインポート
Windowsで行ったのと同様に公開鍵をインポートして、信用しておく。
WSL2側の設定
socat, lsof のインストールをする
$ sudo apt update $ sudo apt install socat iproute2
.zshrcに以下を追加してログイン時に起動するようにする
wsl2_ssh_pageant_bin="/mnt/c/tools/wsl2-ssh-pageant/wsl2-ssh-pageant.exe" if test -x "$wsl2_ssh_pageant_bin"; then export SSH_AUTH_SOCK="$HOME/.gnupg/S.gpg-agent.ssh" if ! ss -a | grep -q "$SSH_AUTH_SOCK"; then rm -f "$SSH_AUTH_SOCK" (setsid nohup socat UNIX-LISTEN:"$SSH_AUTH_SOCK,fork" EXEC:"$wsl2_ssh_pageant_bin --ssh" >/dev/null 2>&1 &) fi export GPG_AGENT_SOCK="$HOME/.gnupg/S.gpg-agent" if ! ss -a | grep -q "$GPG_AGENT_SOCK"; then rm -rf "$GPG_AGENT_SOCK" (setsid nohup socat UNIX-LISTEN:"$GPG_AGENT_SOCK,fork" EXEC:"$wsl2_ssh_pageant_bin --gpg S.gpg-agent" >/dev/null 2>&1 &) fi export GPG_AGENT_EXTRA_SOCK="$HOME/.gnupg/S.gpg-agent.extra" if ! ss -a | grep -q "$GPG_AGENT_EXTRA_SOCK"; then rm -rf "$GPG_AGENT_EXTRA_SOCK" (setsid nohup socat UNIX-LISTEN:"$GPG_AGENT_EXTRA_SOCK,fork" EXEC:"$wsl2_ssh_pageant_bin --gpg S.gpg-agent.extra" >/dev/null 2>&1 &) fi else echo >&2 "WARNING: $wsl2_ssh_pageant_bin is not executable." fi unset wsl2_ssh_pageant_bin
再度ログインしてYubikeyが認識しているかを確認する。
$ gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID 0
Application ID ...: Dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: xxxxxxxx
Name of cardholder: <名><姓>
Language prefs ...: ja
Salutation .......:
URL of public key :
Login data .......: <Email等>
Signature PIN ....: 強制なし
Key attributes ...: nistp521 nistp521 nistp521
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 9
KDF setting ......: off
Signature key ....: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
created ....: 2020-12-09 14:35:35
Encryption key....: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
created ....: 2020-12-09 14:36:18
Authentication key: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
created ....: 2020-12-09 14:37:21
General key info..: sub nistp521/983982062E1BB33D 2020-12-09 <名前> <メールアドレス>
sec# nistp521/BF8A708B020A19BB 作成: 2020-12-09 有効期限: 無期限
ssb> nistp521/983982062E1BB33D 作成: 2020-12-09 有効期限: 無期限
カード番号: 0006 xxxxxxxxx
ssb> nistp521/008734F36B087C1C 作成: 2020-12-09 有効期限: 無期限
カード番号: 0006 xxxxxxxxx
ssb> nistp521/26BAE38657860920 作成: 2020-12-09 有効期限: 無期限
カード番号: 0006 xxxxxxxxx
これでWSL2でも使用することができたので後は普通のLinuxと同様にコミット署名とかを設定する。
トラブルシューティング
WSL2でいきなり動かなくなったら、
> wsl --shutdown
でwslの再起動を行えばたいてい治る
