それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

debian 11 / bullseye に kvm+qemu を作る

debian 11 でのインストール

debian11 に 仮想マシンkvm+qemu+libvirtで作った.その時のメモ。

sudo apt install qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils virtinst libvirt-daemon dnsmasq-base ovmf 

gnome デスクトップのあるときは、併せて次もインストール。

sudo apt install virt-manager gir1.2-spiceclientgtk-3.0 

以前との違い dnsmasq-base

ネットワークを使うのに/usr/sbin/dnsmasq を libvirtd が要求する。

libvirtのネットワークをNATネットワークにするときに、内部への名前解決にdnsmasq を使うので要求される。

しかし、dnsmasq をはresolved や unboundと競合するので、systemdサービスは除いた dnsmasq-baseのみインストールする。

dnsmasq-baseがインストールされていると、次のようにネットワークが起動する。

f:id:takuya_1st:20220105180025p:plain

インストールは、必須ではない任意である。しかしネットワークが使えないのは不便なので、libvirtで仮想環境を作る際に同時に設定しておく

bridge-utils

iproute2 ( ip コマンド ) で ブリッジを構成できるので、bridge-utils は通常インストールしない思うが、libvirtd が要求するので入れておく。

pcsclite

pcsslite のスマートカード関連のライブラリがインストールされているとpscsliteのスマートカードを読みにいくので、録画関連を使っているときは注意が必要。

ovmf

UEFI の起動を試すのに必要. qemu-efi はArm64になってしまうのでこっちを入れる.

OVMFを入れるとEFIが選べる

f:id:takuya_1st:20220105181520p:plain:w250

gir1.2-spiceclientgtk-3.0

Error opening Spice console, SpiceClientGtk missing になり、画面が表示されないことがある。

f:id:takuya_1st:20220105183115p:plain

VboxでCOMポート(シリアルポート/シリアルコンソール)を使う

vbox の仮想マシンにシリアルポートを使わせる。

シリアル・ポートのログインができるように仮想マシンを構成する f:id:takuya_1st:20220105154252p:plain

virtualboxのシリアルデバイス

実現方法は、いくつかあるのですが、一番よく使われるのは「デバイスを渡す」だとおもう。

個数が増えてくると大変なので、仮想マシンの台数が多いときは、デバイス・ファイルを使うほうが望ましいとは思う。

ホスト・デバイスをブリッジ

一番簡単なのは、ホストのデバイス仮想マシンにわたすこと。

Windowsの場合は、仮想COMポートを作るソフトウェア(com0com)を使って、仮想シリアルポートペア( COM3 - COM4 ) を作る、片側を仮想マシンに渡す。

f:id:takuya_1st:20220105153506p:plain

疑似(仮想)シリアル・ポートのペアができると、Terartermなどでつなぐことができる。

f:id:takuya_1st:20220105155113p:plain

Terartermを2つ起動して、COM4/COM3で通信してキー入力がもう一方に送信されると確認できたら準備完了

仮想マシンにデバイスを渡す。

COM4/COM3でペアになっている。このペアの片方を仮想マシンに渡してあげる。

シリアル有効化(ホストデバイス&COM4)

f:id:takuya_1st:20220105153611p:plain

ちなみに、ここで仮想マシン側にCOM1を指定してるので、仮想マシン側ではttyS0 (=COM1)になる

仮想マシン側でgetty起動

仮想マシン側でgetty を起動してログインできるようにする。仮想マシンにはUbuntuを利用した。 COM4は仮想マシンUbuntu)側で、ttyS0になる。

 sudo systemctl start serial-getty@ttyS0

COM4/COM3ペアの他方のCOM3をTerartermで接続する。

f:id:takuya_1st:20220105153439p:plain

起動時のログとGrubをシリアルに流す。

仮想マシンで、GRUBを設定して、シリアルを有効にする。GRUBがシリアルを使うように仮想マシンを設定する。

/etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="console=tty1 console=ttyS0,115200"
GRUB_TERMINAL="serial console"
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"

grubを再構成

sudo update-grub

COM3につないで起動ログを確認

COM3に接続して、COM4経由で出てくる起動ログを確認する。

f:id:takuya_1st:20220105155709p:plain

WSL+screenの場合

WSLの場合、Windows側でCOM3ポートにアクセスするには。COM3=ttyS3 のように COMXX= ttySXXのマッピングになっている 

wsl sudo screen /dev/ttyS3 115200

参考資料

chocolatety (choco) で自動アップデート(すべて・指定除外・指定全て)

winget があるけど、しばらく眺めておく。choco 使います。

chocolatey でフリーソフトのインストールがかんたん

インストールは簡単になり自動処理になり快適になるが、アップグレードがめんどくさい。

頻繁にアップグレードがくるものをどう扱うかで悩んだ。

たとえば、Google ChromeやBitwardenやJoplinなど、頻繁にアップグレードくるのです。各ソフトウェアが自身でアップグレードしちゃうとChocoと管理関係が切れちゃったりする。ちょっと悩んでたかも。choco側で頻繁にアップグレードを実行することにする。

chocolatey の自動アップデート

choco upgrade all -y

一部を指定除外

一部を指定除外して、対象から外す。

choco upgrade all --except="'skype,conemu'"

ワイルドカードで指定できたら便利だけど、ワイルドカードの指定はできないみたい

choco 自身ののアップグレード

choco upgrade chocolatey -y

chocolatety の自分自身をアップグレードをたまにやっておく

アップグレード後にショートカットが出現する

アップグレードすると、インストールが実行されるので、デスクトップにショートカットが作成されて困る。

del C:\Users\Public\Desktop\*.lnk

ほとんどは、public に作成されるので publick の *.lnk を削除しておけば事足りる。

アップグレード忘れるのでタスクスケジューラ

タスクスケジューラを使って、自動的にアップグレードしておく。 f:id:takuya_1st:20220105142241p:plain

タスクスケジューラでの実行部

タスクスケジューラでは、次のコマンドを実行することにした。

    <Exec>
      <Command>C:\ProgramData\chocolatey\bin\choco.exe</Command>
      <Arguments>upgrade all -y</Arguments>
    </Exec>
    <Exec>
      <Command>C:\ProgramData\chocolatey\bin\choco.exe</Command>
      <Arguments>upgrade chocolatey -y</Arguments>
    </Exec>

