- 動機: ssh 経由でsendmail を使えると気づいたので応用してみた。
- ローカル postfix に sshさせ、SSHで別サーバーからメール送信させたい。
- 設定の概要
- ssh を使ってメールを送信
- postfix が ssh 経由で sendmail へ転送する。
- HostA の Postfix にssh hostB sendmail を実行させメール配送させる
- master.cf
- main.cf
- 反映
- テスト
- 公開鍵の設定。
- この設定を作ったときに躓いたポイント。
- 秘密鍵を指定してみる。
- 公開鍵の機能を限定しておく。
- 実際にやってみると楽だった
- 参考資料
動機: ssh 経由でsendmail を使えると気づいたので応用してみた。
Dockerや仮想マシンを起動でメール設定が億劫だし、postfixのsmartリレーを設定が面倒。Gmail送信するとgoogle アカウントの規制が多い。何度もパスワードを保存設定をするのが面倒だった。sendmail が ssh 経由で使えることに気づいたとき、メール送信テストで、メールサーバーをいくつ起動しようが、ssh ログインでどっかのPostfixに集約したらいいじゃないかと気づいた。
ローカル postfix に sshさせ、SSHで別サーバーからメール送信させたい。
得られるメリット
メール送信は格段に便利になる。
1つのPostfixをSSH経由で使い回す。
VPS として使ってるサーバーはpotfix導入済みですね。この vps をポート開放やリレー設定をせずに使いたい。テストサーバーのPostfixのメール送信は、SSH経由でVPSのPostfixを利用すればいい。 VPSはポート25から手軽にメールを送信できるのだから、新規でインストールするPostfixはVPSのSSH sendmail でメールを送信すればいいじゃないか。
root@vps:~# apt list postfix* --installed Listing... Done postfix/focal-updates,now 3.4.13-0ubuntu1 amd64 [installed]
Dccker のインスタンスを増やしたり、仮想マシンを増やしているとメール設定と配送テストが億劫になる。億劫だからといって全く設定しないと使えないサービスもある。なので、HostAはすべてのメールを HostB 経由でで送ればいいわけである。 しかし、メールのリレーだとかPostfixのあれこれは覚えたくないのである。そこで、もっとかんたんな方法がないか模索したわけである。
設定と覚えることがシンプル
postfixのことは殆ど知らなくていいのである。ssh接続先に sendmailが動く環境さえあればいい。
パスワードを平文保存しなくていい。
postfix にパスワードを平文保存するための、dockerfileの設定をどうするかと、などを考えなくていい。不要になれば 公開鍵のアクセス許可を抹消すればいい。
ポート開放などに悩まなくていい。
メール送信のサブミッションポートだとかOP25Bとか考えなくていい。22番へ接続してsendmailを起動、メールを配送するだけなのだから。
設定の概要
テストをするにあたり、次のような構成を考えた。
HostA ( postfix) ---ssh----> HostB (postfix sendmail)-smtp--> gmail smtp など
ssh 関連の設定がちゃんとできるなら使えるはずだ。
HostA Postfixは メール送信を ssh HostB sendmail -i
で丸投げ。HostB Postfixは smartリレーで外部のSMTP(Google/Gmail)などへ丸投げ。こうすることとにする。
ssh を使ってメールを送信
HostBのsendmail は、実はSSH経由で呼び出すことができる。
hostBから HostAの sendmail を起動してメール送信
cat sample-mail.txt | ssh HostB sendmail -i -t
ローカルの場合。
自ホストにpostfixが導入され設定済みであれば、ローカルのpostfix を経由してsendmail でメール送信が可能。
次のように、ローカルのUNIXソケットを使って sendmailコマンドを起動したら終了である。
cat sample-mail.txt | sendmail -i -t
この、sendmail コマンドは、ssh 経由でも起動することができるので、とてもかんたんに sendmail を使うことができる。
ぶっちゃけ、php だとか、wordpressだとか、python だとかを開発環境で動かす際のメール配送はこれでほとんどが解決する。送信メールコマンドを /usr/sbin/sendmail
から ssh hostB /usr/sbin/sendmail
に設定を変えれば済むのだから。
ただ、仮想マシンやコンテナだとそうもいかないので、postfixを設定しssh 経由で丸投げすることにする。
postfix が ssh 経由で sendmail へ転送する。
postfix は メールの配送をいろいろなやりかたで転送することができる。 古えのメーリスだとか、ローカル配送だとか、LAN内で配送とか、部署ごとに配送とかできるわけである。
その一つが postfixのpipe である。すでにpipeがあるんだから、postfix が、 sshコマンドで外部sendmail を呼び出せば設定はとてつもなく簡単になるはずである。
HostA の Postfix にssh hostB sendmail を実行させメール配送させる
HostA ( postfix) ---ssh----> HostB (postfix sendmail)-smtp--> gmail smtp など
これをやる方法が transport service 定義である。
master.cf
postfix のmaster.cf に次の行を追記する。
ssh-relay unix - n n - - pipe user=takuya argv=/usr/bin/ssh HostB /usr/sbin/sendmail -i $recipient
main.cf
main.cf 設定に、次の1行を加え、postfix の転送をすべて ssh-relay 経由にする。default_transport を記述すればオッケ
default_transport = ssh-relay
反映
あとは postfix をリロードするわけである。
$ systemctl restart postfix
テスト
cat sample-mail.txt | sendmail -i -t
これで、メールはPostfixから、ssh のコマンドパイプ(pipe)へ転送され、HostB側で送信処理される。
設定の記述量も極小であり、SSHのポートと公開鍵認証だけを意識すれば解決である。ウルトラシンプルである。
公開鍵の設定。
postfix のmaster.cf に追記した箇所を見てみる。
ssh-relay unix - n n - - pipe user=takuya argv=/usr/bin/ssh HostB /usr/sbin/sendmail -i $recipient
ここでは、どのようにメールを配送するのか書いてある。 unix ソケットで受け付けて pipeながす。
pipe の先に ssh コマンドを起動する。起動するコマンドは ssh コマンドで sshがHostBでリモートsendmail を起動する。
とくに、難しいことはない。
ただし、公開鍵認証でコマンドが実行できる必要がある。
hostA に takuya ユーザーを作成し、hostB へ鍵を登録する。
root@hostB:/root $ adduser takuya root@hostB:/root $ su takuya takuya@hostB:~ $ ssh-keyen -t rsa takuya@hostB:~ $ ssh-copy-id hostA
公開鍵の登録をすれば、ssh 経由で sendmail が呼び出せることを確認しておく
takuya@hostB:~ $ cat - | ssh hostA /usr/sbin/sendmail -i -t To:takuya@example.com From:takuya@example.com Subject: relay test hello from HostA via ssh HostB
メールが無事に配送されることを確認する。あとは hostA の postfix にローカルからの sendmail コマンドでSSH経由させるだけである。 楽である。
この設定を作ったときに躓いたポイント。
ユーザーの秘密鍵のパーミッション。と master.cf へ記述する user=$USER のユーザー
ssh を実行するユーザーは root/postfix とかだとうまく行かなかった。
- postfix ユーザーで ssh を起動しようとしたら status=deferred (unknown mail transport error) になるし
- mail ユーザーで ssh 起動しようとしたら、No such file or directory. Permission denied, please try again._ Permission denied, please try again になるし
- root の場合は、postfix が privilegedはだめとかいうし。
というわけで一般ユーザーで起動するのが無難だった。
秘密鍵を指定してみる。
ssh コマンドを指定なのだから、秘密鍵を引数でファイル指定すればいいはずである。 ssh -i 秘密鍵PATH
で使えるのでそれを設定すれば動くはずである。
ssh-relay unix - n n - - pipe user=mail argv=/usr/bin/ssh -i 秘密鍵パス takuya@HostB /usr/sbin/sendmail -i $recipient
hostA で次のコマンドを実行して、HostBからメール送信ができれば、postfixも同じ設定を使えるはずである。
mail ユーザ が sendmail をリモート実行できることを確認する。
root@hostA:~ $ cat sample-mail.txt | sudo -u mail ssh -i /etc/mail/ssh-sendmail-key -l takuya hostB /usr/sbin/sendmail -i takuya@example.com
送信できれば、mail ユーザーを使う設定を記入する
postfix/master.cf に設定を追記する
今回は、設定名を変えて追記した。
ssh-relay2 unix - n n - - pipe user=mail argv=/usr/bin/ssh -i /etc/mail/ssh-sendmail-key -l takuya 192.168.2.5 /usr/sbin/sendmail -i $recipient
postfix/main.cf に設定を追記する
default_transport = ssh-relay2
これで、固定ユーザーに依存せずにメール起動ができるのである。便利ですね。
公開鍵の機能を限定しておく。
特定の公開鍵では、機能を限定することが可能なので、 authorized_keys を使って機能を限定しておけば安心である。接続元を限定したり、起動可能なコマンドを限定しておけばいい。
実際にやってみると楽だった
たとえば、SSHが可能でsendmail が利用可能なレンタルサーバーやVPS経由でメールを送信すれば、 OP25B や submission ポートに悩まされずに済む。
また、VPS側で postfixをリッスンせず、SSHのみ済むのでファイアウォール設定がとてもシンプルに片付くのである。
また、仮想マシンを増やすたびに smart-replay ホストを設定しパスワード保存する必要もないし、 smart-relayを設定するたびに、Google SMTPサーバーや google account secutiy で警告をもらわずに済むのである。
ssh で トンネル貼る必要もないし、socks5しなくても済むし、VPNも要らないのである。SSHなのでちゃんと暗号化されているのである。
さくらVPSやheteml レンタルサーバーで ssh sendmail
をしてしまえば、25番ポートからfromをアレしたメールが送り放題になってしまうのである。postfixのSSH pipe経由とは、実に、けしからん
メール配送解決策である。