それマグで!

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

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

luksによるboot パーティションの暗号化

boot パーティションの暗号化

luks2 で ルートパーティションの暗号化ができる。

LUKSを使っても /boot が暗号化できずに残ってしまう。これを解決したい。

ただし、これをやってしまうと、grubでluks1を使うためにリモートアンロックはできない。そして問題がある。uEFIブートの場合、 /boot/efi は暗号化実施できずに残ってしまう。 それらをまとめて解決するにはTPMバイスの恩恵に預かるしかないと思う。

参考サイトの流れをすこしアレンジして実施した。

順番

いきなり、全部を一気にやるのは不可能なので、順番にやっていきます。

  • rootFSを暗号化
  • シリアルコンソールを使う。
  • rootFSをSSHでリモートアンロック
  • boot にroot鍵を設置
  • boot を暗号化
  • boot のリモートアンロック

rootfs の暗号化

rootfs を暗号化ディスクにする。

初回インストール時に、やってしまうのが楽だ。

どうしてもインストール後のシステムを移行したときは、次のような感じで・・・

cryptsetup luksFormat /dev/sdG
cruptsetup open /dev/sdG dm-0
ddrescue ddrescue /dev/sdA /dev/mappper/dm-0
mount /dev/mappper/dm-0  /mnt
mount ... # pts dev など
chroot /mnt
update-grub
update-initramfs

rootfs のリモートアンロック手段の確保

rootfs の暗号化の解除はdropbearによるSSH解除が手段がリモート経由のアンロックでとり得るベターな手段だと思う。万が一dropbearの設定に失敗を想定し、シリアルコンソールを使って解除する手段を作業時に確保していくと良い。

ssh によるリモートアンロック

以前やっている https://takuya-1st.hatenablog.jp/entry/2021/11/17/090809

シリアルコンソールを有効化

以前やっている。

https://takuya-1st.hatenablog.jp/entry/2020/01/30/013845

/etc/default/grub

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

有効化

sudo update-grub 

Raspiとつないで、シリアルコンソールをリモートから閲覧できることを確認する。

シリアルコンソールを使って総当りが可能なので、物理的にPCを強奪された場合に総当りでrootログイン試行されてしまう。作業が終わったらシリアル通信を無効にしておく。または、「一定回数の失敗でロックする」または、rootパスワードを無効化しておく。

SSHのリモートアンロック

SSHでLUKSをリモートからアンロックする。これも以前やっている。

https://takuya-1st.hatenablog.jp/entry/2021/11/17/090809

/boot に鍵を配置

rootfsの暗号化解除 initramfs で行う。initramfsが配置のは/boot。なので/bootに鍵を配置わけだ。 /boot が非暗号化だと、/bootに鍵が存在するため、ディスクを強奪・USBブートされると読み込みが可能になる。鍵の危殆化は免れない。

しかし、まずは、bootのinitramfs に鍵配置する。その後、bootを暗号化デバイスにする。

rootfsアンロック鍵を生成し登録

鍵を作成

mkdir -p -m0000 /etc/keys
umask 0777 && dd if=/dev/random of=/etc/keys/root.key bs=1024 count=4 conv=fsync

鍵を登録前に、登録状況を見る。

cryptsetup luksDump /dev/nvme0xp6

鍵を登録

cryptsetup luksAddKey /dev/mapper/my-root /etc/keys/root.key

keyslot に鍵が配置されたことを確認

cryptsetup luksDump /dev/nvme0xp6

crypttabに鍵を使うように登録

/etc/crypttab

dm_crypt-0 UUID=XXXX-XXXX /etc/keys/root.key discard,luks,keyslot=0

keyslot は0,1,2,3,4,5 の順に試されるので、0 番目に配置するほうが起動が早い。

initramfsに鍵を使うように登録

登録した鍵をinitramfsが使うように登録。

/etc/cryptsetup-initramfs/conf-hook

"KEYFILE_PATTERN=\"/etc/keys/*.key\"" >> /etc/cryptsetup-initramfs/conf-hook
# echo UMASK=0077 >> /etc/initramfs-tools/initramfs.conf

ここで、登録することで、initramfsを作成時にKEYFILE_PATTERNを見つけて、KEYFILE_PATTERNにマッチする鍵を収集する。収集した鍵がinitramfs生成時にフィアルに含めてくれる。

initramfs の生成

update-initramfs -u

生成されたinitamfsに鍵があることを確認

takuya:~$ sudo lsinitramfs /initrd.img | grep cryptroot
cryptroot
cryptroot/crypttab
cryptroot/keyfiles
cryptroot/keyfiles/dm_crypt-0.key

私の環境では、crypttab に記載したファイル名とDM名で鍵が登録されていた。

再起動する。

これで、再起動すると、initramfs に鍵が含まれるので、暗号化ディスクでも、そのままbootしてきます。

UEFI → /boot → cryptsetup → rootfs

boot に入れた鍵を使って rootfsは暗号化解除されます。そのため、パスフレーズを入力しなくても起動するってわけです。

このままだと、bootを見られると鍵を見つけられてしまいます。

boot を暗号化する。

boot のパーティションを暗号化します。

もし、bootパーティションを別パパーティションにしてない場合は、別パーティションを作ります。

/boot を暗号化する。

リードオンリーにしとく(トラブル回避)

mount -oremount,ro /boot
tar -C /boot --acls --xattrs --one-file-system -cf /tmp/boot.tar 

/boot が別パーティションになってない場合

パーティション作成(100Mくらいで十分です)

gdisk /dev/nvmeXXX

luks にする