デスクトップにショートカットが増えるので、ショートカットが出現したらアップグレードしたとわかるので、削除コマンドは実行しないことにした。

タスクスケジューラの注意点

デフォルトでは、非ログイン時・スリープ時に実行されないので、その辺はうまく調整する。 いまのところは、次のように、ログオン状態とスリープ状態を設定した。このあたりは適宜見直しておきたい。

f:id:takuya_1st:20220105142803p:plain

f:id:takuya_1st:20220105142925p:plain

参考資料

docs.chocolatey.org

linuxのipコマンドでgretap を作って通信してみる

gretap を作る

GRE Tap でイーサネット・フレームを転送するVPNを作ってみたい。

wg0 でL2-VPNはできると思う。

wg に L2-VPN機能がないので、 wg 上に ip bridge で gre tap を構成すればいい。

wireguardではL2はサポートされていなので、WG上にGRETAPでL2転送をかけてみたらいいと思う。ただし、iPhoneiOSではgreを使えないので、どんな手段を用いてもリモートからGoogle Homeを呼び出しはできないと思う。iphoneL2TPをするならwigreguardは使えない

もっとかんたんに、L2トンネルを使うのなら、softetherOpenVPNを使うしかない。

GRE tap を体験するために、Linux仮想マシンを作る。

仮想マシンをつくると流石に重いので、LXCを使ってコンテナを使うことにする。

netnsがあるので、netns でやれば良いわけですが。netnsあまり使ってないので、lxc でやります。

docker でやってもいいですが、dockerはデフォルトでネットワークがついてきたり、モジュールがなかったりして面倒なので、フルで仮想マシンとして動作するLXCでやることにしました。

ホスト・マシン

今回、すべての構成をUbuntu/DebianのLXCでやっています。

ホストマシンには、Ubuntu 20.04 を使いました。LXCをインストールして使えるようにしておきます。

sudo snap install lxd
sudo lxd init 

インストールしたら、ストレージを設定して コンテナが作成できるように設定します。それで準備完了です。

実験する4台の接続

ざっとみて4台いるわけですよ。

m01 と m02 の間をGRETAPで接続します。

c01 から c02 へ GRETAPのトンネル経由で抜けるように作っていきます。

f:id:takuya_1st:20211229152827p:plain

トンネルをどの経路の上に作るかがポイントです。

GRETAPをwg0の上に作ればwireguardをつかったL2とんね、IPSecを使えばIPsec上にL2トンネル。どこの経路で作るかで呼び方は代わると思う。

今回は、単純に ブリッジでm01/m02 を接続して、ブリッジを経由したGREトンネルを作りたいと思う。

詳細な接続

具体的に作るには、複雑な構成になる。

今回作ったネットワーク構成を詳細に書き込むとこんな感じ。 f:id:takuya_1st:20211229152841p:plain

veth0/brige がややこしい。vethでは、veth ペアを作る。verthは両端がペアで作られる。今回は。片方をLXCへ、もう一方をブリッジに入れる。

疎通テスト用にIPも多めに割振ってるのでちょっとややこしい。

ブリッジとvethの接続について

br0 の接続

次のように作った、このbr0 の接続について。

f:id:takuya_1st:20211229152905p:plain:w320

vethを使ってbr0へ

br0 をホスト側に作成、vethペアを2本作成、そしてbr0に突っ込む

veth のペアの一方はLXCへ

f:id:takuya_1st:20211229152918p:plain:w320

verhを作ったら、もう一方をホスト側の制御から外し、LXC制御を渡す。LXC側にアサインしたら、ホスト側からは見えなくなる。

ブリッジは、vethペア作成、LXCのコンテナへ突っ込む、ブリッジへ接続する。この繰り返しで作っていく。

コンテナ間のブリッジbr0/br1/br2

コンテナ間のブリッジは、ホスト側に作るので、ホスト側から見える。

次の図の、br1 はホスト側に存在する。

f:id:takuya_1st:20211229152931p:plain:w320

lxc コンテナ作成・起動

コンテナのネットワークは自分で作っていくので、ネットワークを持たないコンテナを作る。「ネットワークなしコンテナ」を作成すると、LXCから注意が出るが、意図した動作なので、注意は無視しておく。

lxc launch ubuntu:20.04 m01;
lxc launch ubuntu:20.04 m02;
lxc launch ubuntu:20.04 c01;
lxc launch ubuntu:20.04 c02;
# lxc restart m01
# lxc restart m02
# lxc restart c01
# lxc restart c02

br0 を作成

sudo ip link add name veth1 type veth peer name veth1-br
sudo ip link add name veth2 type veth peer name veth2-br
sudo ip link add br0 type bridge
sudo ip link set veth1-br master br0
sudo ip link set veth2-br master br0
lxc config device add m01 eth0 nic nictype=physical parent=veth1
lxc config device add m02 eth0 nic nictype=physical parent=veth2

br1 を作成

sudo ip link add name veth10 type veth peer name veth10-br
sudo ip link add name veth11 type veth peer name veth11-br
lxc config device add m01 eth1 nic nictype=physical parent=veth10
lxc config device add c01 eth0 nic nictype=physical parent=veth11
sudo ip link add br1 type bridge
sudo ip link set veth10-br master  br1
sudo ip link set veth11-br master  br1

br2 を作成

sudo ip link add name veth20 type veth peer name veth20-br
sudo ip link add name veth21 type veth peer name veth21-br
lxc config device add m02 eth1 nic nictype=physical parent=veth20
lxc config device add c02 eth0 nic nictype=physical parent=veth21
sudo ip link add br2 type bridge
sudo ip link set veth20-br master br2
sudo ip link set veth21-br master br2

アドレスをわり付け

sudo ip addr add 10.1.0.254/24 dev br0
lxc exec m01 -- ip addr add 10.1.0.1/24 dev eth0
lxc exec m02 -- ip addr add 10.1.0.2/24 dev eth0
sudo ip addr add 172.16.101.254/24 dev br1
lxc exec c01 -- ip addr add 172.16.101.2/24 dev eth0
sudo ip addr add 172.16.102.254/24 dev br2
lxc exec c02 -- ip addr add 172.16.102.2/24 dev eth0

