サービス選定〜OSのインストール | |
サーバー類のインストール | |
nginx | |
>>> | さくら de Ubuntu |
サーバーの引越 | |
バックアップ | |
Let's Encrypt |
28 Sep 2020 |
システムが使うMUA
でbsd-mailx インストール時にpostfix がインストールされないようにする方法をequivs を使用したものに変更。
|
06 Nov 2018 | qmail-smtpd に対するfail2ban の設定を追加。
誤記の修正。
|
27 Oct 2018 | 新規作成。 |
やっとこさサーバーのリプレースに手を出し始めました。 インストール手順の覚え書きページです。 必要な設定がgitのリポジトリに全部突っ込んであるので、このページ見ただけでは色々意味不明だと思います。 サーバーはさくらインターネットのVPS、石狩リージョン。 契約直後に北海道の胆振地方で地震があって、さくらインターネットから電力確保に関するお知らせが来ていました。 ずっと普通に使えていたのでメールが来るまで実体が北海道にあるってすっかり忘れてました。
さくらの印象ですが、コントロールパネルに2段階認証が付いていたりと、さすがに充実してる印象。 ゴルゴ13でも出てきますが、サーバーのセキュリティを強化していくと、最終的に一番脆弱なのはコンソールになるのは今も昔も同じで。 契約は512プランなのでSSDで20GBしかありません。 メインサーバー(Ablenet)のバックアップは手元のHDDかなぁ。 代打とかつなぎの感は否めない。 Ablenet(50GB)の方はホームディレクトリを別パーティションにしてあるので、原理的にはバックアップせずにリプレースできるんですけどね。 転ばぬ先の杖。
OSがOpenSUSEからUbuntuに変わるので、HDDのパーティション丸ごと再利用だとユーザーIDの整合性に気をつけないといけないから、tar
してtar
し返す方が何も考えなくて楽といえば楽。
NFSとかsshfsならこの辺りはどうにでもなるんだけど。
Ubuntuサーバーの印象ですが、「余計なものが何にも入ってない」感じでした。
非常に素直なシステム。
Apacheの設定ファイルはinclude多すぎて辟易したけど。
OpenSUSEがいい感じに色々入っていた反面、SuSE Firewall2とか調べないといけないことも多かったので。
Ubuntuサーバーは逆で、余計なことを覚えなくてもいい反面、何も入ってないです。
netstat
が入ってないことに気づいたときはちょっとびっくりした。
単にさくらのインストールメディアがそうなってるだけかもしれませんが。
もっとも、最近はifconfig
→ip
、netstat
→ss
という流れらしいので、そっち使え、ということなのかもしれない。
少し解説しておくと、うちのサーバーの設定は全部/usr/local/etc
に集中させてあります。
ディストリ側は例えばnginxだったら/etc/nginx
に設定があったりしますが、ファイルの本体は/usr/local/etc/nginx/nginx.conf
とかに置いて、/etc/nginx
からシンボリックリンクを張るようにしています。
こうすると、/usr/local/etc
だけバックアップしておけばぶっ飛んだときも楽に復旧できます。
さらに、バージョン管理システムで管理しておくと、何かあったときに元に戻せて便利です。 この用途にはやっぱりgitが向いてるなぁ。 サーバーやOSを変えるときは、元のサーバーからcloneしてブランチ切っちゃえばいいのです。 そのままpushしておけばバックアップにもなるという。
ただ、clone直後のパーミッションはroot:root
644/755になるので、qmailとか変態な所有者設定を要求するものは調整が必要です。
よくalias
で引っかかる。
とりあえず、newgrp wheel; umask 007
とかにして調整していくというのもありかもしれない。
あぁそうそう、wheel
はUbuntuにはないので注意。
私はシステム入れるとネットワークとsshの設定をとりあえずやって、次に古いシステムと新しいシステムのuser/groupをマージする作業をするので、この時点でwheel
ができあがるのですが。
FreeBSD時代からずっと持ってきてます。
再インストールする場合で、同じ鍵を使いたい場合は一度引き上げておく。 インストールの段階で鍵が再生成されると、他の端末からつなぎに行くときに初回の指紋確認ダイアログが出て面倒
Install
」にカーソルがあるのを確認してEnter
Japanese
」を選ぶ
Japanese
」を選ぶ
ファーストネームを全部小文字にしたものが最初のユーザー名になるらしい。
Ubuntuはroot
にパスワードが設定されれず(ログインできない)、ここで設定したユーザーがsudoerとして設定されるので、このユーザーとパスワードでログインして、sudo
で各種作業を行う形になる。
sda2 | 15GB | / |
sda3 | 5GB | /var |
sda6 | 残り全部 | /queue |
パーティションは/swapfiles
として作成されるけど、これはあとで/var
に移す。
HDDが20GBのプランで、表示上は21.5GBになるのでqueue
は約1.5GB。
あとでdf
してみると、ここの表示は1GB=109らしい。
Yes
」選択
ここだけカーソルを動かす必要があるので注意。
Continue
」
この時点でIPアドレスやDNSなど、ネットワークの基本的な設定は終わっています。
が、他からここへssh
すると再生成された鍵が使われてしまうから、それはやりたくない。
このため、エージェントフォワードが使えず、うちの場合は他のホストはすべてパスワード認証不可にしてあるのでログインができない。
つまり、ファイル転送にSSHは使えない。
仕方ないのでopenssl
とかで暗号化してコソーリWebサイトに置いてwget
してしまった。
SSLなら最高なんだろうけど。
openssl
で暗号化する場合はこんな感じ。
$ openssl enc -aes-256-cbc -md sha256 < ssh-keys.tar.gz > ssh-keys.tar.gz.enc
-md
はなくてもまぁいいんだけど、古いOpenSSLではデフォルトのハッシュがMD5で、新しいのはSHA256なので、これが合わないと復号できない。
付けておいた方が無難。
復号するときは-d
オプションを付ける。
ちなみにOpenSSLの暗号化・復号コマンドのマニュアルはman enc
。
大きく出すぎだろ。
無事展開できたら/etc/ssh
にコピーする。
戻すのは鍵だけにして、他の設定はdiff
を取って確認しつつがいいかな。
known_hosts
のハッシュをどうするか決める
このあとssh
するとknown_hosts
ファイルが生成されるが、ハッシュするかどうかをここで決めておく。
設定は/etc/ssh/ssh_config
(クライアント側の設定ファイル)、HashKnownHosts
をyes
かno
に設定しておく。
ssh
鍵の確認を求められるはずなので、一度終わって、確認のときに求められた鍵の指紋を確認してもう一度つなぐ。 例えば、ECDSAの指紋を確認されたら:
$ ssh-keygen -f /etc/ssh/ssh_host_ecdsa_key.pub
これで.ssh
ディレクトリができる。
ssh
保存していた鍵を復帰した場合は指紋の確認はないはず。
新規の鍵の場合は指紋の確認がある。
その場合はVNCコンソールでssh-keygen
を実行して指紋を確認する。
-E md5
を付ける
ssh
でログインしようとしたホストでSHA256のハッシュを表示できない場合は、ssh
側で-o FingerprintHash=md5
を付ける
.ssh/authorized_keys
に公開鍵を書き込んでおく
VNCコンソールではなく、普通のSSHクライアントなので、コピペができるのがミソ。
ssh
して、公開鍵認証でログインできるか確認する
ここまで来たらVNCコンソールはいらない。
以下のようになっていることを確認。
PermitRootLogin
→ no
PasswordAuthentication
→ no
ChallengeResponseAuthentication
→ no
なっていなければ修正。
修正したらsudo systemctl reload ssh
。
エージェントなしでログインできないことを確認する。
自分に2回ssh
するのが多分簡単(最初のssh
でエージェントが無効になり、2回目のssh
ではキーがなくてログインできない)。
ssh
エージェントフォワードが有効になっていれば指紋の確認だけ。
古いホストからの移行の場合、古いホストにあるユーザーとグループが新しいホストに存在していないと、tar
とかでファイルを持ってきたときに面倒なことになるので、なるべく早い時点でユーザーとグループをマージしておく必要がある。
実は一番最初にリプレース作業をやった(Linux → FreeBSDだったと思う)ときにハマった。
遠い昔の、若い頃の話(遠い目)。
手作業でやると結構面倒だが、実はそのための簡単なツールが作ってあって、それでマージしている。 気が向いたらそのうちGitHubとかで公開するかも。 このツールを作ったときはスクリプト言語をほとんど知らなかったのでC++で書いている。 が、連想配列が使えるスクリプト言語で書いた方が絶対楽。 しかも、コンパイルしないと使えないので、ここでgitとGCCを入れることになる。
$ sudo apt install git-gui g++
gitはgitk
・git gui
ごとインストールしているが、このままだとsudo su
したときにXフォワードが効かなくなるのと、CygwinのXでgitkなんかを使ったときに日本語が化けらったするので、ついでに対応しておく。
Xはxauth
まわりをごちゃごちゃいじる必要があるが、どうもXAUTHORITY
環境変数をきちんと設定してexport
しておけば済むみたい。
この辺もOpenSUSEでは気にしたことがなかった。
$ cd; echo export 'XAUTHORITY=~/.Xauthority' >> .bashrc $ sudo apt install fonts-noto
続けてツールをcloneしてきてビルド。
$ git clone user@server:/path/to/conf-tool $ cd conf-tool $ g++ -Wall -Wextra -O -o merge-group merge-group.cpp $ g++ -Wall -Wextra -O -o merge-passwd merge-passwd.cpp
passwd
ファイルにグループIDが含まれるため、必ずグループの方からマージすることになる。
古いホストからpasswd
とgroup
を持ってきてマージを実行する。
本当はshadow
も欲しいが、他のユーザーのパスワードは再設定ということにする(開き直り)。
いや、昔はsudo
使ってなくて、どうせssh
の公開鍵認証でしかログインしないから、自分のパスワードエントリは!
で潰してあって、shadow
を持ってくる必要がなかったんだよね。
sudo
を使おうとすると、root
のパスワードがいらない代わりに、自分のパスワードがないといけない・・・。
あと、実は以前passwd
をマージしたときにmerge-passwd
がばぎゅってて(今は直した)、ユーザーIDが重複してました。
実際にはそれを直してからマージしてます。
$ cd $ mkdir priv $ chmod 700 priv $ cd priv $ PATH=$PATH:~/conf-tool $ scp user@oldhost:/etc/passwd passwd.old $ scp user@oldhost:/etc/group group.old $ check-id-dup.sh < passwd.old $ check-id-dup.sh < group.old $ merge-group -s 20010 group.old /etc/group > group.new $ diff-id.sh group.old group.new $ diff-id.sh /etc/group group.new $ merge-passwd -s 20010 passwd.old /etc/passwd group.old group.new > passwd.new $ diff-id.sh passwd.old passwd.new $ diff-id.sh /etc/passwd passwd.new
プログラムの中身がないから何をやってるかさっぱりだが、ポリシーとしては、
このとき、IDが重複するようなら、0番台のIDは20000番から、1000番台のIDは1000番台のIDの一番後ろの次から、10000番台のIDは10000番台のIDの一番後ろの次から振りなおす。
20000番台で重複した場合は救済策が用意されていないので、その場合は-s
オプションで重複した0番台の割り当て先を明示的に指定する。
0番台はシステムが最初から用意しているID。
1000番台は一般ユーザーID。
10000番台は擬似ユーザーIDだと思っている。
20000番台はIDの墓場。
マージが成功したら置き換えてシャドウを更新。
$ sudo cp passwd.new /etc/passwd $ sudo cp group.new /etc/group $ sudo grpconv $ sudo pwconv
/var
に移動
スワップファイルがルートパーティションにあり、大きさも640MBほどなので、/var
に移して大きさも1GBにしておく。
面倒なのでdd
のカウント数はシェルに計算させている。
$ sudo dd if=/dev/zero of=/var/swampfile bs=1024 count=$((1024*1024)) $ sudo chmod 600 /var/swampfile $ sudo mkswap /var/swapfile $ sudo vi fstab $ sudo reboot $ sudo rm /swapfile
free
やdf
で状況を確認。
カーネルブートパラメータの変更になるので、GRUBから設定するのが今風らしい。
/etc/default/grub
をエディタで開く
GRUB_CMDLINE_LINUX
にipv6.disable=1
を書き加える
sudo update-grub
ちなみに、update-grub2
はupdate-grub
へのシンボリックリンクになってた。
ifconfig
やらip a
やらでIPv6が割り当てられてないことを確認する
UFWを使う。
お気楽でいいが、複雑なことをやらせようとするとやはりiptables
並みの知識は必要になる。
$ sudo ufw allow ssh $ sudo ufw enable
これだけでリブートしても設定が残るらしい。
順番を逆にするとssh
が振り落とされるので注意。
enable
にするときに警告が出るが、事前にちゃんとallow
しておけば大丈夫。
UFWの設定の確認はsudo ufw status
。
おまけで、auth
(ident
、ポート113)は蹴っておいたほうが何かと都合がいいので設定しておく。
$ sudo ufw reject auth
パケットを蹴る設定にはdeny
とreject
があるけど、前者はパケットを捨てるだけ、後者はTCPのRSTパケットを投げるらしい。
stty -ixoff -ixon
bashのヒストリ検索で[Ctrl]+[S]をひっぱたいた瞬間に端末の出力が止まってしまうので。
デフォルトではnano
になっている。
update-alternatives --get-selections
とすると、設定できるalternativesの一覧が出るので、エディタがどの名前になっているか探す
editor
になってるはず。
sudo update-alternatives --config editor
とすると、設定メニューが出るのでお好きなエディタを選ぶ
vi
使いにくいとか言いながら、結局vi
に慣れてしまっている悲しい体。
vipw
なんかは別口で用意されている
ので、一度vipw
を立ち上げておく。
間違ってed
とか選んじゃった場合は、あわてずにselect-editor
を実行する。
/etc/hostname
を確認、必要に応じて編集
逆引きができるようになってるとそこから設定されることもあるようなないような。
/etc/hosts
を確認
DNSがちゃんとしてれば自ホスト名はいらないことがほとんどなので、そういう場合はコメントアウトしておく。 先にDNSを設定するのを忘れないように。
ただ、DNSに頼る前提で/etc/hosts
で自ホストを消していて、シングルユーザーモードとかでDNSキャッシュが死んでると、sudo
が「ホスト名を解決できない」みたいなメールをsudo
するたびに飛ばします。
設定は/etc/sudoer
。
めんどうくせぇ>sudo
/etc/resolv.conf
まわり
このファイルは起動時に自動生成されるので直接いぢってはいけない。
おそらくサーチドメインに問題があるはずだが、/etc/netplan
以下にあるYAMLファイルを編集する。
どこを編集すればいいかは見れば分かる。
複数のサーチドメインを書く場合はコンマで区切る(たぶん)。
あるいはsudo netplan apply
する。
色々検索すると「設定してある」と出てくるが、マニュアルには自動アップグレードの設定方法が書いてあるので、それに従って設定しておくことにする。
ちょっと調べると、まずcron
経由では/etc/cron.daily/apt-compat
が呼ばれる。
頭の方で/run/systemd/system
ディレクトリがあるかどうかを調べていて、あった場合は何もしない。
なければ/usr/lib/apt/apt.systemd.daily
が呼ばれる。
systemd
経由では、apt-daily
とapt-daily-upgrade
というタイマーが仕掛けられていて、apt-daily
の方は1日2回(6時から12時間以内と、18時から12時間以内)、apt-daily-upgrade
の方は1日1回(6時から1時間以内)に発火する。
前者は/usr/lib/apt/apt.systemd.daily update
を、後者は/usr/lib/apt/apt.systemd.daily install
を実行する。
最終的にはapt.systemd.daily
の第1引数が空かinstall
で、unattended-upgrade
が実行可能だとunattended-upgrade
が実行され、20auto-upgrades
にAPT::Periodic::Unattended-Upgrade "1";
と書いてあるとインストールまで行われるのだろう(たぶん)。
なので、デフォルトではスクリプトは走るが何も起きず、apt-config-auto-update
をインストールしておくとパッケージリストの取得まで、10periodic
でDownload-Upgradeable-Packages
を非0にするとダウンロードまで、unattended-upgrade
をインストールしておくと勝手にインストールまで走るっぽい。
sudo apt install unattended-upgrades
/etc/apt/apt.conf.d/50unattended-upgrades
を確認する。
/etc/apt/apt.conf.d/20auto-upgrades
を確認することになっているが、このファイルがない。
実際にapt-file
で検索してみるとやっぱりない。
/usr/share/unattended-upgrades/20auto-upgrades
というファイルと、apt-config-auto-update
をインストールすると湧く10periodic
を合わせると、項目としてはマニュアルの通りになる。
dpkg-reconfigure
でファイルがコピーされてくるらしい。
マニュアルを参考にして適当に設定しておく。
$ sudo dpkg-reconfigure -plow unattended-upgrades $ cd /etc/apt/apt.conf.d $ sudo vi 20auto-upgrades
以下はやらなくても大丈夫そう。
$ sudo apt install apt-config-auto-update $ sudo vi 10periodic
以下をやっとくと色々メールを送ってくれるみたい(MTAを入れないとだめだけど)。
ちなみにこいつは/etc/cron.d
からの起動だった。
$ sudo apt install apticron $ vi /etc/apticron/apticron.conf
他にもupdate-notifier
とかもあるけど、これはものすごい色々なものを入れられてしまう。
reboot-notifier
というのもある。
リブートが必要になると誰かが/run/reboot-required
というファイルを(notify-reboot-required
というスクリプトを実行して)作るので、だいたいはそれを元にごにょごにょしてるらしい。
apt-config-auto-upgrade
をインストールしておくと、自動でパッケージリストを更新してくれる。
apticron
をインストールすると、アップグレード可能なパッケージがあるときにメールしてくれる。
unattended-upgrades
をインストールして設定すると、自動でインストールまでやってくれて、さらにメールを送る設定もできる。
reboot-notifier
をインストールすると、リブートが必要なときにメールしてくれる。
unattended-upgrades
の設定で勝手にリブートするようにもできる。
とりあえず、unattended-upgrades
だけ設定して様子を見る。
$ sudo apt install bind9
named -V
とすると、--sysconfdir=/etc/bind
だということが分かる。
したがって、設定ファイルは/etc/bind/named.conf
になる。
のぞいてみると、include "/etc/bind/named.conf.options";
となっており、named.conf.options
にdirectory "/var/cache/bind";
と書いてあるので、元々持ってる設定ファイルのdirectory
を書き換えておく必要がある。
ここで/usr/local/etc
をcloneしてブランチを切ることになる。
当然root
でcloneするのだが、sudo
はSSHの環境変数を引き継いでくれないのでエージェントフォワードが使えない。
この辺はOpenSUSEでは考えなくてよかった(CentOSとかもかな?)。
色々やってくれていたんだなぁ、と。
とりあえず、sudo -E
でしのぐ。
root
ではまだ他のホストにログインしていないので、一度ログインしてknown_hosts
を作る。
次いで設定ファイルをcloneして、ついでにsudoers
を設定しておく。
$ sudo -E ssh user@server $ cd /usr/local $ sudo -E git clone user@server:/usr/local/etc $ cd /etc/sudoers.d $ sudo su # ln -s /usr/local/etc/sudo/environ . # ln -s /usr/local/etc/sudo/wheel .
ちなみに、environ
にはDefaults env_keep += "SSH_AUTH_SOCK"
と書いてあります。
wheel
には%wheel ALL=(ALL:ALL) ALL
と書いてあります。
Ubuntuにはwheel
がないので。
さっきマージしたときにwheel
グループができあがってます。
sudoers
は書き間違えるとsudo
できなくなるので、root
での作業が一切できなくなります。
できればsudo su
してから編集して、他の端末からsudo
できることを確認してからsudo su
したシェルを終わった方がいいです。
やってもうた時はリカバリーメディアから起動するしかなくなります。
で、BINDの設定。
$ cd /usr/local/etc/named $ sudo git checkout -b newserver $ sudo vi named.conf
directory
を書き換えます。
書き換えたらDNSデータベースへのシンボリックリンクを作っておかないと。
$ cd /var/cache/bind $ sudo ln -s /usr/local/etc/named db
設定ファイルはシンボリックリンクを張る方法もありますが、systemd
の設定ファイルでやってみた。
/lib/systemd/system/bind9.service
を見ると、
EnvironmentFile=/etc/default/bind9 ExecStart=/usr/sbin/named -f $OPTIONS
となっているので、/etc/default/bind9
をいぢればよい。
シンボリックリンクにしてもいいけど、わけが分からなくなりそうなので直接いぢる。
具体的にはOPTIONS
環境変数に-c /usr/local/etc/named/named.conf
を書き加えておけばよい。
これでBIND9自体の設定は終わりだが、実はこれだけでは起動しない。 起動するとこういうログが残る。
$ journalctl -b ... named[634]: open: /usr/local/etc/named/named.conf: permission denied kernel: audit: type=1400 audit(1536939276.534:11): apparmor="DENIED" operation="open" profile="/usr/sbin/named" name="/usr/local/etc/named/named.conf" pid=634 comm="isc-worker0000" requested_mask="r" denied_mask="r" fsuid=53 ouid=0 ...
最初、SELinuxかと思ったのだが、AppArmorだった。
AppArmorの設定は/etc/apparmor.d
にあって、usr.sbin.named
というファイルがあるのでのぞいてみると、#include <local/usr.sbin.named>
と書いてある。
/etc/apparmor.d/local/usr.sbin.named
は空なので、これを削除して/usr/local/etc/apparmor
あたりに設定ファイルを作ってシンボリックリンクを張る。
$ cd /usr/local/etc $ sudo mkdir apparmor $ cd apparmor $ sudo bash -c 'echo "/usr/local/etc/named/** r," > usr.sbin.named' $ cd /etc/apparmor.d/local $ sudo rm usr.sbin.named $ sudo ln -s /usr/local/etc/apparmor/usr.sbin.named . $ sudo systemctl relaod apparmor
あとはBIND9を再起動、動作を確認できたらファイアウォールに穴を開けておく。
必要ならgit commit; git push
しておく。
$ systemctl restart bind9 $ nslookup ... > exit $ sudo ufw allow domain
なお、デフォルトでsystemd
がローカルDNSキャッシュを立ち上げていてポート53を使っているが、lo
インターフェースのエイリアスとして127.0.0.53
を作っていて、ローカルDNSキャッシュはこちらにバインドされている。
あと、さくらのVPSはコントロールパネルから逆引き設定ができるので、正引きを設定し終わったら逆引きも設定しておくといいです。 Ablenetはサポートに連絡すると設定してくれます。 どちらも料金はかかりません。
最近は色々面倒になって、構内のSMTPとPOP3は廃止している。
じゃぁどうやってメールを読み書きするのかというと、受け取ったメールはgmailに転送して、そっちで読んでたりする。
メールを送りたいときはssh
で直接qmail-inject
を実行している。
Cygwinからこんな感じで。
ssh-pageant ssh user@server "/var/qmail/bin/qmail-inject" < file-to-send
だから、家ではPCのメールクライアントは使ってない。
会社はOutlookを強制されて涙目なんだけど(ほんと検索がバカで使えない)。
したがって、使っているデーモンはqmail-send
とその仲間たち、あとは外からメールを受けるためのqmail-smtpd
だけである。
qmailは32ビットでビルドしたいのだが、TLSパッチを当てているせいでOpenSSLで引っかかる。
まずOpenSSLをビルドするところから。
ここでmake
が必要になる。
また、32ビットのビルド環境がないので、それも入れる必要がある。
コンパイラだけ入れればビルドは通るが、ライブラリを入れないと実行ができないという罠が待っている。
ldconfig
も忘れがち。
$ sudo apt install make g++-i686-linux-gnu libc6-i386 $ wget https://www.openssl.org/source/openssl-version.tar.gz $ wget https://www.openssl.org/source/openssl-version.tar.gz.sha256 $ sha256sum openssl-version.tar.gz $ tar xfvz openssl-version.tar.gz $ cd openssl-version $ export CC=i686-linux-gnu-gcc $ ./Configure --prefix=/usr/local/openssl-version-x86 linux-elf $ make $ sudo make install $ sudo ldconfig /usr/local/openssl-version-x86/lib
続いてqmail。 主なパッチは、512バイトを超えるDNS・メッセジーオーバーフロー・メッセージID・TLS・remove-prepend。 他にもあったかもしれない。
$ cd $ git clone user@server:/path/to/qmail $ cd qmail
パッチが更新されていた場合はパッチの当て直し。
Linuxのカーネルみたいにインクリメンタルなパッチならいいが、qmail-tlsはnetqmailからの差分なので、一度netqmailのオリジナルにgit reset --hard
してからパッチを当てて、git reset
でブランチの先頭に戻ってコミットする。
reset --hard
するときに現在のブランチの先っぽに何か印をつけておかないと見失うので注意。
$ git checkout netqmail-tls $ git tag t1 $ git reset --hard netqmail $ patch -p1 < netqmail-1.06-tls-version.patch $ git reset t1 $ git tag -d t1 $ git commit -a $ git checkout master $ git merge netqmail-tls
ここで場合によってはconf-cc
とconf-ld
をいぢる必要がある。
今回はコンパイラがi686-linux-gnu-gcc
で、さっきビルドしたOpenSSLにパスを通さないといけないのでこんな感じ。
あと、エラーや警告を食らわないようにもろもろ。
conf-cc
i686-linux-gnu-gcc -std=gnu90 -O2 -fno-builtin -DTLS=20160918 -I/usr/local/openssl-version-x86/include
conf-ld
i686-linux-gnu-gcc -s -L /usr/local/openssl-version-x86/lib
ビルドとインストール。 qmailのビルドにはユーザーやグループがごちゃごちゃと必要だけど、さっきユーザーとグループをマージしたときに全部終わってるので、あとはビルドするだけ。
$ make $ sudo make setup $ sudo make check
普通、ここで、config-fast
やTLSパッチ用のmake cert tmprsadh
を実行するが、それは全部/usr/local/etc/qmail
に入っているのでここでは不要。
設定ファイル類はgit clone
しただけだとパーミッションが想定どおりになっていないので調整しておく。
シェルスクリプトで一気にやってしまうが、大体以下のような感じ。
alias | ディレクトリはalias:qmail 700 g+s 、ファイルはalias:qmail 600
|
users/* | root:qmail 600
|
control | qmaild:qmail 600 dh2048.pem rsa2048.pem qmaild:qmail 640 rcpthosts servercert.pem qmails:qmail 640 virtualdomains root:qmail 644 残り
|
$ cd /usr/local/etc/qmail $ sudo ./setperm.sh
設定ファイルにシンボリックリンクを張り、systemd
と、あと、TLS用のcrontab
を仕掛ける。
また、users/cdb
はリポジトリに入れてないので、qmail-newu
しておく。
実際にはusers/cdb
はchmod 600
しているので、qmail-newu
もシェルスクリプトにしてある。
一箇所vi
しているのは、ソケットの待ち受けアドレスを書き換えるため。
$ cd /var/qmail $ sudo rm -rf alias control users $ sudo ln -s /usr/local/etc/qmail/alias . $ sudo ln -s /usr/local/etc/qmail/control . $ sudo ln -s /usr/local/etc/qmail/users . $ cd users $ sudo ./newu.sh $ sudo systemctl link /usr/local/etc/systemd/qmail-deliver.service $ sudo systemctl enable --now qmail-deliver.service $ sudo systemctl link /usr/local/etc/systemd/qmail-smtpd@.service $ sudo vi /usr/local/etc/systemd/qmail-smtpd.socket $ sudo systemctl link /usr/local/etc/systemd/qmail-smtpd.socket $ sudo systemctl enable --now qmail-smtpd.socket $ cd /etc/cron.d $ sudo ln -s /usr/local/etc/cron/qmail-update-tmprsadh .
配送のテストをする前に、Maildir
を作っておく必要がある。
$ cd $ /var/qmail/bin/maildirmake Maildir
あとは、qmailのTEST.deliver
、TEST.receive
に従ってテストをする。
リモートからのテストはtelnet
で直接SMTPを叩く。
$ telnet 192.168.1.2 25 Trying 192.168.1.2... Connected to 192.168.1.2. Escape character is '^]'. 220 mx.example.jp ESMTP HELO example.com 250 mx.example.jp MAIL FROM: <user@example.com> 250 ok RCPT TO: <user@example.jp> 250 ok DATA 354 go ahead subject: test test. . 250 ok 1537190551 qp 23956 QUIT 221 mx.example.jp Connection closed by foreign host.
うまくいったらファイアウォールに穴を開けて、リポジトリ更新。
$ sudo ufw allow smtp $ git gui $ git push
もし、ローカルからの発信のみで、リモートからの受信はしない場合(引越前の場合)は、SMTPを止めて、locals
を空に、virtualdomains
を削除すればよい。
locals
は削除してしまうとme
が使われてメールを受け取ろうとするので注意。
うっかりコミットしないように(まぁしてもブランチをリセットすればいいけど)。
$ sudo systemctl disable --now qmail-smtpd.socket $ cd /usr/local/etc/qmail/control $ sudo rm locals virtualdomains $ sudo touch locals $ sudo systemctl reload qmail-delivery.service
メールを送るプログラムがないとシステムがメールを送れないので入れておく。
mailutil
よりもbsd-mailx
の方が入るものが少ないので、bsd-mailx
を入れることにする。
が、どうしてもpostfix
(あるいは他のMTA)が付いてくる。
昔話
postfix
を抜こうとするとbsd-mailx
もいなくなってしまう。
仕方ないのでこれはこのまま放置して、systemctl
で殺しておく(ちゃんと設定してないからどうせ動かないけど)。
$ sudo apt install bsd-mailx $ sudo systemctl disable --now postfix
find
してみるとsendmail
は/usr/sbin
にあり、/usr/lib/sendmail -> ../sbin/sendmail
だったので、
$ cd /usr/sbin $ sudo mv sendmail sendmail.postfix $ sudo ln -s /var/qmail/bin/sendmail .
これでcron
やunattended-upgrades
がメールを送れるようになる、と思う。
apt-cache depends bsd-mailx
するとmail-transport-agent
が依存関係として入っているので、空っぽのmail-transport-agent
パッケージを作ってインストールしてしまえばよい。
空っぽのパッケージを作るにはequivs
を使う(結構でかい、postfix
よりでかかったりして)。
# apt install equivs # equivs-control null-mta # vi null-mta
ここで以下のように2行ほど書き換える。
Package: null-mta Provides: mail-transport-agent
equivs-build
を実行すると.deb
ファイルができるので、dpkg
でインストールする。
# equivs-build null-mta # dpkg -i *.deb
あとはapt install bsd-mailx
すれば、余計なMTAはインストールされずにmailx
だけインストールされる。
メール送信時にsendmail
コマンドを使うが、これはqmailに(qmail-inject
でメールを放り投げる)互換品ができているはずなので、シンボリックリンクを張っておく。
# ln -s /var/qmail/bin/sendmail /usr/sbin
これでcron
やunattended-upgrades
がメールを送れるようになる、と思う。
/etc/apt/apt.conf.d/50unattended-upgrades
のメールアドレスを埋めておく。
他に、.qmail
から指定されているシェルスクリプトやプログラムを持ってくる必要がある。
grep -r '^|' .qmail*
あたりでプログラムを実行している.qmail
を探す。
うちの場合、手製のcheck-spam.sh
、check-null
、メーリングリスト用のseqnum
、addheader
が必要だった。
あとmess822
。
これもちょっとスタイルが古いコードなので、いろいろ引っかかる。
int
に突っ込んでいるところがあるので、32ビットでコンパイルする(qmailと同じで、conf-cc
とconf-ld
を書き換えてi686-linux-gnu-gcc
を使う)。
extern int errno;
をコメントアウト。
errno.h
に#include <errno.h>
を追加。
leapsecs_read.c
のleapsecs_read
関数の最後にreturn
が抜けているのでreturn 0;
を追加。
これ明らかにバグ。
で、こんな感じでconf-cc
を書くと、-Wall -Wextra
でも無警告で通ります(長ぇよ!)。
i686-linux-gnu-gcc -O -Wall -Wextra -fno-builtin -Wno-misleading-indentation -Wno-unused -Wno-implicit-function-declaration -Wno-sign-compare -Wno-main -Wno-parentheses -Wno-missing-field-initializers -Wno-empty-body -Wno-implicit-fallthrough
$ sudo apt install nginx
ここでいきなり
Errors were encountered while processing: nginx-core nginx E: Sub-process /usr/bin/dpkg returned an error code (1)
と言われる。 ログ確認。
$ journalctl -b systemd[1]: Starting A high performance web server and a reverse proxy server... nginx[24332]: nginx: [emerg] socket() [::]:80 failed (97: Address family not supported by protocol) nginx[24332]: nginx: configuration file /etc/nginx/nginx.conf test failed systemd[1]: nginx.service: Control process exited, code=exited status=1 systemd[1]: nginx.service: Failed with result 'exit-code'. systemd[1]: Failed to start A high performance web server and a reverse proxy server.
IPv6を殺しているのがいけないと分かる。
が、このエラーは/etc/nginx/sites-enabled/default
のシンボリックリンクの先にある設定ファイルが出しており、どうせ手持ちの設定と置き換えるので、無視して先に進める。
CGIを実行するためにfcgiwrap
がいるのでこれもインストール。
やっぱりnginx
が動かせないと怒られるけど無視。
ぽこぽことシンボリックリンクを張って、nginx
をリスタート。
ファイアウォールを開ける。
$ sudo apt install fcgiwrap $ cd /etc/nginx/conf.d $ sudo ln -s /usr/local/etc/nginx/http.conf . $ cd ../sites-enabled $ sudo rm default $ sudo ln -s /usr/local/etc/nginx/default-server.conf . $ sudo systemctl restart nginx $ sudo ufw allow http
これでサーバーは動き出すがドキュメントがない。
ドキュメントをCVSからチェックアウトしてくる。
なんで今さらCVSなのかというと、「作業ディレクトリに余計なデータを置かない」から。
手元でHTMLファイルを編集、cvs ci
して、サーバーのHTML公開ディレクトリに行ってcvs up
すると更新が終わるのです。
なんで、CVSはまだなんとなく使えますが、Subversionはほんと忘れそう。
たまに新たにディレクトリ作ったのに、cvs up
に-d
付け忘れてハマってますが。
$ sudo apt install cvs ... W: APT had planned for dpkg to do more than it reported back (8 vs 12). Affected packages: nginx-core:amd64
この警告は無視していいらしい。
CVSでHTMLファイルをチェックアウト。
CVS_RSH
を設定しないといけないと思ったけど、rsh
がssh
へのリンクになってました。
なんで、設定しなくてもssh
でアクセスしに行くけど、一応設定しておく。
.bashrc
にも書いておく。
wwwadmin
グループの人が管理をする前提。
$ export CVS_RSH=ssh $ cd; echo 'export CVS_RSH=ssh' >> .bashrc $ cd /usr/local $ sudo mkdir www $ sudo chgrp wwwadmin www $ sudo chmod g+ws www $ cvs -d :ext:user@example.jp:/cvs-repo co -d www www-docs
ログ周りの設定。
Apache httpd
のrotatelogs
を使う。
パーミッションをいろいろ変更するのだが、デフォルトの位置のままだとunattended-upgrade
がかかったときにパーミッションを元に戻されてしまうことがある(おかげさまで数日分ログを失いました)ので、/var/local
というディレクトリを作って、その下を使うことにする。
とりあえず、nginx
のユーザーIDを確認する。
$ ps -AF | head -n1; ps -AF | grep nginx UID PID PPID C SZ RSS PSR STIME TTY TIME CMD root 24793 1 0 35160 1580 0 22:57 ? 00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on; www-data 24794 24793 0 35831 6212 0 22:57 ? 00:00:00 nginx: worker process
www-data
さんでした。
www-data
さんのグループを確認。
$ grep www-data /etc/passwd www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin $ grep :33: /etc/group www-data:x:33:
www-data
グループでした。
これを元に作業。
$ sudo systemctl stop nginx $ sudo apt install apache2-utils $ cd /var $ sudo mkdir local $ cd local $ sudo chmod g+ws . $ sudo chgrp staff . $ sudo mkdir nginx $ cd nginx $ sudo chown www-data:adm . $ sudo chmod o-rwx . $ sudo mkfifo log.fifo $ sudo chown www-data log.fifo $ sudo chmod 600 log.fifo $ sudo systemctl link /usr/local/etc/systemd/nginx-rotatelogs.service $ sudo systemctl enable nginx-rotatelogs.service $ sudo systemctl start nginx-rotatelogs.service $ sudo systemctl start nginx
カウンタCGIがあるので、パーミッションを調整する必要がある。
例によってシェルスクリプトになっているので、グループ名をwww-data
にして設定スクリプト実行。
$ cd www $ sudo WWWGRP=www-data ./wwwcount-setup.sh
あとはユーザーディレクトリだけど、これはホームディレクトリをコピーすれば勝手についてくるはず。
昔はApacheで全部やってたんだけど、nginxは基本的にフォワードプロキシとして使うようにはできていない。
何ができないのかと言うと、CONNECT
(https://
をそのまま放り投げる)と多段プロキシができない。
前者はパッチ当てればできるらしい。
Ubuntuのnginxにパッチが当たっているかどうかは確かめてない。
以下、フォワードプロキシとして使えそうなものを列挙。
これ入れるんだったらWebサーバーもApache使えよ的な。
こんな本格的なのはいらない。
結構多機能。
シンプル。
和製。ちょっと古い。
apt
で入れると1.8.4が入るが、最新は1.10.0。
実は1.10.0では以下の条件が揃うとフォアグランドでログを標準出力に出しながら動く。
syslog
への出力を指定していない。
-d
オプションを指定している。
apt
で入れてみて、こういう動きにならないのかなー、と思ってgithubでソースを追うと、どうもそういう挙動になっているように見えたので色々やってみたが、どうしても思い通りに動かない。
git blame
してみると、master
のコミットccbbb81a
で機能追加されており、1.8系ブランチには取り込まれてない模様。
どおりで変だと思った。
万人に公開しているプロキシじゃないし、使いたいときにちゃらっと立ち上げて使えればいいので、1.10.0を/usr/local
以下に入れてしまった。
$ cd ~/src $ wget https://github.com/tinyproxy/tinyproxy/releases/download/1.10.0/tinyproxy-1.10.0.tar.gz $ tar xfvz tinyproxy-1.10.0.tar.gz $ cd tinyproxy-1.10.0 $ ./configure $ make $ sudo make install
設定ファイルは/usr/local/etc/tinyproxy/tinyproxy.conf
。
特権ポートを使っていない限り、tinyproxy -d
とすれば一般ユーザーでも動く。
ポートは開けない。
ssh
のポートフォワードで使うので、localhost
からだけ使えればよい。
いたづらしてきた人にお仕置きするツール。
実際にはufw
でdeny
を指定して無反応にする。
reject
だとすぐに接続失敗になるが、deny
だと無反応になるので、ボットはタイムアウトを待つことになる。
ログを見てbanするかどうか決めているので、logger
なんかでログを書き込める人は、簡単にfail2ban
を誤動作させることができる。
十分に信頼できない人にシェルアカウントを与えているようなシステムでは運用に注意する必要がある。
設定ファイルは/etc/fail2ban
にある。
*.conf
に対して、*.local
というファイルを作り、そこにデフォルト設定からの差分を書く。
デフォルトではssh
だけ有効になっている。
とりあえず、こんなjail.local
を書いてみた。
[DEFAULT] findtime = 1m destemail = root@example.jp sender = root@example.jp banaction = ufw bantime = 1d usedns = no
usedns
をno
にしてあるのは、デフォルトでは変なDNS queryが発生してしまうから。
local
とかjp
にサーチドメインを付けて、local.example.jp
とか、jp.example.jp
とかを検索してしまう。
ただ、usedns
をno
にした場合、ログに記録されたアドレスがホスト名になっているとufw
にIPアドレスを渡せない。
ログを監視されるアプリケーション側で、IPアドレスでログを吐くようにする必要がある。
/action.d/ufw.local
は
[Init] blocktype = deny log-all
こうしておくと、banされた後もアクセスしに来るとログが残る。
ufw
のデフォルトではルールに対してはログを残さないらしい。
SSHでユーザー名を入れた後、パスワード認証が使えないと分かった時点で接続を切ってしまう輩は引っかからないらしいので、ルールを追加してみた。
man jail.conf
すると書いてあるが、ルールを追加する場合、.conf
を直接編集しなくても、.local
の方に以下のように書けばよい。
[DEFAULT] prohibited_users = (root) [Definition] failregex = %(known/failregex)s ^%(__prefix_line)sConnection closed by authenticating user %(prohibited_users)s <HOST> port [0-9]+ \[preauth\]
これはこんな行に引っかかる。
sshd[1234]: Connection closed by authenticating user root 192.0.2.123 port 12345 [preauth]
fail2ban-regex
を使うとルールがどう適用されるかが分かる。
fail2ban-regex
のログファイルは実ファイルが必要なようで(matchとmissで2回読むからかな?)、bash
の<( )
記法は使えなかった。
$ fail2ban-regex --print-all-matched /var/log/auth.log sshd
systemd
のジャーナルを直接食わせることもできる。
$ fail2ban-regex --print-all-matched systemd-journal -m '_SYSTEMD_UNIT=ssh.service' sshd
-m
オプションの書き方はjournalctl -o verbose -u ssh
などとすればなんとなく分かるだろう。
journalctl
の-u
オプションではワイルドカードを使えるが、この形式では使えないっぽい。
socket
を使ってるとちょっと困ることになる気がする。
qmail-smtpd
はほとんどログを残してくれない上、向こうが不躾に接続を切ると終了コードが非0になり、systemd
がfailed
と記録してそれが溜まっていってしまう。
うちのSMTPは外からやってくるメールしか受け付けず(MUAが使うことを想定していない)、AUTH
を発行してぶち切る奴は間違いなく普通のMTAではないので、これを弾くことを考える。
まず、qmail-smtpd
をちょっといじって、AUTH
を発行して接続を切られた場合は終了コードで見分けられるようにしておく。
そうすると、
systemd[1]: qmail-smtpd@pid-srvaddr:25-cliaddr:port.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
というログを残すようになるので、これを引っ掛ける。 フィルターはこんな感じ。
[INCLUDES] before = common.conf [DEFAULT] _daemon = systemd [Definition] failregex = ^%(__prefix_line)sqmail-smtpd@\d+-[0-9.:]+-<HOST>:\d+\.service: Main process exited, code=exited, status=2/.*
あとはjail.local
でルールを有効にしてやればよいのだが、このログはqmail-smtpd
ではなく、systemd
が残していることに注意。
したがって、journalmatch
でqmail-smtpd
を指定しても引っかからない。
EXIT_CODE=exited
で引っ掛けることにする。
[qmail-smtpd] enabled = true backend = systemd journalmatch = EXIT_CODE=exited
sudo apt install
で入れる。
nkf
at
入ってなくてびっくりした。systemd
で代替できたりするのかなぁ?
Copyright (C) 2018 akamoz.jp
$Id: sakura-ubuntu.htm,v 1.13 2020/12/10 04:32:07 you Exp $