それマグで!

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

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

gsuite のアカウント増やさずにメアドだけ増やして mailcow で管理する。

概要

GSuite(google workspace) 宛のメールを、独自のメールホストへ転送してGoogle アカウント管理下にないメールアドレスを使う。

前提条件

課金済み

重大な前提条件 Google Workspaceで課金済み。

課金しているGsuiteが必要です。歴史的経緯の無償版Gsuiteで使えません。

postfix などのメールサーバー

postfix単体が正しく設定されたもの。

デフォルトインストールでは、スパム処理や配送処理をしてないので、そのままでは内部転送が使い物にならないので devecot などIMAPを正しく設定しておいたもの( とりあえずmailcow いれとけばおっけ)

設定ステップ

設定は4ステップが必要

  1. Gmailの設定でホストを追加
  2. 転送設定(ルーティングを書く)
  3. 送信設定(返信・送信をGmail経由にする)
  4. postfix 側でメールボックスを追加

1.google admin でホストを追加

Google admin console にアクセスし、アプリからGmailを開いてホストを追加する。

f:id:takuya_1st:20210318190645p:plain

2. google admin → gmail → でルーティングを追加

ルーティングを追加する。

ルーティング設定の概要は次の通り

  • 対象経路
    • 外部から受信
    • Gmail内部から受信メール
  • 対象メアド
    • 受信者が一致
      • パターンに一致
      • 正規表現パターンに合致したもの
    • 存在しないメールアドレス
  • 転送先
    • 先程設定した mailcow サーバー
    • バウンスメールはOP25Bのために転送されないので無視する

      f:id:takuya_1st:20210318190929p:plain

      f:id:takuya_1st:20210318191000p:plain

      f:id:takuya_1st:20210318191023p:plain

3 送信ルート・返信ルートをGmail経由にする。

mailcow posfixから直接相手に送信せずに、GoogleSMTPを経由するよう設定する。

まず、GoogleSMTP経由を許可させる。 f:id:takuya_1st:20210318191147p:plain

つぎに、PostfixのTransport設定する

トランスポート設定で、smtp-relay.gmail.com:587 をスマートリレーで設定する。

このとき、SMTP認証が必要になるので、Google Workspace中の適当な アカウントをless secure apps(安全性の低いアプリ)に認定するか、アプリごとのパスワード生成(2FA時)をしてリレーを設定すればオッケ。

もし送信元のmailcowが固定IPアドレスであれば、SMTP認証は不要なのだが・・・

mailcow の場合

mailcow で転送設定するなら。次のステップで

  • 一般からSender Transportを追加
  • ドメインから 追加したSender Transportを指定

mailcow にログイン して 右上メニュ → ルーティング → Sender Transport

f:id:takuya_1st:20210318192212p:plain

右上メニュ→メールセットアップ→ドメイン→編集 f:id:takuya_1st:20210318192414p:plain

ドメインが追加されてない場合は追加しておく。

4.posftix でメールボックスを追加

postfix でちゃんと配送設定を書いていれば不要。

mailcow の場合。

mailcow を使うなら設定をする必要がある。

mailcow にログイン → 右上メニュー → mailsetup → 真ん中タブ → mailboxes の順にたどってメアドを追加。 f:id:takuya_1st:20210318192008p:plain

最後に

メールの送受信をチェックして終了。

GoogleSMTP経由で送信されるので、うっかりSPAM判定されるということはまずなさそう。

受信もGoogleSMTP経由から配送されるのでスパムフィルタもそこそこ動いてくれそう。

メールアドレスだけほしいために、Google Driveの容量とかGCPAPI利用可能なアカウントを発行するのは煩雑すぎるしこれでいいや。

google workspace がメールのルーティング機能を提供してくれているとか優しすぎです。Postfixの地獄のセットアップ修行をしなくてもmailcow 入れていたらとりあえず動くのも幸せすぎます。

ただ、gsuite と同じドメインで、独自メアド運用すると、一部のgoogle accounts 管理やログイン連携がちょっと面倒なことになりそうなんですよね。

参考資料

https://support.google.com/a/answer/60730?hl=ja&ref_topic=2921034

https://support.google.com/a/answer/2685650?hl=ja&ref_topic=2921034#zippy=%2Csmtp-%E3%83%AA%E3%83%AC%E3%83%BC-%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%A6-gmail-%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E7%B5%8C%E7%94%B1%E3%81%A7%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%92%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%99%E3%82%8B%2C%E3%81%99%E3%81%B9%E3%81%A6%E3%81%AE%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%92%E3%82%B2%E3%83%BC%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A4-%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E7%B5%8C%E7%94%B1%E3%81%A7%E9%80%81%E4%BF%A1%E3%81%99%E3%82%8B