リンクアップ(忘れがち。忘れると動かないので注意)

sudo ip link set br0 up
sudo ip link set veth1-br up
sudo ip link set veth2-br up
sudo ip link set br1 up
sudo ip link set veth10-br up
sudo ip link set veth11-br up
sudo ip link set br2 up
sudo ip link set veth20-br up
sudo ip link set veth21-br up
lxc exec m01 ip link set eth0 up
lxc exec m01 ip link set eth1 up
lxc exec m02 ip link set eth0 up
lxc exec m02 ip link set eth1 up
lxc exec c01 ip link set eth0 up
lxc exec c02 ip link set eth0 up

up を忘れると、通信できない。通信できず、経路が悪いのか設定が悪いのか分からずに、嵌まり込むので注意する。事前にしっかりとlink up しておく。 とくにvethでは両端をUPしていくので注意。

vethのup はめんどくさいけど、漏れなくダブりなく設定を頑張る。

ブリッジに入れたnic間の通信許可

sudo sysctl net.bridge.bridge-nf-call-iptables=0

ブリッジ・インタフェースは、iptablesで制御されてしまうので、それを外しバカ・ハブ(ダムハブ)として動作させる.この処理はなくても動くと思う。

コンテナ内部 ブリッジ br-gre01 作成

lxc exec m01 ip link add br-gre01 type bridge
lxc exec m01 ip link set eth1 master br-gre01
lxc exec m01 ip link set br-gre01 up
lxc exec m01 ip addr add 172.16.101.1/24 dev br-gre01

gretap を作ったらブリッジに入れて共有するので作っておく。

コンテナ内部 ブリッジ br-gre02 作成

lxc exec m02 ip link add br-gre02 type bridge
lxc exec m02 ip link set br-gre02 up
lxc exec m02 ip link set eth1 master br-gre02
lxc exec m02 ip addr add 172.16.102.1/24 dev br-gre02

gretap を作ったらブリッジに入れて共有するので作っておく。

動作チェック

ping -c 1 10.1.0.254
ping -c 1 172.16.101.254
ping -c 1 172.16.102.254
lxc exec m01 -- ping -c 1 10.1.0.254
lxc exec m01 -- ping -c 1 172.16.101.254
lxc exec m01 -- ping -c 1 172.16.101.2
lxc exec m02 -- ping -c 1 10.1.0.254
lxc exec m02 -- ping -c 1 172.16.102.254
lxc exec m02 -- ping -c 1 172.16.102.2

ここまでで、通信経路と仮想デバイス接続が間違ってないか確認する。

ネットワークとコンテナが間違ってる通信ができない。そのときは、一つずつミスを探してやり直し。

連続したlxc exec -- command を、複数行をまとめてコピペすると動かないので注意する。

greptap を作って通信する。

gre を作成 して ブリッジに入れる

lxc exec m01 -- ip link add name gre01 type gretap remote 10.1.0.2
lxc exec m02 -- ip link add name gre02 type gretap remote 10.1.0.1
lxc exec m01 -- ip link set gre01 master br-gre01
lxc exec m02 -- ip link set gre02 master br-gre02
lxc exec m01 -- ip link set gre01 up
lxc exec m02 -- ip link set gre02 up
lxc exec m01 -- ip link set gre01 mtu 1450
lxc exec m02 -- ip link set gre02 mtu 1450

gre0は予約されているので、別名にした。

ここも、lxc exec -- command に注意する。複数行をまとめてコピペすると、改行が -- で吸収されてしまう。なので、まとめてコピペせずに1行ずつやる

gre 経由の通信を確認

sudo ip addr add 172.16.101.253/24 dev br2
lxc exec m02 -- ip addr add 172.16.101.3/24 dev br-gre02
lxc exec c02 -- ip addr add 172.16.101.4/24 dev eth0

疎通を確認

lxc exec m01 -- ping -c 1 172.16.101.253
lxc exec m01 -- ping -c 1 172.16.101.3
lxc exec m01 -- ping -c 1 172.16.101.4
lxc exec c01 -- ping -c 1 172.16.101.253
lxc exec c01 -- ping -c 1 172.16.101.3
lxc exec c01 -- ping -c 1 172.16.101.4

c01 と c02 が通信できたらイーサネットフレームが転送されている。pingの応答が来たら成功。

DHCP がgretap 経由で転送されているか確認

pingの他にも dhcp などを試してパケットを確認しておく

ホスト側からブリッジの通信を見つつ

sudo tcpdump -i br2

別のターミナルを立ち上げてDHCPパケットを流して見る。

lxc exec c01 -- dhclient -4 -v eth0
lxc exec c01 -- dhclient -6 -v eth0

tcpdump でパケットが確認できたら無事にGRETAPできていると言える。

ubuntuを使った理由はここで、tcpdump は最初からインストール済みでコンテナが作成される。

ARPの確認

arp キャッシュを見てみる。ip neigh で隣接しているMACアドレスが分かる。ここに出てきていてればOKである。

takuya@raspi-ubuntu:~$ lxc exec c01 -- ip neigh
172.16.101.254 dev eth0 lladdr 3e:0a:df:7d:f4:52 STALE
172.16.101.1 dev eth0 lladdr 16:9a:f2:ba:c1:f0 STALE
172.16.101.253 dev eth0 lladdr 3e:0a:df:7d:f4:52 STALE
172.16.101.4 dev eth0 lladdr f6:ca:27:f5:91:cc STALE
172.16.101.3 dev eth0 lladdr c6:2c:d0:0e:4e:1b STALE

ARPが抜けてるか確認

tcpdump -i br1 arp
lxc exec m02 tcpdump -i br-gre02 arp

ARPが抜けてない場合は、arptablesをオフにする必要があるかもしれない。

mDNSが使えるかチェック

mDNSは、ubuntuなら最初から稼働しているはずなのでチェックしておく

lxc exec c01 -- ping c02.local