cryptsetup luksFormat --type luks1 /dev/nvmeXXp3

フォーマット

mkfs.ext4 /dev/nvmeXXp3

blkid を確認

sudo bllid  /dev/nvmeXXp3

fstab に記載。

UUID=XXXX  /boot ext4 defaults,noatime,nodiratime,discard  0 2

mountして、bootの中身を移動

mount UUID=XXXX /mnt
rsync -av /boot /mnt
mv /boot /boot.old
mkdir /boot

/boot をマウントして確認

mount -a # fstabを反映
## 比較
md5sum /boot/*
md5sum /boot.old/*

アンマウント

sudo umount /mnt
sudo umount /boot/efi
sudo umount /boot

再マウント

mount UUID=XXXX /boot 

grub を更新

念の為

sudo update-grub
sudo update-initramfs -c -t -k all
## または
# sudo update-initramfs -u

起動する

起動すると grub メニューで、パスワードを訊かれる。

GRUB なので、sshリモートアンロックなどはできない。

ssh リモートアンロックは、initramfs のdropbearなのでできません。
シリアルコンソールには何も出力されなかった。grub だからできると思ったんですけどねぇ。

ブート時にVGAにコンソールが出るだけでした。grub のシリアルコンソールにプロンプトがなぜ出ないのかは今後調べる。

結論

boot パーティションの暗号化ロックは、とても安全になるが、リモートからアンロック手段が失わえます。なので、ノートPCなどでは良いが、常時起動したりリモートから使うことが多いデスクトップPCでは利用は難しいんではないかと思われる。bootに鍵を置くよりSSHリモートアンロックですね。

Linuxのデフォルトのタイマーがわかりにくい。cron/systemd.timerの優先関係

伝統的に、cron/atq によってタイマー・スケジュール実行は管理されています。

現代のLinuxでは、systemd.timer が追加されています。いまのLinuxでは両方が存在します。

両方が存在するために、タイマーの設定ファイルが systemd.timer / cron に同時に存在しています。

デフォルトのcron を見る。

takuya@:~$ ls  /etc/cron.*
/etc/cron.d:
anacron  certbot  e2scrub_all  php  popularity-contest

/etc/cron.daily:
0anacron  apt-compat       cracklib-runtime  exim4-base  man-db   popularity-contest
apache2   automysqlbackup  dpkg              logrotate   mlocate

/etc/cron.hourly:

/etc/cron.monthly:
0anacron

/etc/cron.weekly:
0anacron  man-db

デフォルトの systemd.timerを見る。

takuya@:~$ systemctl status *.timer | grep enabled
     Loaded: loaded (/lib/systemd/system/phpsessionclean.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/lib/systemd/system/anacron.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/lib/systemd/system/man-db.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/lib/systemd/system/apt-daily-upgrade.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/lib/systemd/system/apt-daily.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/lib/systemd/system/e2scrub_all.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/lib/systemd/system/exim4-base.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/lib/systemd/system/logrotate.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/lib/systemd/system/fwupd-refresh.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/lib/systemd/system/fstrim.timer; enabled; vendor preset: enabled)

思い切り、被ってないか?

2つを見比べると、少し気づいたことがあります。同じ名前の設定ファイルが存在します。anacron とか logroatateとか。

両方に設定が存在するもの

これらは、systemdにもcron にも登場します。つまり被ってます。

  • anacron
  • certbot
  • e2scrub
  • php/phpsessionclean
  • exim4-base
  • man-db
  • logrotate
  • popularity-contest

cron だけにあるもの

  • apt-compat
  • cracklib-runtime
  • apache2
  • automysqlbackup
  • dpkg
  • mlocate

systemd だけにあるもの

  • fstrim
  • fwup-refresh

被ってるものはどうなってるのか

被っていたら、正しくジョブが実行されないはずです。どうなってるのでしょうか。

anacron の例

よくこれで、重複実行されないよね。とおもったので調べました。

anacrom.timer の中身

[Unit]
Description=Trigger anacron every hour

[Timer]
OnCalendar=*-*-* 07..23:30
RandomizedDelaySec=5m
Persistent=true

[Install]
WantedBy=timers.target

timer 実体は anacron.service にありますね。 service/timer のペア運用を知らないと気づかないね、初見殺し。

takuya@:~$ cat /lib/systemd/system/anacron.service
[Unit]
Description=Run anacron jobs
After=time-sync.target
# By default, anacron will not run when no AC power is connected to system.
# If you are using systemd and want to run anacron even when running on
# battery, you should create the following file with the specified content
# and then call "systemctl daemon-reload":
#    /etc/systemd/system/anacron.service.d/on-ac.conf:
#        [Unit]
#        ConditionACPower=
# See /usr/share/doc/anacron/README.Debian for detailed information.
ConditionACPower=true
Documentation=man:anacron man:anacrontab

[Service]
EnvironmentFile=/etc/default/anacron
ExecStart=/usr/sbin/anacron -d -q $ANACRON_ARGS
IgnoreSIGPIPE=false
KillMode=mixed
# Use SIGUSR1 to stop gracefully
KillSignal=SIGUSR1

[Install]
WantedBy=multi-user.target

そしてこれが、cron.d

takuya@:~$ cat /etc/cron.d/anacron
# /etc/cron.d/anacron: crontab entries for the anacron package

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

30 7-23 * * *   root    [ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi

cron.d/anacron では /run/systemd/system のチェックし、cronは無視される。具体的には、systemd-initがpid=1環境であれば 、cron では実行スキップ

互換性重視のために、ファイルを残している。そのような意図が見えます。

動かないけど、cronは起動するよ

でも、これってcron 自体は実行起動しますよね。testコマンドだけで負荷もないから気にしないけど。

e2scrub の場合

systemdが存在したら実行するようです。

でもこれも、cron 自体は起動しますよね?負荷は気にはならないけど、実行されるという事実が気になる。

takuya@:~$ cat /etc/cron.d/e2scrub_all
30 3 * * 0 root test -e /run/systemd/system || SERVICE_MODE=1 /usr/lib/x86_64-linux-gnu/e2fsprogs/e2scrub_all_cron
10 3 * * * root test -e /run/systemd/system || SERVICE_MODE=1 /sbin/e2scrub_all -A -r

mlocate の場合

mlocate の場合は etc/cron.daily にあるので単純にスクリプトです。

cron の中身不要じゃね?

消したい・・・消したいけど、dist-upgrade時に /etc/の中身変わってるよと聞かれるのがうざい。

systemd timer より、cron.dailyは可読性がいい。

systemd timer でみるより、/etc/cron.daily/logrotate のほうが可読性が高く、何をしているのかよく分かる。

#!/bin/sh

# skip in favour of systemd timer
if [ -d /run/systemd/system ]; then
    exit 0
fi

# this cronjob persists removals (but not purges)
if [ ! -x /usr/sbin/logrotate ]; then
    exit 0
fi

/usr/sbin/logrotate /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
    /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit $EXITVALUE

mlocate は実行されないかも?

mlocate は、cron にだけ存在する。しかし、cron.daily/mlocateではsystemd側では動作しない。

mlocate は systemd では mask されている。

takuya@:~$ sudo systemctl status mlocate.service
● mlocate.service - Update a database for mlocate
     Loaded: loaded (/lib/systemd/system/mlocate.service; static)
     Active: inactive (dead)
       Docs: man:updatedb.mlocate(8)
             man:updatedb.conf(5)
takuya@:~$ sudo systemctl status mlocate.timer
● mlocate.timer
     Loaded: masked (Reason: Unit mlocate.timer is masked.)
     Active: inactive (dead)
    Trigger: n/a

しかし、cron.daily では mlocate は systemd環境下で何も実行しないよう構成されていました。

takuya@:~$ cat  /etc/cron.daily/mlocate
#! /bin/bash

set -e

# skip in favour of systemd timer
if [ -d /run/systemd/system ]; then
    exit 0
fi
# 中略
flock --nonblock /run/mlocate.daily.lock $NOCACHE $IONICE nice /usr/bin/updatedb.mlocate

cron記述では、systemdを優先する条件分岐があり、systemd.timerではマスクされる。これでは、何も実行されませんね。どうなってるのでしょうか。

タイマーは見直したほうがいい。

systemd信用できない。

Linux で eth0 を使わせる.( ethXなNIC名に戻す)

Linux で eth0 を使わせる

enp3s0 のような名前が不便だった。

SSDを載せ替えたり、ネットワークインタフェースを切り替えたりするとどうしても思ったようにならない。マイグレーション・サーバ移転で面倒が起きる。

もう、ネットワーク・インタフェースが1個〜2個に限られるようなサーバーは、eth0 で固定しちゃえばいいじゃないか。

サーバの構成を変更すると、netplan や network-manager が設定移行しなくて/ネットワークにつながらなくて焦る。なんでネットに繋がらない!!って焦ってよく見ると 「enp3s0enp3s1 に変わって設定エラー発生」。こんなことが頻発してもうキレた。

昔みたいにeth0 に固定したい。

起動時のカーネル引数で指定する。

/etc/default/grub

GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"

net.ifnames=0 biosdevname=0 が一意な名前を解除するカーネル引数である。

設定の反映

update-grub

カーネルのオプションなので強烈な設定だが、確実に動作するし誤作動もない。

その他の方法

systemdのマニュアルに書いてある

ln -s /dev/null /etc/systemd/network/99-default.link

これでlinkの名前をsystemdに変更を未然に防止できる。がカーネル引数が一番確実。

netplan の場合(注意が必要)

netplan に set-name があるので、これを使うと eth0 にすることができる。

network:
    version: 2
    ethernets:
        enp0s1:
            addresses:
            - 192.168.123.213/24
            gateway4: 0.0.0.0
            match:
                macaddress: 52:54:00:70:cd:5c
            set-name: eth0

ただし、永続化しない。設定ファイルを見て分かる通りenp0s1 を直接書いている。

なので当初目標である「マザーボードを交換しても設定がそのまま使える」という目的は全く達成されない。

ということでnetplan は全く使えない。

さらに、これは、networkd のlink設定を入れるのと同じなので役に立たない。systemdのマニュアルでは候補2と書いてあるが、全く無用の長物である。なぜなら、networkdで「名前がenps01」になったあとに「名前をeth0」に変更する。その変更設定を書くのである。永続化するわけがない。

さらにいえば、match が不可欠でmacaddress を指定して名前を変えるわけである。

これは、vpn などソフトウェア制御なNICのためにある機能であり、物理NICのためには使うべきではない機能だと思う。

2022-01-06 メモ

ubuntu の場合、netplan の設定に、直接eht0 と書いたら、自動的に eth0 が使われた。eth0を使っていてenp0s3 のような表記にしていない人たちへの互換性配慮のためだろうと思う。

逆手に取れば、 netplan の config.yml を eth0 で作っておけばそれで十分解決するわけである。

しかし、上にも書いたとおり、今後動かなくなる可能性が高い。そしてnetplanがない ubuntu以外はどうすればいいんだろうか。と考えるとカーネル引数が確実かもしれない。

他にも方法があるかもしれないので調べたい。

2022-01-10

systemdの公式サイトに記載があったので追記。

2022-02-16

match/macaddress について追記

参考資料

https://www.itzgeek.com/how-tos/linux/debian/change-default-network-name-ens33-to-old-eth0-on-debian-9.html

dpkg-reconfigureなどでダイアログ以外を選択して表示スタイルを変えたい。

dpkg の選択肢の表示を変えたい。

dpkg の選択肢の表示をダイアログじゃなく、単なるテキストの文字列入力でやりたい。

ncursesで作られてると思われるDialogは日本語で表示が乱れたり、tty設定が甘くて表示が崩れたり、シリアルコンソールでうまく行かなかったり。

表示は文字列だし、選択も文字列なんだから、単純に文字列を表示して、文字列をreadしてくれたらいいのにと思ってた。調べてみたら。簡単にできるじゃん。

dialog

ダイアログを選んでいると、選択をキーボードで入れることになる。

f:id:takuya_1st:20211123043445p:plain

readline

readlineを入れると、標準出入力で渡すことができる。

dpkg -f readline 

f:id:takuya_1st:20211123043458p:plain

nointeractive もいいけど。

readlineも使いやすいよ。

デザインが崩れるとき。

diaglog ( curses / ncurses ) とかでtty で「デザインが崩れる」ときは、 --frontend=readline / -f readlineで指定すれば、問題が解決しそうですね。

設定の確認

takuya@:~$ sudo debconf-show debconf
  debconf-apt-progress/title:
  debconf-apt-progress/info:
  debconf/frontend: Dialog
  debconf-apt-progress/media-change:
  debconf/priority: high
  debconf-apt-progress/preparing:

ちなみに、ダイアログの一覧は、 debconf-get-selectionsで見れる。

debconf-utils を入れないといけないが、手軽に、設定をもう一度呼び出すことができて便利である。

sudo apt install debconf-utils
takuya@:~$ debconf-get-selections | grep -v ^# | cut -f 2 | cut -d / -f 1 | sort | uniq
debconf: DbDriver "passwords" warning: could not open /var/cache/debconf/passwords.dat: Permission denied
adduser
apparmor
apt-listchanges
base-passwd
ca-certificates
certbot
console-setup
cpufrequtils
cryptsetup
cryptsetup-initramfs
dash
debconf
debian-installer
dictionaries-common
discover
exim4
exim4-base
exim4-daemon-light
fontconfig
gdm3
glibc
grub2
iproute2
keyboard-configuration
libpam-modules
libpam-runtime
libpam0g
libpaper
libraries
libssl1.1
libvirt-daemon-system
lightdm
linux-base
locales
make-ssl-cert
man-db
mariadb-server-10.5
mdadm
netselect
nginx
openssh-server
passwd
popularity-contest
s-nail
samba-common
sane-utils
shared
shim
tasksel
tzdata
ucf
unattended-upgrades
update-inetd
xserver-xorg-legacy

2022-01-17

ダイアログの設定の選択をがあるものをリストする方法を追加。

参考資料

https://askubuntu.com/questions/667493/change-of-graphical-text-interface-to-completly-text-interface#:~:text=From%20man%20dpkg-reconfigure%3A%20-ftype%2C%20--frontend%3Dtype%20Select%20the%20frontend,so%20you%20actually%20get%20to%20reconfigure%20the%20package.

https://tokyodebian-team.pages.debian.net/html2005/debianmeetingresume2005-fuyuse2.html

rootFSにluks + LVM を用いたときのfstrim

fstrim / discard できない

luks + lvm で構成された root ファイルシステムは、fstrim ができない

$ sudo fstrim -v / 
Operation not permitted.

対策。

discardオプションを使って dmsetup する。

設定 /etc/crypttab

ubuntu_dm_crypt-0 UUID=4aa....  none  discard,luks

設定2 lvm.conf

issue_discards=1

設定3 /etc/fstab

UUID=XXX-XXX/ ext4 defaults,discard 0 0

fstab に discard を書くと、fstrim しなくても rm 実行時に fsrtrim が走る。rm が遅くなる諸刃の剣。

設定2,3について

LUKS しているなら、 crypttab は必須。

lvm.conf のissue_discardは、fstabをdiscardが優先される。 fstabにdiscardを書いていたらlvm.conf記載がなくてもfstrim できる。

個人的には、 fstab でいいと思う。discardでマウントしても、nvmeのディスクのrm速度は気にならない。

参考資料

apt installed automatice のなぜ(Why)をしり、どこからインストールされたかをたどる。

apt installed automatice のなぜ(Why)をしり、どこからインストールされたかをたどる。依存関係

どこでイントールされたんだお前は。

インストール済み/自動installed / automatic って出てくるけど、どこからインストールされたのか知りたい。

apt-chache を使います。

apt-cache --installed rdepends パッケージ名

"apt-cache --installed rdepends XXX" のXXX部分に検索したいものを入れると、XXXに依存するYYYが見られる。installed をつけることで、「どいつがインストールしたのかを見ることができる。

takuya@:~$ apt-cache --installed rdepends bsd-mailx
bsd-mailx
Reverse Depends:
  unattended-upgrades
 |logrotate
 |automysqlbackup

rdepends という、キーワードがポイント。

Google検索ではrdpendsを検索しても出てこない。 rdepends は 'depends'のミス・スペリングだと、怒られて検索結果を丸められちゃうので、"rdepends"は全くGoogleで検索できない。Googleひどい

古えの技術

むかしは、依存関係を知るなら、aptitutde がwhy が便利だった。名前の通り why を調べられた。

aptuide why bsd-mailx

aptitude は最近使われない。apt に切り替わったけど、whyやrdepends がなくて困りますね。

apt にはなかった

man apt で調べたけどなかった

2022-01-09

rdepends では、Google検索でインデックスされてないことに気づいた。まじでどうなってんだろう。

キーワードを散りばめないと検索されない。

たとえば、ソースコードの引用部分は絶対に検索されない。

参考資料

さくっとメールを送るコマンド mailx(s-nail/bsd-mailx)

コマンドからサクッとメールを送信する。

コマンドからサクッとメールを送信して、送信テストをしたい。

コマンドには幾つか候補がある。

  • mailx がある。
  • s-nail がある。
  • mailutilsがある。
  • curl がある。
  • swaks がある。

これらを自由に選んで、メール送信をテストすることができる。

mailxは最初からインストールされているので手軽に試せる。

互換性がある。

mailx と s-nail は互換性がある。

mailx は外部のSMTPなどに非対応(未対応ではなく非対応)

MTA(外部サーバ・ポート)を指定する場合はs-nailを使う

mailx の場合

mailx は linuxでは bsd-mailx で存在する。

## 通常はインストール済みで、apt は不要
# sudo apt install bsd-mailx

mailxでメール送信

echo hi | mailx root
echo hi | mailx takuya

mailx を使うと、sendmail 経由で楽にメールを送れる。

bsd-mailx は初期導入済み

そもそも、私の環境に、なぜbsd-mailx は入っていたのか。

$ apt-cache --installed rdepends bsd-mailx
bsd-mailx
Reverse Depends:
  unattended-upgrades
 |logrotate
 |automysqlbackup 

logrotate と一緒に入っている。

logrotate で使われるので、初期インストールで、インストール済みであるはず。

mailx の実体。

mailxコマンドは、Aliasになっていて、初期設定の場合は bsd-mailxを指している。

takuya@:~$ ll /usr/bin/mailx
lrwxrwxrwx 1 root root 23 11月 18 16:53 /usr/bin/mailx -> /etc/alternatives/mailx

管理しているのは alternatives

takuya@:~$ sudo update-alternatives --config mailx
リンクグループ mailx に 1 つの alternative のみがあります (/usr/bin/mailx が提供): /usr/bin/bsd-mailx
設定は行いません。

smtp を指定するならs-nail

s-nailを使えば、SMTPサーバーを指定することができる。ポート番号やSMTP-AUTHを使える。メールの送信のチェックなら s-nailがmailxより高機能で使いやすい

sudo apt install s-nail 

s-nail で送信。

echo hi | s-nail root
echo hi | s-nail takuya

s-nail でSMTP経由でメールを送る

コマンドでSMTP経由でメール配送できる。

echo Hi success? | s-nail  \
   -S mta=smtp://localhost:25255 \
   -S smtp-auth=none  \
  -S v15-compat=yes \
   takuya@example.com

-S でオプションを指定できる。

s-nail はmailx互換性あるみたい

使い方を見ればわかるが、mailxと互換性がありそう。

しかし、alternativesには出てこない。

alternatives に登録する

mailxとs-nail はほぼ同じだし、alternativesでmailxは管理されている。

しかし、s-nail は apt インストールしても mailx にはならない。(公式パッケージのバグじゃないの)。仕方ないので手作業で登録する。

参考資料に従って、alternatives を構成する。

s-nail をmailxに追加

sudo update-alternatives \
  --install /usr/bin/mailx mailx  /usr/bin/s-nail 10 \
  --slave  /usr/bin/mail mail /usr/bin/s-nail \
  --slave  /usr/share/man/man1/mail.1.gz mail.1.gz /usr/share/man/man1/s-nail.1.gz \
  --slave  /usr/share/man/man1/mailx.1.gz  mailx.1.gz /usr/share/man/man1/s-nail.1.gz \

s-nail をmailxに設定

設定

sudo update-alternatives --set mailx  /usr/bin/s-nail

不要になったとき削除する場合はこれ

sudo update-alternatives --remove mailx /usr/bin/s-nail

mailxとしてsnail を使う。

s-nail を mailxとして登録したのであとは同じ。

echo Hi | mailx takuya

正しく追加するのは・・・・大変ですね。

その他の方法

curlでSMTPが何処でも使えるので便利だと思う。

mail.utils はmailxと互換性がありそうでないので、しらべなかった。

2022-01-10 追加

mailxで検索にマッチしないので記述見直し。

参考資料

exim4 でsmart relay ホスト利用中にユーザーへのローカル配送メールを外部メールアドレスへ

Exim4 でユーザ宛のメールを外部サーバへ

root 宛のメールを、指定のメールアドレスへ送信する

仕組み

ローカル配送をしないので、ローカル配送宛のメールを指定のメールアドレスへ送信する。

root@mail --> sendmail --> exim4 --> smartrelay --> gmail 

設定

スマートリレーを設定する。

sudo dpkg-reconfigure exim4-config

このとき、mailname(ホスト名)の解決が行われるので注意する。

設定 mail alias を設定する。

/etc/aliases

# /etc/aliases
mailer-daemon: postmaster
postmaster: root
nobody: root
hostmaster: root
usenet: root
news: root
webmaster: root
www: root
ftp: root
abuse: root
noc: root
security: root
root: takuya
takuya: takuya+exim4@example.com

ローカル配送のroot 宛は、takuya 宛とする。 takuya 宛は、メールアドレスへ送信する

設定の確認

送信テスト

echo Hi success? | mailx -v takuya

mailx コマンドは snail に指定してあるので、ログが出てきて便利。

送信ログ

mailxからexim4 経由でメールをちゃんと送って、ログを見ながら接続を確認すれば確実

f:id:takuya_1st:20220110044334p:plain

参考資料

https://mirahouse.jp/n10/blog/2015/debian-exim4/

ディスク(hdd/ssd)のブロックデバイスのUUIDを知る

いつも忘れるので再度纏め直し。

UUID は他とかぶることのないユニークIDである。

指定したブロックデバイスのUUIDを知る。

blkid =ブロックデバイスのID

sudo blkid /dev/sda

すべてのUUIDを表示する

sudo blkid

lsblk で一緒に表示する

lsblk -f 

/dev ファイルシステムから知る。

ls -l  /dev/disk/by-uuid/

UUIDでマウントする

mount UUID=XXXXX-XXXXX /mnt

fstab に書く

UUID="XXXX-XXXX" /mnt      auto  noatime,nodiratime,nofail,nosuid,nodev,nofail,x-gvfs-show    0 1

ファイルシステムをチェックする

sudo fsck UUID=xxxx-xxxxx

UUIDだけを得る

blkid -o value -s UUID /dev/sda1

UUIDを変数に入れる

UUID=$(blkid -o value -s UUID /dev/sda1  )

フォーマット時にuuid を指定する。

自動生成するとUUIDが毎回変わってしまう、特に問題がなければ固定してしまってもいいだろう。

mkfs.ext4 -U $uuid /dev/sda1 

FAT32のUUIDは短い

ファイルシステムによってUUIDに複雑性が違いがある。とくにfatは短いので時々ビビる。

takuya@:~$ lsblk -f /dev/nvme0n1p2
NAME      FSTYPE FSVER LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINT
nvme0n1p2 vfat   FAT16       56CD-08C9
takuya@host:~$ sudo fsck UUID=56CD-08C9
fsck from util-linux 2.36.1
fsck.fat 4.2 (2021-01-31)
/dev/nvme0n1p2: 8 files, 870/51145 clusters

UUIDは普段使わないので忘れる

UUIDはfstabに一旦設定しまうと、1年近く使うことがないので、ついつい忘れがち。HDD/SSDが直接UUIDを持つわけではなく、ファイルシステムがUUIDを持つ。

過去記事

dm-crypt のリモートアンロック(SSHでLUKSアンロック)

dm-crypt したシステムルートをリモートSSHから解除

luks の鍵をtpmに入れたいけど、TPMバイスがないPCの場合、鍵をUSBで差し込むか、SSHでリモートからアンロックをするといい

仕組み

luks のルートパーティションがinitramfs に読み出されるときに、dorpbearでsshサーバーで、パスフレーズ入力を待ち受ける。

準備

参考サイト1,参考サイト2,参考サイト3に従って処理。

## debian 11
apt install -y dropbear busybox
## debian 10
apt install dropbear-initramfstools

起動時のIP割当

起動時に initramfs が起動する。initramfs がIPアドレス持つように grub を変更する

dhcp で割り当てる場合

GRUB_CMDLINE_LINUX="ip=:::::eth0:dhcp"

固定IPの場合(おすすめ)

GRUB_CMDLINE_LINUX="ip=10.1.1.5::10.1.1.1:255.255.255.0:my-name:eth0:none"

並びは、次のようになってる(DNSのところは自信がない。)

GRUB_CMDLINE_LINUX="ip=ADDR:BRD:GW:NETMASK:hostname:eth0:none"

eth0 を使わせる設定 を利用して固定することにした。

GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"

出来上がった設定はだいぶ長い・・・

GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 ip=10.1.1.5::10.1.1.1:255.255.255.0:my-server:eth0:none"

eth0 を使わない場合は、enoXXや enpXX を使う

GRUB_CMDLINE_LINUX="ip=10.1.1.5::10.1.1.1:255.255.255.0:10.1.1.53:enp0ns11:none"

公開鍵の追加

initramfsのdropbearへSSHするには公開鍵ログインが必須です。

パスフレーズだと、/bootなどを総当りされる恐れがあります。

公開鍵を登録する

公開鍵の設置先。

/etc/dropbear-initramfs/authorized_keys

既存の公開鍵を設置すればおっけ。

sudo cp /root/.ssh/authorized_keys /etc/dropbear-initramfs/authorized_keys

drobear設定は、/etc/dropbear にもあるが、ここは使わない。 /etc/dropbear-initramfs/に、authorized_keys を置くのが正しい。

update-initramfs -u
update-grub

update-initramfs で firmware 関連のエラーが出るとき

ただし、non-free なfirmware を入れると起動時にめっちゃエラー出る。

W: Possible missing firmware /lib/firmware/i915/skl_huc_2.0.0.bin for module i915
W: Possible missing firmware /lib/firmware/i915/skl_guc_33.0.0.bin for module i915

main contrib nonfree に変えるファームウェアのエラーは消せる。

sudo sed -i  's/ main$/ main contrib non-free/' /etc/apt/sources.list
sudo apt update
sudo apt list firmware*
sudo apt install firmware-linux

シリアルも有効にしておく。

grub に設定を書いて、シリアルのコンソールでも待ち受けておく。(予備手段)

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

リモートで作業することも考えて、シリアルを有効にしておく。

リモート時に障害時対応ができると思う。

シリアルの接続先に、Raspiなどをつないでおく。そうすれば、RaspiにSSHしてログインし、serial console でメンテできます。 raspi zero とかのRS232CのGPIOとか使えばコストも安く上がる。

ホスト鍵を揃えてやる/fingerprint不一致対策

grub で指定するIPアドレスを同じにすると、initramfs(dropbear)と 起動後のdebian(opensshd) でホスト鍵が異なって警告が鬱陶しい。そこでホスト鍵を揃えておく

ホスト鍵の揃え方に従って処理をする。

変換対象の鍵

root@borane:/home/takuya# ls -l  /etc/ssh/ssh_host_* | grep -v pub
-rw------- 1 root root  505 1114 16:51 /etc/ssh/ssh_host_ecdsa_key
-rw------- 1 root root  399 1114 16:51 /etc/ssh/ssh_host_ed25519_key
-rw------- 1 root root 2590 1114 16:51 /etc/ssh/ssh_host_rsa_key

ssh_host_ecdsa_key を変換する。

## 作業ファイルにコピー
cp /etc/ssh/ssh_host_ecdsa_key /tmp
## PEM 形式に変換
ssh-keygen -p -m PEM -f /tmp/ssh_host_ecdsa_key
## dropbear用に変換
sudo dropbearconvert openssh dropbear \
 /tmp/ssh_host_ecdsa_key \
 /etc/dropbear-initramfs/dropbear_ecdsa_host_key

これを繰り返す

for name in ecdsa ed25519 rsa;  do 
    cp /etc/ssh/ssh_host_$name_key /tmp;
    ssh-keygen -p -m PEM -f /tmp/ssh_host_$name_key
    dropbearconvert openssh dropbear/tmp/ssh_host_$name_key /etc/dropbear-initramfs/dropbear_$name_key
done;

initramfs の再生成 / grub 再生性

sudo update-initramfs -c -t -k all
## または
# sudo update-initramfs -u
sudo update-grub

これでおっけ。

起動CHECK

起動したらSSHでログインする。

ssh -vvv -i ~/.ssh/id_rsa root@192.168.2.5

参考資料

dm-crypt でマッピングされてるブロックデバイスの名前の変更

dm-crypt で luks のデバイス名を変更

バイス名を変更したい。

cryptsetup luksでopen されてるデバイス名のデフォルト設定を変えたい。

dm-crypt でマッピングされてるブロックデバイスの名前の変更ができればいいなと。 調べたら変更できるとわかった。

暗号化デバイスの名前の変更

 sudo dmsetup rename nvme0n1p4-dm dm_crypt-0

dmsetup コマンドを使えば、できるとわかった。

やってみた。

takuya@server:~$ lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
nvme0n1         259:0    0 476.9G  0 disk
└─nvme0n1p4     259:4    0 476.5G  0 part
  └─nvme0n1p4-dm          254:1    0 476.5G  0 crypt
    ├─server-root 254:2    0  93.1G  0 lvm   /
    ├─server-home 254:3    0  55.9G  0 lvm   /home
    └─server-swap 254:4    0   9.3G  0 lvm   [SWAP]

takuya@server:~$ sudo dmsetup rename dm dm_crypt-0
takuya@server:~$ lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
nvme0n1         259:0    0 476.9G  0 disk
└─nvme0n1p4     259:4    0 476.5G  0 part
  └─dm_crypt-0  254:1    0 476.5G  0 crypt
    ├─server-root 254:2    0  93.1G  0 lvm   /
    ├─server-home 254:3    0  55.9G  0 lvm   /home
    └─server-swap 254:4    0   9.3G  0 lvm   [SWAP]
takuya@server:~$

なんでこんな事するの?

えっとね、Debian/Ubuntuのインストール時に自動的に決まるdm名に nvme01と入っててものすごく可搬性が悪そうだから。変えておきたかった。

変更後には、update grub/ initramfs

自動でupdate されるが、念の為に、手動で再度実行してもいいかと

update-initramfs -c -t -k all
# または
# update-initramfs -u

grub更新

update-grub

参考

https://unix.stackexchange.com/questions/81011/how-to-change-the-name-an-encrypted-full-system-partition-is-mapped-to

システムが uEFIで起動しているか見る

EFIで起動しているかチェックする

EFI起動して無いと、update-initramfsupdate-grubEFIが使えない、使われないので、ブートを修正するとき、最初にEFIで鬼道しているか、ちゃんと確認する。

マウント見てみ良いんじゃない?

takuya@:~$ mount | grep efi
efivarfs on /sys/firmware/efi/efivars type efivarfs (rw,nosuid,nodev,noexec,relatime)
/dev/nvme0n1p2 on /boot/efi type vfat (rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro)

efibootmgr が動くかどうか

takuya@:~$ efibootmgr
BootCurrent: 0002
Timeout: 1 seconds
BootOrder: 0002,0004,0006,0005,0000,0001
Boot0000* Windows Boot Manager
Boot0001* ubuntu
Boot0002* debian
Boot0004* ハードドライブ
Boot0005  debian
Boot0006* リムーバブルドライブ

参考資料

bashで入力しやすく見やすいパスワードをサクッと作る(シェルコマンドでハイフン区切りのパスワード生成)

シェルコマンドだけで、覚えやすいパスワードを作りたい

iOS のパスワードジェネレーションみたいな、ハイフン区切りのパスワードをサクッと作りたい。

pwgen を入れるとはやい。

sudo apt install pwgen 

pwgenのパスワードをハイフン区切りにする

takuya@$ pwgen  5 4  | xargs echo  | sed 's/ /-/g'
euD1i-Aloh3-uN9ai-nahZ7

曖昧な文字を排除する。

pwgen -s -B -n 5 5 |xargs echo | sed 's/ /-/g'
Mv3tW-m9Pnc-iMr3u-pyJ3C-7TciV

openssl を使う。

pwgen がないときは openssl で

for i in {1..4}; do openssl rand -hex 4; done  | xargs echo  | sed 's/ /-/g'

openssl hex の場合文字種がA-Fに限定される。

openssl でbase64 を使う

openssl でランダム文字列な文字列を作る。

for i in {1..4}; do openssl rand -base64 6; done  | xargs echo  | sed 's/ /-/g'

BASE64の場合読みにくい文字種と+記号が混じるのでちょっと使いにくい。

個人的には、base58 くらいが使いやすいと思うけど。

base58を使う場合

base58は曖昧な文字を省いてくれるし記号もないので。人間が見て判別するパスワード向きです。

sudo apt install base58

コレを組み合わせる。

for i in {1..4}; do echo $(openssl rand 4 | base58) ; done  | xargs echo  | sed 's/ /-/g'

2022-01-08

追記更新

dockerのコンテナにホストssh経由で接続する

リモートのdocker のコンテナへSSHで接続する

作業マシンは、macOS/Windowsで、docker はリモートのUbuntu Serverの中。なんてことが多いと思います。

次のような接続。

PC ---<internet>---UbuntuServer--<dockerio>---container

直接 container に入りたくないですか?

ssh でやると2回の処理に別れます。

$ ssh ubuntu-server
takuya@ubuntu # docker -it exec myContainer bash 

一回で済ませたくないですか?

ssh myContainer

ssh -t でできます。

それTTYをアロケーションすればできます。

ssh -t ubuntu-server 'docker exec -it myContainer bash '

設定で更に省略

Host myContainer
  Hostname ubuntu-server
  RequestTTY force
  RemoteCommand docker exec -it e339fc9cfb25 bash

すっきり!

ssh myContainer

たまに、docker コンテナに openssh入れようとしてる人いる。 けど、殆どの場合必要ないからね。無駄な努力とCPU浪費してQiitaにエントリ書いて、DockerfileビルドしてSSD寿命縮めて、何してんだろうなぁ。もっとエコに生きようぜ。怠惰はプログラマの美徳だよ。

参考

追記

sshしなくてもdocker_host環境設定すれば、直接TCP経由でリモートのdockerに接続もできます。こっちの方がむしろ便利じゃないかな。 docker別ホストから接続、管理SockをTCP経由許可して利用する。 - それマグで!

sshで踏み台(ゲートウェイ)経由での接続のショートカットを作る

SSHのconfig で踏み台ショートカットをつくる

  • ssh を経由して sshする
  • ssh 経由して docker exec する
  • ssh経由して lxc shell する
  • ssh 経由して virsh consoleする

リモートの仮想マシンやdocker や lxc までなんでも簡単に ssh できちゃいます。

SSHの踏み台経由でsshする

SSHで、ゲートウェイSSHログインしてから、内部のPCにログインする。

書き方

ssh -t 踏み台サーバー " ssh アクセス先サーバー"

ssh -t gw.example.com "ssh 192.168.2.100 "

ssh -t-tssh -o 'RequestTty force' の省略形で、tty の割当を矯正するものです。

ssh 設定にする

毎回記入するのが面倒で、ssh_config の設定にする場合はこうする。

host 好きな名前
  Hostname 踏み台の先のIP
  ProxyCommand ssh 踏み台のIP -W %h:%p

設定例

先程の接続例

ssh -t gw.example.com "ssh 192.168.2.100 "

先程の接続例をconfig にする例

host s1-gitlab
  Hostname 192.168.2.100
  ProxyCommand ssh gw.example.com -W %h:%p

上記 config を使う例

ssh s1-gitlab

踏み台のホスト名を「別名にする」

踏み台のIPやホスト名を書いていると、変更に弱くなる。踏み台の「名前」も設定にする。

ssh -t humidai "ssh 192.168.2.100 "

上記の設定例。

host humidai
  Hostname gw.example.com
host s1-gitlab
  Hostname 192.168.2.100
  ProxyCommand ssh fumidai -W %h:%p

これを応用すると、「踏み台」を「踏み台」にして多段で入れる。

踏み台経由でdocker

踏み台でdocker のコンテナに直接に入れます。

ssh 192.168.2.240  -t 'docker exec -it e339fc9cfb25 bash'
## または
ssh 192.168.2.240  -o 'RequestTTY true' 'docker exec -it e339fc9cfb25 bash'

上記コマンドのssh_config 設定例。

Host sample
  Hostname 192.168.2.240
  RequestTTY force
  RemoteCommand docker exec -it e339fc9cfb25 bash

踏み台経由でのLXC

LXCも同様にして、コンテナに直接入れます。

ssh lxc-host -t' lxc shell lxc-container-01'
## または
ssh lxc-host -o 'RequestTty force' ' lxc shell lxc-container-01'

上記コマンドのconfig例

  Host lxc-container01
    Hostname lxc-host
    RequestTTY force
    RemoteCommand lxc shell lxc-container-01 

踏み台経由の virt-machine

virsh でkvm+qemu仮想マシン へ接続するのもこれでいける。

ssh 192.168.2.240 -t 'sudo virsh console 28'

virsh の場合は、sudo つけないと動かないかも。

おまけ windows標準のopenssh-server でwslを直接呼び出す。

Windowsの標準搭載のopenssh-sever だと cmd.exeになってしまうので、wsl や ps を直接呼び出す。

ssh win10pro -t 'wsl'
ssh win10pro -t 'powershell'

結構なんでもできるよ。

関連資料