Bash
centos7
socat

socat を使った簡易プロキシと、自作シェルスクリプトの自動起動

自社のメールサーバを海外から使いたいが、自社の場合
海外 IP からの 587 番ポートの通信を許可しておらず SMTP 送信ができなかった、
そこで国内に別の Linux サーバを立てて、そこ経由で通信しようと企みました。

自身の IP アドレス以外から特定のサーバにアクセスする際の簡易プロキシとして
socat を試してみました。

自作スクリプトを systemctl enable する所まで記載してみます。
※ 本稿では SELinux やファイヤウォール設定などの記載を省略しています。

前提

アクセスしたいサーバ : example.co.jp
アクセスしたいポート : 587/tcp (SMTP Submittion) と 143/tcp (IMAP)
中継サーバで開放するポート(例) : 50587 と 50143

中継サーバには CentOS7 をインストールしました。

socat をインストール

$ sudo yum -y install socat

自作スクリプト置き場を作成する

$ sudo mkdir -p /opt/socat-proxy/{bin,lib}
$ sudo chmod 0755 /opt/socat-proxy/bin

起動スクリプトを作成する

本稿では User=root Group=root で起動していますが、
環境に応じて適切なユーザ権限でサービスを動かすべきと思います。

まずサーバの 50587 ポートと目的サーバの 587 ポートを繋ぐ socat を作成します。

$ sudo vi /opt/socat-proxy/bin/tcp-50587.sh
/opt/socat-proxy/bin/tcp-50587.sh
#!/bin/sh

/usr/bin/socat -d -d -lm tcp-l:50587,fork,setgid=root,setuid=root tcp:example.co.jp:587 </dev/null &

echo $! >/var/run/tcp-50587.pid

同様に 50143 ポートと目的サーバの 143 ポートを繋ぐ socat を作成します。

$ sudo vi /opt/socat-proxy/bin/tcp-50143.sh
/opt/socat-proxy/bin/tcp-50143.sh
#!/bin/sh

/usr/bin/socat -d -d -lm tcp-l:50143,fork,setgid=root,setuid=root tcp:example.co.jp:143 </dev/null &

echo $! >/var/run/tcp-50143.pid

起動スクリプトに実行権限を付与します。

$ sudo chmod 0755 /opt/socat-proxy/bin/tcp-50587.sh
$ sudo chmod 0755 /opt/socat-proxy/bin/tcp-50143.sh

ユニットファイルを用意する

まず 50587 ポート用ファイルを作成。

$ sudo vi /opt/socat-proxy/lib/tcp-50587.service
/opt/socat-proxy/lib/tcp-50587.service
[Unit]
Description = socat proxy tcp 50587
After=syslog.target network.target remote-fs.target nss-lookup.target
ConditionPathExists=/opt/socat-proxy/bin

[Service]
Type=forking
PIDFile=/var/run/tcp-50587.pid
ExecStart=/opt/socat-proxy/bin/tcp-50587.sh
ExecStop=/bin/kill -s QUIT $MAINPID

[Install]
WantedBy = multi-user.target

同様に 50143 ポート用ファイルも作成。

$ sudo vi /opt/socat-proxy/lib/tcp-50143.service
/opt/socat-proxy/lib/tcp-50143.service
[Unit]
Description = socat proxy tcp 50143
After=syslog.target network.target remote-fs.target nss-lookup.target
ConditionPathExists=/opt/socat-proxy/bin

[Service]
Type=forking
PIDFile=/var/run/tcp-50143.pid
ExecStart=/opt/socat-proxy/bin/tcp-50143.sh
ExecStop=/bin/kill -s QUIT $MAINPID

[Install]
WantedBy = multi-user.target

作成した 2 サービス分のファイルを /etc/systemd/system/ 配下にコピーします。

$ sudo cp /opt/socat-proxy/lib/tcp-50587.service /etc/systemd/system/tcp-50587.service
$ sudo cp /opt/socat-proxy/lib/tcp-50143.service /etc/systemd/system/tcp-50143.service

ユニットファイルを変更したあとは毎回 daemon-reload を唱えます。

$ sudo systemctl daemon-reload

サービスに含まれていることを確認します。

$ sudo systemctl list-unit-files --type=service | grep tcp-50
tcp-50143.service                             disabled
tcp-50587.service                             disabled

起動確認

ここで、もっとサービス名らしいサービス名にすればよかったと後悔。

$ sudo systemctl start tcp-50587
$ sudo systemctl start tcp-50143

サービスがポートを使用していることを確認します。

$ netstat -ltup4
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN      617/sshd            
tcp        0      0 0.0.0.0:50587           0.0.0.0:*               LISTEN      27009/socat         
tcp        0      0 0.0.0.0:50143           0.0.0.0:*               LISTEN      27018/socat         
$ sudo systemctl status tcp-50587
● tcp-50587.service - socat proxy tcp 50587
   Loaded: loaded (/etc/systemd/system/tcp-50587.service; disabled; vendor preset: disabled)
   Active: active (running) since Tue 2018-05-01 00:00:00 JST; 0min 01s ago
  Process: 27008 ExecStart=/opt/socat-proxy/bin/tcp-50587.sh (code=exited, status=0/SUCCESS)
 Main PID: 27009 (socat)
   CGroup: /system.slice/tcp-50587.service
           └─27009 /usr/bin/socat -d -d -lm tcp-l:50587,fork,setgid=root,setuid=root tcp:example.co.jp:587

 May 01 00:00:00 hostname systemd[1]: Starting socat proxy tcp 50587...
 May 01 00:00:00 hostname systemd[1]: Started socat proxy tcp 50587.
 May 01 00:00:00 hostname socat[27009]: N listening on AF=2 0.0.0.0:50587
$ sudo systemctl status tcp-50143
● tcp-50143.service - socat proxy tcp 50143
   Loaded: loaded (/etc/systemd/system/tcp-50143.service; disabled; vendor preset: disabled)
   Active: active (running) since Tue 2018-05-01 00:00:00 JST; 0min 01s ago
  Process: 27017 ExecStart=/opt/socat-proxy/bin/tcp-50143.sh (code=exited, status=0/SUCCESS)
 Main PID: 27018 (socat)
   CGroup: /system.slice/tcp-50143.service
           └─27018 /usr/bin/socat -d -d -lm tcp-l:50143,fork,setgid=root,setuid=root tcp:example.co.jp:143

 May 01 00:00:00 hostname systemd[1]: Starting socat proxy tcp 50143...
 May 01 00:00:00 hostname systemd[1]: Started socat proxy tcp 50143.
 May 01 00:00:00 hostname socat[27018]: N listening on AF=2 0.0.0.0:50143

メールソフトの SMTP 先を中継サーバの IP アドレス:ポート 50587 に変更。
メールソフトの IMAP 先を中継サーバの IP アドレス:ポート 50143 に変更。
メールサーバと透過的に通信できていることを確認します。

問題なければ enable して、サーバ再起動後に自動起動されることを確認します。

$ sudo systemctl enable tcp-50587
$ sudo systemctl enable tcp-50143

参考エントリ

Linux経由でリモートデスクトップ接続をフォワーディング
systemdで簡易中継サーバを作る
systemdを用いたプログラムの自動起動
Systemdを使ってさくっと自作コマンドをサービス化してみる