ubuntu 以外だと、avahi-daemon を入れる必要があり、仮想マシンを外部ネットワークへ接続する必要があるので、ubuntu 以外をコンテナに使うとめんどくさいんだよね。

wireguardの場合

veth1-br0-verth1 の部分が、wg0 の wireguardネットワークになるだけで動くはずである。まだ試してない。

今回使ったもの

です。

openwrt でやる場合

WRTで実験するなら、opkg install kmod-gregreを足してやる必要がある。kmod-gre を足すと、デフォルトで gretap0 が生えてくる

参考資料

iproute2を使ってARPエントリ(arpテーブルarpキャッシュ)を表示する

ip コマンドを使って arp キャッシュを表示する

arp コマンドが無い。

L2のARPのキャッシュを表示するのは、arp コマンドを使うが、現代では初期インストールされていない。

ip neigh を使う。

ip neigh を使ってneighbor(近隣)を調べられる。arp は無いが代わりに、ip コマンドで完結する。

ip neigh と arp の比較

ip コマンドと arp コマンドの結果を比較してみる。

takuya@raspi-ubuntu:~$ ip -4 neigh show dev lxdbr0
10.105.86.3 lladdr 00:16:3e:86:00:2c STALE
10.105.86.45 lladdr 00:16:3e:45:80:f3 STALE
takuya@raspi-ubuntu:~$ arp -i lxdbr0
Address                  HWtype  HWaddress           Flags Mask            Iface
10.105.86.3              ether   00:16:3e:86:00:2c   C                     lxdbr0
10.105.86.45             ether   00:16:3e:45:80:f3   C                     lxdbr0

ip neigh の場合は、v6 も表示される

ipコマンドの場合neigh を使うと、v6 アドレスも出てくる。

takuya@raspi-ubuntu:~$ ip neigh show dev lxdbr0
10.105.86.3 lladdr 00:16:3e:86:00:2c STALE
10.105.86.45 lladdr 00:16:3e:45:80:f3 STALE
fe80::216:3eff:fe45:80f3 lladdr 00:16:3e:45:80:f3 STALE
fe80::216:3eff:fe67:1747 lladdr 00:16:3e:67:17:47 router STALE
fe80::216:3eff:fe86:2c lladdr 00:16:3e:86:00:2c STALE
fd42:9963:9019:21c8:216:3eff:fe45:80f3 lladdr 00:16:3e:45:80:f3 STALE
fd42:9963:9019:21c8:216:3eff:fe86:2c lladdr 00:16:3e:86:00:2c STALE

ip コマンドは v6対応なのでこっちのほうが使いやすいですね neig は近隣探索になる。

lxc で確認する

takuya@raspi-ubuntu:~$ lxc exec sample02 -- ip -4 neigh
10.105.86.1 dev eth0 lladdr 00:16:3e:67:17:47 STALE

curl でDoHを使ってDNS問い合わせをしてみる

DoH をcurlでやる

github を見ていたら、curl にDoHのサポートが入ってることを知った。早速使ってみました。

DNS問い合わせを curl で DoH する。

使うDoHサーバーはcloudflare を選びました。

curl -v  --doh-url https://cloudflare-dns.com/dns-query t.co

リダイレクトでサーバーへ接続

オプションにリダイレクトを入れると、DoHした結果をそのまま使ってHTTPリクエストをしてHTMLを取得しに行く

このリダイレクトの仕組みがあると確実にDNS問い合わせ結果を、ネットワークスタックの監視プログラムなどに割り込みされることなく、確実に目的のサーバーでたどり着けますね。

curl -vL  --doh-url https://cloudflare-dns.com/dns-query https://t.co

実際やってみたところ

f:id:takuya_1st:20211227171111p:plain

DoHは、途中の経路の暗号化

暗号化により、盗聴・改竄・成りすましは防止できますが、DoH通信先サーバーが「信用できる」かどうかは別問題であり、DoH先にしていたサーバがDNS応答内容を「書き換え」してブロッキングしてる可能性もあるので十分に注意する。ただ、経路上で成りすましはおこりえないので安心である。

DoHを展開する有名どころ

その他に、大量のDoHサーバーが展開されている。たぶんDNSトラフィックを監視するのは、大手以外では不可能になるのだろう。

そして、大手企業を「ポリティカル・コレクトネス」で締め上げるていくことでインターネットは安全になっていくのであろう。

そのうち、自前でDNSを引いてるだけで、闇インターネットだとかダークウェブとか言われうのであろう。

uBlockのフィルタで文字列(キーワード)を条件にブロックする

uBlock のブロックを要素のテキストでブロックする

これは、XPATHを使うとできます。

www.amazon.co.jp##:xpath(//div[@data-cel-widget][contains(.//span ,"再び購入")])

CSSブロックの問題点。

通常のublock は ドメイン、URLとCSSのクラス名で指定しますが、CSSのクラス名には限界がある。

また昨今のウェブサイトランダムはCSSクラス名が使われる。管理上cssnpm build されている。、CSSのクラス名がランダムでユニークなIDになっており、クラス名で指定すると、広告ブロックがあっという間に陳腐化(意味をなさなくなる)してしまう。

また、CSSブロックだと「どこをブロックした」かがわかりにくく、ブロックを間違えてたり、ブロックしすぎたときに除去するなどのメンテナンスが不便である。

キーワードで指定したい。

そこで、要素に含まれる文字列で指定したい。

たぶんこれが簡潔でメンテが用意だと思う。

しかし、CSSでテキスト文字列を指定するのは難しい。

かわりにXpathにある'contains()' 関数を使えるといいなと思ってたらuBlock origin はXpathをサポートしているとわかったので歓喜した。

xpath を記入する

f:id:takuya_1st:20211226162046p:plain

xpathブロックの記入例

ブロックのルールにxpathを書くときは、次のように書く。