https://support.google.com/a/answer/2956491#zippy=%2Cpostfix

xz/unxz コマンドをインストールする。

unxz コマンドが見つからない。

debian でいつものように xz をunxz展開しようとしたら。コマンドが見つからない

unxz ubuntu-20.04.2-preinstalled-server-arm64+raspi.img.xz
-bash: unxz: command not found

インストール

xzを使うパッケージは、xz-utilsになる。

次のコマンドがインストールされることがわかる。

sudo apt-file list xz-utils
xz-utils: /usr/bin/lzmainfo
xz-utils: /usr/bin/unxz
xz-utils: /usr/bin/xz
xz-utils: /usr/bin/xzcat
xz-utils: /usr/bin/xzcmp
xz-utils: /usr/bin/xzdiff
xz-utils: /usr/bin/xzegrep
xz-utils: /usr/bin/xzfgrep
xz-utils: /usr/bin/xzgrep
xz-utils: /usr/bin/xzless
xz-utils: /usr/bin/xzmore

インストール結果

 sudo apt install  xz-utils
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  gyp libatomic1 libbrotli1 libjs-inherits libjs-is-typedarray libssl-dev libuv1-dev
Use 'sudo apt autoremove' to remove them.
The following NEW packages will be installed:
  xz-utils
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 183 kB of archives.
After this operation, 453 kB of additional disk space will be used.
Get:1 http://deb.debian.org/debian buster/main amd64 xz-utils amd64 5.2.4-1 [183 kB]
Fetched 183 kB in 0s (2,361 kB/s)
Selecting previously unselected package xz-utils.
(Reading database ... 30068 files and directories currently installed.)
Preparing to unpack .../xz-utils_5.2.4-1_amd64.deb ...
Unpacking xz-utils (5.2.4-1) ...
Setting up xz-utils (5.2.4-1) ...
update-alternatives: using /usr/bin/xz to provide /usr/bin/lzma (lzma) in auto mode

なんか lzma も増えた

mailcowをインストールしてubuntuでお手軽メールサーバー構築

mailcow でメールサーバー構築

メールの運用はめんどくさい。それ以前にインストールがめんどくさい。

スパム対策や、DKIMだとか、MXとMTAだとかあれこれ考える必要がある。考えるのをやめて、GoogleApps(Gsuite/Google workspace)だとかoffice365を使えばいいんだろう。しかし、すべてが解決するというわけでもない。メアドの追加だとか、ライセンス数を考慮したらしんどい(エイリアスで無料で足せるんだけど)、キャッチオールアドレスが欲しくなったり

期間限定なプロジェクトで、アルバイト雇用など一気に人が増えるとか。フェスティバルやイベントのために問い合わせフォームとメアドが必要だったりとか。たかだが数ヶ月のためにメアドとアカウントを大量にサービス側で追加するのもコスト的に負荷がかかる。そういうなにかメアドを管理できる方法を模索した。

mailcow パッケージがオールインワン

mailcow というパッケージをみつけた。 https://mailcow.email/

これをDockerで動かすとメールのあれこれが解決しそう。

WEBメールとカレンダーとアドレス帳機能があるSogo WEB を使える。

OpenMail プロジェクトも mailcow をベースに使っている。

https://openemail.io/

スパム対策

最初から、設定済みでソフトウェアが導入されているので、とても楽。 設定を増やすだけでいいのだから。必要なclamdとRspamdとか最初から入ってる。これが嬉しい。

インストール

インストールは、とてもかんたんだった。

docker と docker-composeが動く環境さえあればいい。

準備

ssh server-docker-host
cd /var/www/virtualhost/maicow.example.com
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
./generate_config.sh
vim  mailcow.conf

設定変更

設定変更は次の箇所だけにした

MAILCOW_HOSTNAME=mail.example.com
HTTP_PORT=11334
HTTPS_PORT=11335
SMTP_PORT=2525
TZ=Asia/Tokyo

MXレコード設定

dns 設定 で MXレコードとAレコード(今回はcname)を作った。

## 
mail.example.com cname gw.example.com
mail.example.com mx gw.example.com

リバプロ設定

HTTPSの443アクセスで、nginx があるので、それをdockerで起動したmailcow へ向け、リバプロする。

server {
  listen 443 http2 ssl;
  server_name mail.exammple.com;
  if ($scheme != "https") {
  return 301 https://$host$request_uri;
  }
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  location ~ {
    proxy_set_header Host $host;
    ## 略
    proxy_pass http://docker-host.local:11334;
  }
  
}

起動と終了

docker-composeで解決。