:xpath(//element[contains(.//span ,"再び購入")])

ブロックに、xpathを書くときは、クォートとマーキングをちゃんとやる

##:xpath("//div") # ← クォートたらブロックルールの記述エラー
###:xpath ← `#` が多すぎ

正しい記述

##:xpath(//body//div)

xpath contains について

containsCSSではなくXpathで明示的に要素をセレクトするセレクターで使う関数である。

contains は慣れてないと使いにくいが次のようになっている。

contains( 対象ノード選択, 文字列 )

なので次のようになっている

contains( . , "オススメ商品" ) # カレントノードから下のすべてのテキスト・ノードを探す。
contains( ./span , "オススメ商品" ) # カレントノード直下の ./span に'文字列'が含まれているとマッチ
contains( .//span , "オススメ商品" ) # カレントノード子孫ノードに .//span に'文字列'が含まれているとマッチ

xpath と contains の関係

Xpathでは、条件にマッチしたノードを取り出す。そして選択時は選択条件を追記していく

//div # すべてのdiv

## この辺はCSSでもできそう
//div[@data-cwd]  ## <div  data-ads > とdivかつdata-ads属性があるもの すべて
//div[@data-cwd="youname"]  ## <div  data-cwd > とdivかつdata-cwd=younameであるもの すべて
//div[contains(@data-ads, "name" )]  ## div で 属性値チェック [data-cwd*="youname"]
//div[contains( ./text(), "name" )]  ## div のテキストノードで'name' があるか
## この辺はCSSでは無理そう
//div[contains( ./, "block" )][contains( ./, "detected" )]  ## div の文字列に 'block detected' の3つが含まれるもの
//div[contains( ./, "アド" )][contains( ./, "検出" )][contains( ./, "無効" )]  ## div の文字列に 'アド 検出 無効' の3つが含まれるもの

たとえば、Amazonのページ

「検索内容に関係したブランド」という迷惑なレコメンドがある場合。

##:xpath(//div[@data-cel-widget][contains(.//span ,"検索内容に関連したブランド")])

これでフィルタにマッチングさせて、わかりやすく文字列でフィルタを設定することができる。

このように、「表示されている文字」や「タイトルの文字」「文章」を元にブロックガッツリかけて便利です。 f:id:takuya_1st:20211226162103p:plain

xpathについて

XPATHについては、過去記事を参照してください。

過去記事

macOSのwifi設定(ssid/password)をiOSと共有するしないを設定する。

macOSSSIDごとに共有可能か選択可能なのですね。

知りませんでした。macOSSSIDごとの設定に「共有オプション」がありました。

f:id:takuya_1st:20211223184739p:plain

共有オプションを外しておけば、iOSと共有されることがなくなるはずです。

オプションの出し方。

mac無線LAN接続の詳細を押しながらクリック

f:id:takuya_1st:20211223185501p:plain

ssh/rsyncで`Warning: No xauth data; using fake authentication data for X11 forwarding.`

rsyncssh でwarning が出るようになった。

Warning: No xauth data; using fake authentication data for X11 forwarding.

原因

~/.ssh/config にX11の設定をしている
xauth のPATHがわからない。~/.Xauthorityがない

対応1

x11 の設定を消す。(XQuratz)を使わないのであれば。

Host sever-1
    Hostname 192.168.2.5
    #ForwardX11 yes
    #ForwardX11Trusted yes
    #XAuthLocation /opt/X11/bin/xauth

対応2

X11を使うなら、.Xauthority の設定をやり直す。

rm  ~/.Xauthority*
open -a XQuartz.app
xauth generate $DISPLAY
ls  .Xauthority*
echo $DISPLAY

設定をやり直す。

~/.ssh/config

Host sever-1
    Hostname 192.168.2.5
    ForwardX11 yes
    ForwardX11Trusted yes
    XAuthLocation /opt/X11/bin/xauth

参考資料

https://sonotaropp.hatenablog.com/entry/2019/07/22/154545

wireguardのパケットサイズとMTUの値。

MTUの値

wireguard のMTUの値を調べた。

1420 = ip6 to ip6 で wireguardしたとき
1440 = ip4 to ip4 で wireguardしたとき

パケットはこんな感じになりますね。

f:id:takuya_1st:20211222173918p:plain

wireguardのパケットについては

IP以外に、40バイトを使います。

https://lists.zx2c4.com/pipermail/wireguard/2017-December/002201.htmlによれば

The overhead of WireGuard breaks down as follows:
- 20-byte IPv4 header or 40 byte IPv6 header
- 8-byte UDP header
- 4-byte type
- 4-byte key index
- 8-byte nonce
- N-byte encrypted data
- 16-byte authentication tag

ということです。

フレッツPPPoE経由でwireguardやったとき

フレッツPPPoEは、MTU1454 です。20+8+16+2=46バイト切り詰めです。
残った1454からwireguard が使う40バイトとip4の20バイトを切り詰めです。
ってことは、1394かな。

f:id:takuya_1st:20211222175831p:plain

ds-liteの場合や、ybb/sb のipip の場合はどうなるんだろう。

参考サイト

wireguardのwg-quickにルーティング・テーブルを触らせない。Table=off

wireguard は便利なんだけどwg-quickに問題が。

wireguard は手軽でそこそこ速く、使いやすい。iOSからも使えるので、ここ一年CellularData通信は、ずっとwireguardしてる。

ほとんどの人は、wg-quick を使ってると思う。でも、私は今まで使ってない。

wg-quick は、ルーティングを書き換えすぎて困ってた。

問題点 wg-quick がルーティングを書き換えすぎる

次のように、wq-quick で wg0 を起動すると、一気に route を書き換えに来る。

takuya@ubuntu01:~$ sudo wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 172.16.3.3/32 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] wg set wg0 fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] iptables-restore -n

対応 table=offを書く。

iproute を使ってルーティングを書き変えないように、テーブル利用(書き換え)を制限します。

[Interface]
PrivateKey = XXXXXXXXXXXXXXXXX
Address =  172.16.3.3/32

Table=off # これを書く。
AllowIPs=0.0.0.0/0 

セカンドベストな対応 table=mainを書く。

table をmain テーブルと同じに書かせることで、ミスを防げます。

[Interface]
PrivateKey = XXXXXXXXXXXXXXXX
Address =  172.16.3.3/32

Table=main # これを書く。
# AllowIPs=0.0.0.0/0 # main 時はできない

テーブルにmainを指定すると、ip route と同じものが出てきます。