cd $installed_path
docker-compose up -d
docker-compose restart

docker-compose でshutdown rm しても 設定が ./data に残るので、永続化も問題ない。ついてもportainer を入れていおいてもいいくらいだ。

OP25B をどうするのか

メール送信を行うとき、配送先のメールサーバーの25番に接続するが、一般のプロバイダ網内から外向けの25番は接続ができない。

通常個人ユーザーであれば、外向きにメール送信をする際のサブミッションポートを使えば事足りるが。メールサーバー間の配送は相手サーバー25番へ接続が不可欠である。

つまり Postfixから相手への配送は宛先ポート25番で転送するが、OP25Bでその接続(宛先ポート25)は使えない。ということで、代替手段が必要になる。

代替手段といっても、外部で25番が接続許可されている、制限されないIPアドレスのサーバーを確保するのが対策。わかりやすく言えばFromを書き換え許可されているSMTPサーバーが確保できるかが重要。

外部25へ転送方法さえ確保できれば、サーバーへの接続方法はなんでもいい。VPN接続でもよし、SSHポート転送でもよし、SSHのパイプ経由すら使える。一般的ならSubmissionポートへ接続だろう。

mailcow の管理画面からトランスポートを設定できる。

OP25Bへの対応が必要な場合、トランスポートを設定して、外部のリレーサーバーを指定する。mailcow のWEB画面から設定できるのが強い。

起動後の初期パスワード

初期パスワードは admin / moohoo でログインできるので変えておく。

SOGoが嬉しい

SOGoでWEBメールのUIがあるので、最低限WEBからメールを使うことができる。IMAPPOP3SMTP(submissuon)のポートや総当り対策を考えなくていいのは本当に嬉しい。

カレンダー

共有できるWEBカレンダーがあってちょっと驚く。

アドレス帳

メール運用に不可欠なアドレス帳もWEB機能があり、さらにドメイン内ユーザーでの共有アドレス帳も使える。いいじゃん

スパム対策

Rsamd があるのでこれを使っていく。フィルタの書き方や clamcv の導入に時間を取られないので嬉しい。

キューの一覧

postfix にたまったキューのチェックや削除も mailcow のWEB画面から行える。

メアドの追加

メールアドレスとメールボックスの追加は、mailcown のUIから行える。

そのさいにエイリアスや複数のドメインなども使える。

mailcow導入で考えることが減る。

とりあえず、MXレコードとポート転送さえしておけば、辛うじてつかえるメール環境が手に入る。がちでPostfixから設定したらノウハウがまとまるまで1年経っても終わらない仕事になる。docker-compose でWEBメールボックス一式が手に入るのは強い。

運用してくとスパムとの戦いユーザー数が多くなる長期間の運用などは、運用担当者を割当てノウハウを確保してくのが大変だろうけど、一通り行えることはわかる。

VPSのメモリと容量が余っていればとりあえず入れておけば、クラウド追加課金を考えずにメアドを増やせて便利だと思う。

XMPP や unbound は流石に要らないと思うけど・・

その他のWEBメール環境

PostfixDovecotSMTPIMAPさえ動かせてしまえば、あとは好きにできる。

nextcloud-mail / roundcube /Cypht のような、他のWEBメール環境も使える。

WEBメール環境を確保するには、IMAP環境さえあればなんとかなる。しかし、自前のIMAP構築のためにPostfixDovecot+pamAssassinのインストールがあまりに面倒すぎる。それで誰も試さないのがメール構築。 メール運用の最初ハードルがインストールと構築だと思う。それがこんなに簡単に行けるなら、脱GoogleGmailも不可能じゃないと思えてくる。

2023/10/17 追加

Solr が動かないので

https://docs.mailcow.email/manual-guides/Dovecot/u_e-dovecot-fts/#delete-mailbox-data

インデックスが入ってるフォルダを明示的に消した。

docker compose exec solr rm /opt/solr/server/solr/dovecot-fts/data/index
docker compose exec solr rmdir /opt/solr/server/solr/dovecot-fts/data/index

参考資料

nvim で vimrc が読み込まれなくなった

~/.vimrc が読み込まれなくなった

特定の環境で nvim を使っていると、 .vimrcが正しく解釈されなかったのでメモ。

mkdir -p ~/.config/nvim; ln -s ~/.vimrc ~/.config/nvim/init.vim

nvim は .config を標準に変えたんですね。

参考資料

https://stackoverflow.com/questions/3495124/not-reading-vimrc

ssh で ユーザー名 と ネットワークの複数条件のANDで設定を書く

sshd_config で条件を複数AND/ORで書きたい

ユーザーが takuya で、LocalIPからの、の両方にマッチしたときのみ、パスワードログインを許可する。

複数を記述は、そのまま列挙すればいい。

Match User takuya Address 192.168.0.0/16
  PasswordAuthentication yes

複数条件をORで列挙したいとき

たとえば、takuya or pi のユーザーに対して許可したい

Match User takuya,pi Address 192.168.0.0/16
  PasswordAuthentication yes

たとえば、複数のネットワークを指定したいとき

Match User takuya,pi Address 192.168.11.0/24,192.168.1.0/24
  PasswordAuthentication yes

などとと書けば、AND OR のように使うことができる。

not の 否定条件も併せて使うと便利。

拒否すると列挙が楽になると思う。

Match Group sudo User !pi Address 192.168.11.0/24,192.168.1.0/24
  PasswordAuthentication yes

ネットワークもアドレス範囲をガッツリかいて特定を拒否とかね。

Match User takuya,pi Address 192.168.11.0/24,!192.168.11.222
  PasswordAuthentication yes

ANDで絞り込めると便利。

複数条件をANDでかけると、条件記述がシンプルになって嬉しいです。

関連資料

参考資料

htaccess でサブディレクトリをトップディレクトリとして公開する。

htaccess をサブディレクトリをトップディレクトリとして公開する。

https://example.com として、 https://example.com/subdomain を公開したい。

RewriteEngine on
RewriteBase /
RewriteRule ^(.*)$  subdirectory/$1

現実で、こんなことする必要はないんだろうが。特定のディレクトリで作業内容をいったん公開しておいて、そのまま正式リリースしたいとか。

ほかの条件と組み合わせると格段に使える。

たとえば、公開日まではサブディレクトリへ転送するとか

# 2021年03月01日 09:00 まではティザーページ(サブディレクトリ)を表示
RewriteEngine on
RewriteBase /
RewriteCond %{TIME} <202103010900.*
RewriteRule ^(.*)$  subdirectory/$1

参考資料

.htaccess の書き方(リダイレクト編) - Qiita

curl でSMTP経由のメール送信

curlsmtp 経由でメールを送信する。

curl -v --url 'smtp://192.168.1.1:2525' \
  --upload-file sample-mail.txt \
  --mail-from takuya@example.com \
  --mail-rcpt takuya@example.com

curl で送信できるわこれ。

smtpTELNETで接続してメール送信テストしなくて済む。 ポート解放をしておけば、あとあと困らないでメール送信ができますね。

curl って万能ですね。

ELHO ホスト名を指定する場合

Postfixをポートフォワーディングで使っていて、 Helo command rejected: need fully-qualified hostname となる場合

curl -v --url 'smtp://192.168.1.1:2525/smtp.example.com' \
  --mail-from takuya@example.com \

このように、スラッシュのあとに、EHLOのホスト名を追記すればいい。

curl で smtps で gmail 経由する場合

メールのログインとパスワードを追記したら SMTP-AUTH を経由してSMTPSでメールが送信できる。

curl --url "smtps://smtp.gmail.com:465" \
\ 
 --ssl-reqd --mail-from "sender@gmail.com"  \
 --user "sender@gmail.com:senderGmailPassword" \
\
 --mail-rcpt "example@gmail.com"\
 --upload-file /var/scripts/mail.txt \

GMAILのメール送信もcurl で1行でできるので、google の 「 less scure app ( 安全性の低いアプリ)」が1ヶ月未使用ならオフにされちゃうので定期的にログインしておくのに良さそう

postfix 相手にSMTPS (SSL / starttls ) で、オレオレ証明書

Postfixオレオレ証明書を使っていて、Submissionポート 587 を通して接続する場合

startls は内部がSMTPなので、smtp:// を使う。smtps ではない。ただし、starttls でSSLを使うので --ssl をつける。さらに、証明書がオレオレ証明書なので -k / --insecure をつける。

curl -v --url 'smtp://10.185.93.22:587/mailcow.example.com' --ssl -k

さらに、それが、SMTP Auth を経由する場合

curl -v --url 'smtp://10.185.93.22:587/mailcow.example.com'  --user "takuya@example.com:PASSWORD" --ssl 

なんかオプションが増えて大変だけど、ちゃんと送信できる。

TO / FROM を正確に記述する

curl は to(recpt) / from をSMTPプロトコルにつかうので、メールの本文のFROM/TOは書き換えは行われない。当然であるが。

メールのボディを指定して、FROM/TOとSubjectを正確に記載すると普通のメールとして送信が可能。SMTPの動作チェックであればなくても構わないので上記まででは省略してた。

echo 'To: takuya@example.com
From: takuya@mydomain.tld
Subject: this is a test from 465