ただし、main を使う場合は、AllowIPs=0.0.0.0/0を指定すると、デフォルトルートが衝突して RTNETLINK answers: File exists になります。

[#] ip -4 route add 0.0.0.0/0 dev wg0 table main
RTNETLINK answers: File exists
[#] ip link delete dev wg0

これが、個人的に困っていた問題です。仕方ないので wq-quick を諦めて、wgコマンドでちまちま接続していました。

個人的に困ってた問題

2点ある。個人的に困っていた問題点がある。

  1. デフォルト・ルートを上書きされる。
  2. 知らない名前のiproute でテーブルを使われる。

それが、先程の例ではこの箇所として接続ログに出力されている。

[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820

デフォルトルートを上書きされる。

AllowedIPs に すべて(0.0.0.0/0) を指定すると、デフォルトルートが書かれる。

AllowedIPs でガッツリ許可(0.0.0.0/0)をすると

テーブル未指定で、0.0.0.0/0を許可する

[Interface]
## 略
[Peer]
## 略
AllowedIPs =  0.0.0.0/0

この状態で接続する

[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820

このように、デフォルト・ルートを書き換えられてしまう。

そして、そのルーティングはルーティングテーブル表示 ip route show には出てこない。wg-quick がtable名を指定してルーティングを入れるためである。

さらなる問題点:table名

wg-quick はiproute のテーブル指定を使っている。テーブルにはポート番号が使われる。

[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820

テーブルを使うのを知っていたらいいのだけれど。知らないとルートが見つからず泥沼にはまり込むことになる。

普段からテーブル指定を省略してると「うっかり見逃す」事が多い

テーブル指定なしでルート一覧

$ sudo ip route list table all
default via 192.168.1.1 dev br0 metric 99
192.168.1.0/24 dev br0 proto kernel scope link src 192.168.1.240

テーブル指定してルートを一覧

テーブル名がポート番号と知ってないと色々とめんどくさい。

$ sudo ip route list table 51820
default dev wg0 scope link

ルーティングテーブルの全テーブルを表示

sudo ip -4 route list table all

実際にやってみると、様々なテーブルがあることがわかる。

$ sudo ip -4 route list table all
default dev wg0 table 51820 scope link
default via 192.168.1.1 dev br0 metric 99
192.168.1.0/24 dev br0 proto kernel scope link src 192.168.1.240
broadcast 127.0.0.0 dev lo table local proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo table local proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo table local proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo table local proto kernel scope link src 127.0.0.1
local 172.16.3.3 dev wg0 table local proto kernel scope host src 172.16.3.3
broadcast 192.168.1.0 dev br0 table local proto kernel scope link src 192.168.1.240
local 192.168.1.240 dev br0 table local proto kernel scope host src 192.168.1.240
local 192.168.1.244 dev br0 table local proto kernel scope host src 192.168.1.240
broadcast 192.168.1.255 dev br0 table local proto kernel scope link src 192.168.1.240

テーブル(main/local/default/all) の指定を知らないと、ただただ、wq-quick は謎のルーティングを書いているようにしか見えない。

そして、それはip route show だけを普段使ってると、ミスを誘発する。

table=main の場合

先述したとおり、ルーティングはip route で表示される。table=main だからip route で表示が可能

しかし、mainのデフォルトルートが衝突して接続できないとなり、エラーに。

個人的には、メトリック入れてほしい。と思っていたのですが、できないようです。

wg-quick は怖い

以上のことから、wq-quick を使う前に、ip route と iproute table を知っておく必要があると思います。

ちゃんと知っておかないと、ルーティングが意図通りにならなくて困ると思います。

仮に、知っていても、ip route(main) の方をよく使うため、意図しないとチェックが漏れます。

無意識なチェック漏れが発生するので、とても怖いと思うのです。

AllowIPsやPre/Post を工夫する前にテーブルの確認

Pre/Post Up/Down でルーティングをしたりフォワードを書き換える前に、一度 ip route show table all で 「ルーティング・テーブル」の「テーブル」確認したほうがいいと思うのです。ルーティング・テーブルにはテーブル名という「名前空間」らしきものがあるのです。

そして、テーブルが本当に必要ない(試験的につなぐだけ)のようなときと、PCを全転送するするとき、AllowIPsでガッツリ指定するけどiptablesでFORWARDはまだ書いてないとき、など状況で使い分ける必要があるのでした。

懲りずに同じミスで2回もハマったのです。

約1年前にも同じ現象でルーティングを見失ってハマったのです。そして記事に書いたのに、忘れて同じミスをして、1年前と同じスタックをしたのです。

wq-qucik 怖いよ。

参考URL

OpenWrt x86のアップグレード手順(見直し

2023-10-16 追記

手順を見直して、新規エントリして書き直した。 openwrtのアップグレード手順(見直しの見直し - それマグで!

以下 以前の記録。

x86_64のアップグレード手順を公式Wikiに従って見直してみた。公式Wikiがロードが早くなって読みやすくなったし、整理されて読みやすくなって便利だ。

19.07.{1,2,3,4,5} を21.xへアップグレードしながらアップグレード手順を見直した。

アップグレード手順

  1. opkg の一覧の保存
  2. 保存が必要なファイルを列挙。sysupgrade.conf
  3. 設定の保存とバックアップ
  4. WEBか、コマンドからアップグレード
  5. SSH ログインしてopkgをインストール

手順1

opkg save 

手順2

## 保存するファイルの追加
echo path/to/config >> /etc/sysupgrade.conf
## 保存するファイルの確認
sysupgrade -l 

手順3

## バックアップ作成
sysupgrade --create-backup $HOSTNAME-$( date -I ).tgz
## バックアップ保存(scpやUSBで)
scp $HOSTNAME-$( date -I ).tgz takuya@myserver:~/

または、WEB(luci)の画面から。っていうか、WEB-UIからやるのが楽ちん。

手順4

URL=https://downloads.openwrt.org/releases/21.02.1/targets/x86/64/openwrt-21.02.1-x86-64-generic-ext4-combined.img.gz
sysupgrade  --test -f $( date -I ).tgz -v  $URL
sysupgrade  -f $( date -I ).tgz -v  $URL

コマンドでやるより、WEB画面の方が圧倒的に楽ちん。っていうかコマンドからは地獄。

手順5

ssh wrt-router
### pppoeが起動してないときは 
# ip route add default via 192.168.111.111 # 別のルータ経由で出る
## opkg構成を復元
opkg restore

ここで、PPPoEにつながってないと詰むので、別のルータを用意してPPPoEさせるほうがいい。

各手順について

各手順ついて、知っておく必要があったこと、実際にアップグレードして起きたトラブルと対応をまとめておく。

opkg でインストールしたものを保存

opkg save
opkg restore  # 再現インストール

注意点 opkg save コマンドは、19.x 系には存在しないので、スクリプトをとってくる.

saveがない場合

wget -O opkg-extras.sh "https://openwrt.org/_export/code/docs/guide-user/advanced/opkg_extras?codeblock=0"
. ./opkg-extras.sh

アップグレード時に維持する設定ファイルを指定sysupgrade.conf

アップグレードでファームを書き換えると設定もファイルも消える。x86/64のEXT4を使っていてるが、容赦なくext4もまっさらになる。

そこで、sysypgrade.confを使って、アップグレード後に保持するファイル指定が必要。

  • /etc/configにあるファイルは保持される。
  • /etc/sysupgrade.conf に書いたファイルは追加で保持される。
  • 例外的にパッケージが指定したファイルは保持される ( 例 /etc/unbound/unbound_srv.conf など)

その他: 特定アップグレードの注意点。

  • SoftEtherの設定は保持されない
  • DDNSスクリプトは19.x と 21.x で違うので設定が保持されない。
  • /root/.ssh は破棄されるので、もし使ってる場合は、 sysupgrade.confに書くこと
  • chsh している場合は、/bin/ash に戻しておくこと。
  • luci-proto 関連
  • hotplug 関連
  • opkgを再インストール時の注意
  • ipv6 NGNの注意。

softether の設定は保持されない

そのままでは、/etc/ 中に、softetherの設定は存在しない、パッケージが指定してないので、設定はバックアップされないので注意する。

SoftEtherについては、次の3つの選択肢がある。

  • エクスポート・インポート
  • 設定ファイルをバックアップ(sysupgrade.conf)に含める
  • vpncmd を作っておく。

エクスポートする場合

vpncmd /CLIENT localhost /CMD AccountExport $NAME /SAVEPATH:/etc/config/softether-$name.config

sysupgradeに含めるなら、設定は次の場所にある。

/usr/libexec/softethervpn/vpn_client.config

再設定のvpncmd を作っておく(おすすめ

vpncmd /CLIENT localhost /CMD NicCreate soeth0
vpncmd /CLIENT localhost /CMD AccountCreate ocn /SERVER:vpn.example.com:443 /HUB:Vpn /USERNAME:takuya@myCA /NICNAME:soeth0
vpncmd /CLIENT localhost /CMD AccountPasswordSet ocn /PASSWORD:*****  /TYPE:radius
vpncmd /CLIENT localhost /CMD AccountConnect ocn
udhcpc -i vpn_soeth0 -s /etc/config/custom/softether/dhcp.sh
vpncmd /CLIENT localhost /CMD AccountDisconnect ocn

DHCP割当をもらうときは、udhcpcを使って割当をもらう

DDNSの設定

DDNSの設定は、19.07 と 21.0 で構成が違うようです。

21.xへアップグレードしたあと、ddns設定が飛んでしまいました。

19→21のアップグレードは、ddns関連の罠が多いので注意する。

ddnsスクリプトは、それ自体が一覧としてopkgとは別管理になったみたい。

なので一旦設定を破棄して、インストールし直して、設定し直したたほうが良さそうです。

mv /etc/config/ddns /etc/config/ddns.my.conf
service ddns stop
opkg reinstall ddns-scripts luci-app-ddns    ddns-scripts-cloudflare
mv /etc/config/ddns.my.conf /etc/config/ddns 
vim /etc/config/ddns  # または luci から作り直し。

SSH

/root/.sshの鍵は sysupgrade.conf で指定しないと、消えます。

wrt の root でどこか他のサーバにsshしているなら注意。

chshの注意

インストール後、ashで起動します。

chshbash指定したままアップグレードすると、、bashが未インストール状態で起動します。

bashが見つからなくてログイン失敗します。Luci 入れてる場合はWebからインストールが可能なので復旧できる。

Luci 入れてない場合は、完全に詰み。諦めるしかない。シリアルコンソールを使ってブート時に何とかする。潔く諦める。

luci-proto 関連

luci-proto をopkgでインストールしたWRTで、設定を保持ししてアップグレードすると、エラーになる。

初期起動時にluci-protoが見つからなくて、WEBからネットワークの状態が見られない。

wrt自体は起動するので、大至急 opkg restoreで luci-protoを戻すこと。

hotplug 関連

hotplug関連であれこれしてるときは、設定が誤作動の元になるのでいったんhotplugのカスタマイズを無効にする。

無効にしてからアップグレードするほうがトラブルが少なくていい

opkgの再インストールトラブル。

opkg の構成の復元は、saveを使う。

opkg list-installed でインストール済み一覧を作れるが、これをもとに作業すると、ミスを引き起こすので、opkg saveを使うこと。

適当に opkg list-installedの結果をcat list | xargs opkg re-installとかやると opkg がopkg 自体をアンインストして詰むので注意。

opkg で一部のパッケージはrestoreされないので手動でreinstallした。

opkg reinstall ip-full
opkg reinstall wget
opkg reinstall procps-ng-ps
opkg reinstall ddns-scripts luci-app-ddns   
opkg reinstall less

IPv6 NGNを使ってる場合

19.x から 21.x にアップグレードするとv6の機能が増えているので取り扱いには注意する。

ip -6 route 

のデフォルトルートが、構成が代わるので注意する。 busybox の ipip-full の ipで v6の表示が異なる。

また、DS-liteとか ip4ip6 をしているときは、NTTのGWまでの経路に注意すること。

参考資料

netplan でDHCP設定すると metric がぶっ壊れた件。

netplan でDHCP設定すると metric ばぶっ壊れる件

表題のとおりです。

問題点

RaspberryPi4の、eth0 と wlan0 が接続されたUbuntuシステムで、netplan を設定するとmetric がおかしい。

パケットがすべてWif( wlan 0 ) 経由になってしまう。

原因

eth0 と wlan0 なら、wlan0のほうが接続が遅く、同一DHCPから割り当てると、あとから来たほうが優先されている。

netplan に metric を設定しても無駄。

再現方法

netplan で wifi を接続する

network:
  version: 2
  renderer: networkd
  wifis:
    wlan0:
      dhcp6: false
      dhcp4: false
      addresses: [192.168.1.249/24]
      gateway4: 192.168.1.1
      dhcp4-overrides:
        route-metric: 200
      routes:
        - to: 192.168.1.0/24
          via: 192.168.1.1
          metric: 200
        - to: default
          via: 192.168.1.1
          metric: 200
      access-points:
        "takuya.mywif.local":
          password: "***********"

networkd で、eth0 を設定する。

[Match]
Name=macvlan0

[Network]
DHCP=no
Address=192.168.1.240/24
Gateway=192.168.1.1
DNS=192.168.1.1
DNS=192.168.1.5
LinkLocalAddressing=no

[Route]
Destination=192.168.1.0/24
Metric=1

結果

default via 192.168.1.1 dev eth0 proto static
default via 192.168.1.1 dev wlan0 proto dhcp src 192.168.2.249 metric 200
192.168.2.0/24 dev wlan0 proto kernel scope link src 192.168.1.249 ### ←おいおい、わたしmetricいれたよな
192.168.2.1 dev wlan0 proto dhcp scope link src 192.168.1.249 metric 200
192.168.2.0/24 dev eth0 proto kernel scope link src 192.168.1.240 
192.168.2.0/24 dev eth0 proto static metric 1

結論

netplan の metric はおかしい。

さらに、詳細に調べれば、原因が突き止められるかもしれないが、めんどくさいので netpaln すてて、 netowkrd + wpa_supplicant で Wifi 接続することにする。

netplan 怖いよ。renderer を network-managerに変えようかと思ったけど、もうしんどい。

経路が指定できないので、手動で ip route del / ip route add するのに疲れたのでもう諦める。

どっかで設定間違えたかなぁ。

個人的には、wlan0 とeth0 が共通サブネットとゲートウェイなら、eth0を優先してほしいんだけどなぁ

HTMLフォームのinputにイベントで文字列の値を突っ込む。スクレーパー用に使う。

課題:DOMを直接書き換えると反映されない

DOMでValueを書き換えても、反映されないJSのフレームワークが幾つかある。Angularとか。あのあたりをつかったログインフォームをかんたんに入力したい。

方法1 html のイベントをトリガーして文字列を突っ込む

最近は、domを直接書き換えないでJSでオブジェクトをObserveしていることが多いので、イベントを発火させて文字列を入力する。

inputElement = document.querySelector('input[name=nationalId]')
var event = new Event('input', {
    'bubbles': true,
    'cancelable': true
});

inputElement.value = '12345678'
inputElement.dispatchEvent(event);

めっちゃ単純ですね。通常通りDOMを書き換えたあとに、dispatchEvent で new Event('input') を発行してやるだけです。 これで、擬似的にフォームの入力をprogrammatically に試行できます。

方法2 execCommand

いにしえの手法 focus/ execCommand を使うともっと楽ちん。

document.querySelector('#tel001').focus()
document.execCommand('insertText', false, "090123456");

こちらは、focus したうえで、 execCommand を発行する。

focus したうえでイベントを発行するなら、他イベントも行けそうです。ただイベントを調べたりサポート状況が曖昧なので、execCommandという枯れた物を使います。

昔のやつ

https://takuya-1st.hatenablog.jp/entry/2014/11/12/162008

AngularJSのやつ

https://takuya-1st.hatenablog.jp/entry/2021/12/15/015820

Angular/AngularJSの場合は、スコープを取り出せば入力ができますが、フレームワークに特化すると後々が面倒そうなのでイベントを発火するほうが無難だと思う。

追記:パスワード自動入力ソフトの場合。

パスワード入力をするChrome のExtensionではどういう実装になっているのかというと、Bitwardenのソースコードを覗いてみました。

しつこくイベントを発行してました。

var event1 = el.ownerDocument.createEvent('HTMLEvents'),
                    event2 = el.ownerDocument.createEvent('HTMLEvents');
                el.dispatchEvent(doEventOnElement(el, 'keydown'));
                el.dispatchEvent(doEventOnElement(el, 'keypress'));
                el.dispatchEvent(doEventOnElement(el, 'keyup'));
                event2.initEvent('input', true, true);
                el.dispatchEvent(event2);
                event1.initEvent('change', true, true);
                el.dispatchEvent(event1);

https://github.com/bitwarden/browser/blob/master/src/content/autofill.js

ちなみに、bitwarden がこれだけイベント発火しても、一部のサイト(TP-Linkのルータログインページなど)では入力がうまくJS側に拾われないんですよねぇ。

AnguarJS のng モデルにchromeコンソールから入力する。

angular のモデルに変数を突っ込む

angular のモデルに直接値を突っ込んでもHTML要素の書き換えは反映されない。

ng-model を探す

angular を呼び出して。html element からスコープを取り出す。

var scope = angular.element(document.querySelector('input[name=nationalId]')).scope();

新生銀行での例

f:id:takuya_1st:20211215015549p:plain

modelをscope で探して apply する。

var scope = angular.element(document.querySelector('input[name=nationalId]')).scope();
scope.$apply(function() {
  scope.nationalId='123456789'
  scope.password='AAAAAAAAA'
});

これで、だいたい動く。angarJSなので、typescriptベースのangularでも動くかは試してないから、apply がどのバージョンまで動くかはわからない。

Angularの場合は、次で動くはず。

ng.probe($0)

document.forms[] や HTMLElementを使うところから比べるAngularは自己完結なのでちょっとめんどくさいですよね。

AngularJS/Angular に特化するより、DOMのInput系のイベントをファイアしたほうが楽だと思う。

今後、webasembly とか出てきたらスクレーパーはどんどん難しくなっていくだろうな辛い。