this is a test
using smtps
' \
| curl -v --ssl --url 'smtps://mailcow.mydomain.tld:465' \
   --mail-from service@mydomain.tld \
   --mail-rcpt takuya@example.com \
   --user "account@mydomain.tld:XXX_PASS_XXX" \
   -T -

ここでは、--mail-from と、ボディの From: と、--user は、敢えてすべて異なるようにしている。SMTPではこれらを一致させる必要はなく、実際にこれで送れてしまうのだ。

一般のメールだと、拒否されるかもしれないが、smtp replay に直接投げ込みできると送信が可能なのである。

そして、From:が受信者のメーラーで表示されるはずだ。 ---mail-fromsmtp プロトコルだし、--userSMTP Auth用である。ややこしいですがそういうものなんでしょうね。

curl はほとんどの環境で使える。

curlWindows に添付された ( C:/Windows/System32/curl.exe ) ので、すべての環境で使えるコマンドになった。

curl未インストールは、 alpine や debian 軽量版など、特殊状況に限られるようになった。

curl だけでメールは送れるし、コマンド呼び出しで使えるのである。

メールプログラムを書く、ライブラリをインストールするなど、車輪の再発明するくらいならcurl でいいのである。

2022-03-15 追記

EHLOについて追記。

SMTP + start TLS について追記。

2022-03-16 追記

メールボディ指定、FROM / mail-fromについて追記。

参考資料

https://stackoverflow.com/questions/10523147/what-are-the-curl-smtp-command-line-arguments-to-support-gmail-tls-starttls-v

16 Command Examples to Send Email From The Linux Command Line

Sending email - Everything curl

Postfixが ssh ログインして、メールをリレー配送する設定を入れる。

動機: ssh 経由でsendmail を使えると気づいたので応用してみた。

Dockerや仮想マシンを起動でメール設定が億劫だし、postfixのsmartリレーを設定が面倒。Gmail送信するとgoogle アカウントの規制が多い。何度もパスワードを保存設定をするのが面倒だった。sendmailssh 経由で使えることに気づいたとき、メール送信テストで、メールサーバーをいくつ起動しようが、ssh ログインでどっかのPostfixに集約したらいいじゃないかと気づいた。

ローカル postfixsshさせ、SSHで別サーバーからメール送信させたい。

得られるメリット

メール送信は格段に便利になる。

1つのPostfixSSH経由で使い回す。

VPS として使ってるサーバーはpotfix導入済みですね。この vps をポート開放やリレー設定をせずに使いたい。テストサーバーのPostfixのメール送信は、SSH経由でVPSPostfixを利用すればいい。 VPSはポート25から手軽にメールを送信できるのだから、新規でインストールするPostfixVPSSSH 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 をインストールしたが、自身は外部へ送信しない。
  • HostB ( postfix をインストール・設定済サーバ、smart-replay で外部へ送信する)

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 経由で丸投げすることにする。

postfixssh 経由で sendmail へ転送する。

postfix は メールの配送をいろいろなやりかたで転送することができる。 古えのメーリスだとか、ローカル配送だとか、LAN内で配送とか、部署ごとに配送とかできるわけである。

その一つが postfixのpipe である。すでにpipeがあるんだから、postfix が、 sshコマンドで外部sendmail を呼び出せば設定はとてつもなく簡単になるはずである。

HostA の Postfixssh hostB sendmail を実行させメール配送させる

HostA ( postfix) ---ssh----> HostB (postfix  sendmail)-smtp--> gmail smtp など
  • HostA ( postfix をインストールしたが、自身は外部へ送信しない。
  • HostB ( postfix をインストールしサーバ、smart-replay で外部へ送信する)

これをやる方法が 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をアレしたメールが送り放題になってしまうのである。postfixSSH pipe経由とは、実に、けしからんメール配送解決策である。

参考資料

Using sendmail over SSH - Super User

sendmail コマンドを ssh 経由で呼び出せることに気づいた。

sendmail でメールを送ろうとして苦労してた。

webの問い合わせフォームだとか、phpsendmail をサーバでは使えるが、ローカルでは smart-relay な postfix を設定して試していた。

実にめんどくさいことだった。或る日、コマンドを眺めていて、ふと気づいた。sendmail って ssh経由で呼び出せるんじゃね。

ローカルのpostfix を経由してsendmail を使う場合、次のように、ローカルのUNIXソケットを使って sendmailコマンドを起動したら終了である。

cat sample-mail.txt |sendmail -i -t 

これ、ssh経由でコマンド呼び出せば、メール配信完了するんじゃないか。ためしたできた。いままでの 苦労は何だったんだ・・・

ssh を使ってメールを送信

HostBのsendmail は、じつは、SSH経由で呼び出すことができる。

cat sample-mail.txt | ssh HostB /usr/sbin/sendmail -i -t 

この、sendmail コマンドは、ssh 経由でも起動することができるので、とてもかんたんに sendmail を使うことができる。

ぶっちゃけ、php だとか、wordpressだとか、python だとかを開発環境で動かす際のメール配送はこれでほとんどが解決する。

レンタルサーバーやVPSSSH経由でsendmail コマンドを発行すればいいのだから。

windows の標準搭載されている、マイクロソフトのアプリを削除する

プリインアプリは正直言って要らないもある。

右クリックメニューででてきたり、開くメニューで目障りなので消してしまいたい。

windows の標準搭載されている、マイクロソフトのアプリを削除する。

メール・カレンダーは消すか迷う。

たとえば People を消すには、次のようにします。

get-appxpackage *Microsoft.People* | remove-appxpackage

f:id:takuya_1st:20210305111340p:plain

まず使わないアプリを消す

以下は、まず使うことがないので消しておく。

## Groove ミュージック
get-appxpackage *Microsoft.ZuneMusic* | remove-appxpackage
### 映画テレビ
get-appxpackage *Microsoft.ZuneVideo* | remove-appxpackage
## OneNote
get-appxpackage *Microsoft.Office.OneNote* | remove-appxpackage
## People
get-appxpackage *Microsoft.People* | remove-appxpackage
## Xbox
get-appxpackage *Microsoft.XboxApp* | remove-appxpackage
## ペイント 3D
get-appxpackage *Microsoft.MSPaint* | remove-appxpackage

ペイント 3Dは、標準から削除されるようなのでとっとと削除してほしい。

Xboxも要らないと思うし、映画テレビなんてもっといらない。Grooveに至ってはMSは買収後放置しすぎだろ。

アプリ名の調べ方。

Powershell だけだと覚えることが多すぎるので、MSYS/MinGWから動作すると楽。

MINGW64 ~$ powershell  'get-appxpackage Microsoft*' | grep ^Name | sort 

参考資料

https://answers.microsoft.com/ja-jp/windows/forum/apps_windows_10-outlook_mail/windows-10/239ef7e9-9f4f-40dc-bf41-2cd2b8217843

windows 標準カレンダ・メールにiCloud のアカウントを接続する。

windows のメール設定に書いても設定できない。

Windows のカレンダーとメール設定に icloud のアカウントを設定し、iPhone とカレンダーを共有する。

iCloud のアカウントと接続すれば問題ない。だが、設定にはいくつかの問題点がある。

アプリのプライバシー設定

アプリのプライバシー設定で、Windowsのカレンダ・メールが「アカウント」のアクセス権をもっていないと、エラーにすらならず、設定画面が設定中で止まるだけである。権限がないというメッセージも出てこない。

icloud のパスワード設定

iCloud では、パスワードをデバイスに保存する使い方が非推奨となっていて、パスワードを保存が必要なアプリごと「別のパスワード」を発行するようになっている。OAuthをしなくてもいいのは便利だが、設定がわかりにくいので知らないと詰む。

アプリのプライバシー設定

アプリのプライバシー設定は、Windowsの設定からプライバシー、アカウントを選んで設定。

f:id:takuya_1st:20210304070807p:plain

Apple ID の設定画面でパスワードを生成

https://appleid.apple.com/account/manage にアクセスし、セキュリティからパスワードを追加。

f:id:takuya_1st:20210304071450p:plain

準備が整ったら、 Windowsでアカウントを追加する。

アカウントの追加を押す。

f:id:takuya_1st:20210304071645p:plain

icloud を選んで作成したパスワードを入れる。

f:id:takuya_1st:20210304071113p:plain

これでWindowsのカレンダーからiCloud が使える。

Windowsのカレンダーからイベント(予定)の編集と追加が行えるようになる。

その他の方法。

applewindows 版の icloud アプリをインストールしてもいいが、 outlook にしか対応しておらず、Windowsプリインアプリのメール・カレンダーでは使えないので注意が必要。

WSL (v1)からdocker を使う

WSL (v1)からdocker を使う

WSL から Docker を使うには、TCPでローカルホストに接続するのが楽ちん

docker ( windows ) のインストール

まずは、Windows にDocker-Desktop をインストール

choco install docker-desktop

port 2575 を有効にする。

インストールしたら、Dockerが外部からの接続を受け付けるように設定する。

f:id:takuya_1st:20210304070117p:plain

WSL 側で docker-client を使えるようにインストール。

WSL v1 ( ubuntu / debian )で docker コマンドをインストール ( cli だけでいい)

sudo apt install docker-ce-cli

DOCKER_HOST の環境変数を用意する。

docker-desktop がリッスンしているポートを指定する。

export DOCKER_HOST=tcp://localhost:2375

あとは通常通り使える

WSL v2 じゃないとだめってわけじゃなく、TCP接続すれば別に問題なく動く。

docker ps 

たとえば、php を動かす。

php のコードを docker 内部で動作させる。

wsl v1 のパスを 明示的に変換する必要がある。とくにボリュームを接続するときは、 wslpath を使ってwindowsC:\ のパスに変換して上げる必要ある。

docker run --rm -it -v "$(wslpath -m ${PWD})":/app -w /app -u www-data php:7.4-cli php test.php

ボリュームの接続先はどこでも動きそうだ。

WindowsビルトインのOpenSSH サーバーが鍵認証できない。(ログを有効にして確認しながら設定する。)

Windows のOpenSSH サーバーが鍵認証できない。

ログをみると、公開鍵で認証できない。理由はパーミッションパーミッションLinux/BSDと同じく他者から書き込み不可が必須である。

WindowsでもLinuxなどのOpenSSH-サーバーと同じ

Admin権限で sshd.exe が起動している。設定はLinuxと同じ。authorized_keys の権限は、他人から読み込みはオッケ。書き込みは自分だけ。

デフォルトの設置場所

C:\ProgramData\ssh\administrators_authorized_keys

WindowsのデフォルトのsshdC:\ProgramData\ssh に公開鍵を保存します。 ここはシステム領域なので注意が必要です。SSHログインするユーザがUACを使えないと書き込みできません。

設定

Windowsビルトインのssh サーバーに設定する設定は次のとおりです。

## 既存
Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
## 追加
Match User takuya
       AuthorizedKeysFile .ssh/authorized_keys

私は、ユーザフォルダに設置するほうが確実だと思います。

公開鍵のフォルダのパーミッションに注意します。

公開鍵をいれた( authorized_keys ) のパーミッションは次のようにします。

編集は自分だけ。

閲覧はAdministrators だけ

エラーメッセージを見るには。

冒頭にある、パーミッションエラーの詳細なログ情報は、ssh サーバーの設定を変更し再起動するとファイルに書かれます。

sshd.exeの設定とログは、次のフォルダに設定ファイルがあり、ログも同じ場所に書かれます。

設定フォルダ

C:\ProgramData\ssh

logs にログを書き出したいとき。

logs フォルダに、ログを書き出し時は、つぎのように、設定を LOCAL0 に変えると、通常のLinuxと同じくファイルにAppendされてる。

# Logging
SyslogFacility LOCAL0
#SyslogFacility AUTH
#LogLevel INFO
LogLevel DEBUG3

もし設定をせず、デフォルト設定のままであれば、ログは、Syslog( event viewer )に書かれる。しかしsyslog では、ログの詳細情報が書かれず、全く役に立たない。そのためファイルに記入させる必要がある。 ファイルに記入させる設定が SyslogFacility local0 である。 設定し再起動 net stop ssh ; net start ssh するとログが見れるようになる。

ログを流すようにすると、公開鍵認証に関するエラー確認できる。公開鍵の認証設定が動くようになるまで、デバッグモードでログをファイルに書くようにする。

windows ビルトインの sshd(openssh-server)の再起動。

設定ファイルを編集したら、再起動して設定を反映します。

管理者権限の コマンドコンソールで

net stop sshd
net start sshd

PS (powershell) からは Service コマンドで、この手の記述でも動くはず(ためしてない)

PS C:\ProgramData\ssh> Stop-Service  sshd
PS C:\ProgramData\ssh> Start-Service sshd
PS C:\ProgramData\ssh> ReStart-Service sshd
PS C:\ProgramData\ssh> Stop-Service    'OpenSSH SSH Server'
PS C:\ProgramData\ssh> Start-Service   'OpenSSH SSH Server'
PS C:\ProgramData\ssh> ReStart-Service 'OpenSSH SSH Server'

注意点: 接続中は再起動されない。

これは、LinuxのOpenSSHサーバーと違う点なので注意。

接続中のセッションがあれば、サービス再起動されない。接続が残っていると再起動がうまく行かず、設定が反映されないことがあるので注意

わたしも、設定反映されなくてパニクった。

ユーザーフォルダのAuthorized_keys を使いたい。

デフォルトでは、authorize_keys の設置場所は、Adminと一般ユーザーで違う場所が指定されている。WEBサイトを閲覧していると、Match Group コメントアウトするように指示する記事を散見するが、個人的には Match User を追記する方法おすすめしたい。

sshd_config に自分のユーザーだけの設定を書く。

Match User takuya
       AuthorizedKeysFile .ssh/authorized_keys

Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

Match Group administrators の末尾をコメントアウトするか、Match User を作るかは趣味の問題だが、個人的にはデフォルト設定を生かした設定をしたほうがベターだと思う。

公開鍵認証について

WindowsのOpenSSHサーバーでも通常通り公開鍵認証ができます。

「公開鍵認証」とは、<秘密鍵と公開鍵のペア>を使います。

公開鍵をサーバーに登録しておけば、秘密鍵を持った人だけが、アクセスできます。一般的に使われるRSA公開鍵では、秘密鍵から公開鍵が導出されます。

公開鍵は「公開」するためのものです。誤解を恐れず、極めて短言で表現すれば、公開鍵の束(authorized_keys)は「印鑑証明」です。公開するものです。臆さず公開して構いません。

ハンコと捺印で例れば、印章が「秘密鍵」、印影が「公開鍵」です、ログインが「捺印・印鑑」です。( RSA鍵の署名と暗号化については、詳しくは、RSA公開鍵暗号方式ググること)

また、公開鍵暗号方式RSA公開鍵であるとは限らないのも注意。

WindowsSSHサーバの公開鍵設定でググったら、公開鍵と秘密鍵の違いすら分かってないようなブログ記事が散見され、ヤバさしかなかった。

公開鍵は「秘匿する」ものじゃないですからね。また id_rsa が公開鍵じゃないですからね。

Windowsな人たちは、なんで、id_rsa を公開キーとか書いちゃうんだろう。また公開鍵を秘密にしたがるんだろう。 なんで鍵ペアを知らないんだろう。

関連記事

SSHが鍵認証されないとき、パーミッションを疑え。 - それマグで!

右クリック禁止のサイトへ対策するシンプルな方法。

アフィサイトごときが、右クリック禁止をするなんておこがましい。

銀行サイトごときが、残高表示の金額を選択させないなんて、バカにしてんのか。

ドメイン購入サイトごときが、戻るだけで決済されてませんって、フザケンナと。

というわけで、一瞬にして対策できるシンプルなコードを

右クリック禁止の対応。

`
selectstart
contextmenu
dragstart
mousedown
copy
cut
paste
mousedown
mouseup
beforeunload
beforeprint
`.split(/\s/).filter(String).forEach((e, i) => {
  window["on"+e] &&(  window["on"+e] = null );
  document["on"+e] && (document["on"+e] = null);
  window.addEventListener(e, function(ev){ev.stopPropagation()}, true);  
});

Array.from(document.querySelectorAll('*')).filter( e => e.style.userSelect ).forEach(e => e.style.userSelect='auto')

UserJSなどに突っ込んでおけば、お手軽にいらっとすることがなくなる。

他人の記事をパクるサイトほど、右クリック禁止だし。

銀行が、残高表示させるくせに、残高をコピーできないとかさ。

ほんとうにWEBをなめてるよね。

拡張機能でもいいけど、iOS Safari でどうしようもないのは、本当に困りますね。

userSelectはメニューなどでテキスト選択が暴発すること防ぐためにあって、本文をコピーされないためではないですよね。

全角の英数を半角の英数に統一する(ただし、記号は除外)

全角を半角にする。

php で日本語の英数字(A-Z)を半角にしたいときは、文字コードのコードポイントを用いた計算ができる。

英数字だけを半角にしたいとき。

<?php
$v = 'Microso'
$v = preg_replace_callback('/[A-Za-z0-9]/u',function($s){
  $s = IntlChar::chr(IntlChar::ord($s[0]) - 0xFEE0);
  return $s;
},$v);

通常であれば mb_convert_kana

mb_convert_kana でもいいのだけれど、記号が変換されてしまう。

<?php
$v = 'Microso'
mb_convert_kana( $v , 'a')

ord ではなく、IntlChar::ordを使う理由

IntlChar::ord が必須。ord()はユニコード(utf8) の文字コードを計算できない。

配列の全てを半角にするには

filter_vars を使うと便利

<?php
 $arr_group =filter_var($section_group, FILTER_CALLBACK, ['options' => function ($v) {
                  $v = preg_replace_callback('/[A-Za-z0-9]/u',function($s){
                    $s = IntlChar::chr(IntlChar::ord($s[0]) - 0xFEE0);
                    return $s;
                  },$v);
                  return $v;
                }]);

全角半角の置換

全角半角の英数字の置き換えは、Unicode文字コードポイントをだして、 cp - 0xFEE0 をすればいい。これを覚えておけば、他のプログラム言語でも対応が可能になる。

参考資料