CentOS」カテゴリーアーカイブ

CentOS7 + nginx + phpMyAdmin

CentOS7にphpMyAdminをEPEL経由でインストールしてみた。

環境:
OS: CentOS 7.5
Webサーバ: nginx (EPELパッケージ)
PHP: php-fpm 5.4.16 (CentOS標準パッケージ)
DB: MariaDB 5.5.56 (CentOS標準パッケージ)

1. nginxインストール

EPELリポジトリを追加する(まだ追加していない場合)
$ sudo yum install epel-release

nginxをインストールする。
$ sudo yum install nginx
追加機能をコンパイルしたい場合は、SRPM を自前でリビルドしてもよい

あとは自分の用意したいWebサーバに合わせてバーチャルホスト設定ファイルを作成することになる。設定ファイルの中に、phpMyAdmin 用の記述を入れる。Apache 用の設定が /etc/httpd/conf.d/phpMyAdmin.conf にあるので、参考にする。

  root /usr/share/phpMyAdmin;
  ...
  location ~ ^/libraries/ { deny all; }
  location ~ ^/setup/lib/ { deny all; }
  location ~ ^/setup/frames/ { deny all; }
  location ~ ^/.*\.php$ {
    allow 203.0.113.100;		←自宅からのアクセス許可
    deny all;				←それ以外は全部拒否
    fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
    include fastcgi_params;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
    fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
  }
  location / {
    allow 203.0.113.100;
    deny all;
  }

$ sudo systemctl enable nginx
$ sudo systemctl start nginx

2. mariadb インストール・設定

$ sudo yum install mariadb mariadb-server
$ sudo systemctl enable mariadb
$ sudo systemctl start mariadb

rootパスワードの初期設定を行っておく。
$ mysql_secure_installation

3. phpインストール・設定

必要そうなパッケージをまとめてインストールしておく。
$ sudo yum install php-fpm php-mysql php-gd php-mbstring

phpの基本設定を行う。
$ sudo vi /etc/php.ini

expose_php = Off			←PHPの情報を隠す

ほかにもパフォーマンスチューニングのパラメータがphp.iniの中にあるので、必要に応じて変更しておく。

php-fpmとして動作するときの設定を行う。
$ sudo vi /etc/php-fpm.d/www.conf

listen = /run/php-fpm/php-fpm.sock	←UNIXソケットを利用
listen.owner = nginx			←UNIXソケットの所有者をnginx実行ユーザにする
listen.group = nginx
listen.mode = 0600			←nginx以外からソケットを利用できないようにする
user = nginx				←php-fpm実行ユーザをnginxにそろえておく
group = nginx

php-fpmデーモンを起動する。
$ sudo systemctl enable php-fpm
$ sudo systemctl start php-fpm

3. phpMyAdminインストール・設定

phpMyAdminをインストールする。
$ sudo yum install phpMyAdmin

必要なディレクトリの作成、nginxから読めるよう権限の修正を行う。
$ sudo mkdir -p /var/lib/php/session
$ sudo chown nginx:nginx /var/lib/php/session
$ sudo chgrp -R nginx /etc/phpMyAdmin
$ sudo chown -R nginx:nginx /var/lib/phpMyAdmin

phpMyAdminに必要なDB・テーブルの作成を行う。
$ mysql -u root -p
Enter password:
MariaDB [(none)]> source /usr/share/phpMyAdmin/sql/create_tables.sql;
MariaDB [(none)]> \q

あとはWebブラウザで http://自分のサーバ/phpMyAdmin/ にアクセスし、動作確認を行う。

Linux 同士の IPv6 IPsec 接続

個人的なことだが、自宅のフレッツ回線とプロバイダがIPv6ネイティブ方式 (IPoE) に対応したため、自宅内のノードに IPv6 グローバルアドレスを割り当てられるようになった。

これを利用して、自分で借りた「さくらの VPS」(こちらも IPv6 グローバルアドレスが付与される)と自宅内サーバの間に IPv6 IPsecトンネルを作成してみる。

前提環境:
・自宅サーバ: Raspbian 9.4 + strongswan
・VPS: CentOS 7.5 + strongswan
・認証方式: X.509 証明書

ネットワーク構成図

1. 証明書の作成

myserver1 上に CA のためのディレクトリと設定を準備する。
user@myserver1:~$ sudo mkdir /etc/ssl/CA
user@myserver1:~$ sudo mkdir /etc/ssl/newcerts
user@myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/serial"
user@myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/crlnumber"
user@myserver1:~$ sudo touch /etc/ssl/CA/index.txt
user@myserver1:~$ sudo vi /etc/ssl/openssl.cnf

/etc/ssl/openssl.cnfの抜粋:

dir		= /etc/ssl		# Where everything is kept
database	= $dir/CA/index.txt	# database index file.
certificate	= $dir/certs/ca1.crt 	# The CA certificate
serial		= $dir/CA/serial 		# The current serial number
crlnumber	= $dir/CA/crlnumber # the current crl number
                    # must be commented out to leave a V1 CRL
crl     = $dir/crl/crl.pem
private_key	= $dir/private/ca1.key

CA 鍵・証明書を作成する。
user@myserver1:~$ sudo openssl req -new -x509 -extensions v3_ca -keyout /etc/ssl/private/ca1.key -out /etc/ssl/certs/ca1.crt -days 3652
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Nagoya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
Organizational Unit Name (eg, section) []:CA
Common Name (e.g. server FQDN or YOUR name) []:ca1.home.example.com
Email Address []:

myserver1 の秘密鍵を作成する。
user@myserver1:~$ openssl genrsa -aes256 -out /etc/ssl/private/myserver1.key 2048
Enter pass phrase for myserver1.key:********
(後でパスワードを削除するので、パスワードはここでは適当に決める)
Verifying - Enter pass phrase for myserver1.key:********

秘密鍵ファイルのパスワードを削除しておく。
user@myserver1:~$ openssl rsa -in /etc/ssl/private/myserver1.key -out /etc/ssl/private/myserver1.key
Enter pass phrase for myserver1.key:********
writing RSA key

myserver1 の CSR を作成する。
user@myserver1:~$ openssl req -new -days 1826 -key /etc/ssl/private/myserver1.key -out /etc/ssl/cert/myserver1.csr
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Nagoya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
Organizational Unit Name (eg, section) []:Server
Common Name (e.g. server FQDN or YOUR name) []:myserver1.home.example.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

CA 鍵を使って CSR に署名する。
user@myserver1:~$ sudo openssl ca -in /etc/ssl/cert/myserver1.csr -config /etc/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/private/ca.key:********
(snip)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
(snip)
Data Base Updated

CA 証明書とホスト証明書・鍵を strongswan 用に配置する。
user@myserver1:~$ sudo cp /etc/ssl/certs/ca1.crt /etc/ipsec.d/cacerts/
user@myserver1:~$ sudo cp /etc/ssl/newcerts/01.pem /etc/ipsec.d/certs/myserver1.crt
user@myserver1:~$ sudo cp /etc/ssl/private/myserver1.key /etc/ipsec.d/private/

myvps1 用の証明書も同様に作成する。
user@myserver1:~$ openssl genrsa -aes256 -out /etc/ssl/private/myvps1.key 2048
user@myserver1:~$ openssl rsa -in /etc/ssl/private/myvps1.key -out /etc/ssl/private/myvps1.key
user@myserver1:~$ openssl req -new -days 1826 -key /etc/ssl/private/myvps1.key -out /etc/ssl/cert/myvps1.csr
user@myserver1:~$ sudo openssl ca -in /etc/ssl/cert/myvps1.csr -config /etc/ssl/openssl.cnf

いま作成した myvps1 用のホスト証明書・鍵、CA証明書を myvps1 側にコピーする。
user@myserver1:~$ cp /etc/ssl/certs/ca1.crt .
user@myserver1:~$ cp /etc/ssl/newcerts/02.pem ./myvps1.crt
user@myserver1:~$ sudo cp /etc/ssl/private/myvps1.key .
user@myserver1:~$ sudo chown user myvps1.key
user@myserver1:~$ scp ca1.crt myvps1.crt myvps1.key myvps1:

myvps1 上で証明書・鍵を配置する。
[user@myvps1 ~]$ sudo cp ca1.crt /etc/strongswan/ipsec.d/cacerts/
[user@myvps1 ~]$ sudo cp myvps1.crt /etc/strongswan/ipsec.d/certs/
[user@myvps1 ~]$ sudo cp myvps1.key /etc/strongswan/ipsec.d/private/

作業用ファイルを削除する。
[user@myvps1 ~]$ rm ca1.crt myvps1.crt myvps1.key
user@myserver1:~$ rm ca1.crt myvps1.crt myvps1.key

2. VPS 側の IPsec 設定

strongswan をインストールする。
[user@myvps1 ~]$ sudo yum install epel-release
[user@myvps1 ~]$ sudo yum install strongswan

カーネルモジュールをロードする。
strongswan公式ドキュメントを参照して、必要なモジュールがロードされていない場合は手動でロードする。
[user@myvps1 ~]$ sudo modprobe xfrm6_tunnel

設定ファイルを編集する。
[user@myvps1 ~]$ vi /etc/strongswan/ipsec.conf

conn myhome-to-vps6
        authby=rsasig
        auto=add
        closeaction=clear
        dpdaction=clear
        leftid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myvps1.example.com"
        leftsubnet=2001:db8:abcd:efab:cdef:abcd:efab:cdef/128
        leftcert=myvps1.crt
        right=%any
        rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myserver1.home.example.com"
        rightsubnet=2001:db8:1234:5678::/64
        ike=aes256-sha512-modp8192!
        esp=aes256-sha512

[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.secrets

: RSA myvps1.key

strongswanサービス起動
[user@myvps1 ~]$ sudo systemctl enable strongswan
[user@myvps1 ~]$ sudo systemctl start strongswan

3. 自宅内サーバ側の設定

strongswanをインストールする。こちらは Raspbian なので apt コマンドで。
user@myserver1:~$ sudo apt install strongswan

必要なカーネルモジュールをロードする。
user@myserver1:~$ sudo modprobe xfrm6_tunnel
user@myserver1:~$ sudo modprobe esp6

設定ファイルを編集する。
user@myserver1:~$ sudo vi /etc/ipsec.conf

conn myhome-to-vps6
        authby=rsasig
        auto=start
        closeaction=restart
        dpdaction=restart
        leftid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myserver1.home.example.com"
        leftsubnet=2001:db8:1234:5678::/64
        leftcert=myserver1.crt
        right=2001:db8:abcd:efab:cdef:abcd:efab:cdef
        rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myvps1.example.com"
        rightsubnet=2001:db8:abcd:efab:cdef:abcd:efab:cdef/128
        ike=aes256-sha512-modp8192!
        esp=aes256-sha512

user@myserver1:~$ sudo vi /etc/ipsec.secrets

: RSA myserver1.key

strongswanサービスを起動する。
user@myserver1:~$ sudo systemctl enable strongswan
user@myserver1:~$ sudo systemctl start strongswan

nginx のモジュール追加リビルド (CentOS 7 EPEL 版)

nginx 公式や epel パッケージの nginx バイナリでは使いたいモジュールがコンパイルされていない。特に nginx-dav-ext-module(WebDAV で OPTIONS メソッドが利用可能になる)、headers-more-nginx-module(HTTPヘッダを追加したり削除したり)、nginx-ct(証明書の透明性対応ができる)を使いたいので、ソースからビルドすることにする。

前提として、使用 OS は CentOS 7 である。

nginx 公式の RPM パッケージもあるが、この記事では epel リポジトリの nginx RPM をベースに、必要なモジュールの記述を追加して SRPM からリビルドしてみる。

1. コンパイルに必要なパッケージをインストール

$ sudo yum install gperftools-devel openssl-devel pcre-devel zlib-devel GeoIP-devel gd-devel perl-devel perl-ExtUtils-Embed libxslt-devel expat-devel git

2. epel リポジトリを追加

epel リポジトリを追加する。追加済みであれば作業の必要なし。
$ sudo yum install epel-release

3. SRPM の入手

SRPM をダウンロード・インストールする。
$ sudo yum install -y yum-utils
$ sudo yum-config-manager --enable epel-testing
$ sudo yum install @buildsys-build
$ yumdownloader --source nginx
$ rpm -ivh nginx-1.20.1-9.el7.src.rpm

今後 yum update で勝手にアップデートされないように、epel レポジトリを無効化しておく。
$ sudo yum-config-manager --disable epel\*

4. カスタマイズ

SRPM の spec ファイルを編集する。
$ vi rpmbuild/SPECS/nginx.spec

以下、nginx.spec に追加する部分を diff -u 形式で記述する。追加する3つのモジュールのうち、nginx-ct は元々 nginx に含まれていて動的モジュール化されている mod-mail と mod-stream に依存するため、これも動的モジュール化する(そうしないとビルドエラーになる)。

--- nginx.spec.orig 2021-10-19 08:55:50.000000000 +0900
+++ nginx.spec 2022-04-28 09:38:22.327765589 +0900
@@ -92,6 +92,8 @@
%endif
BuildRequires: pcre-devel
BuildRequires: zlib-devel
+BuildRequires: expat-devel
+BuildRequires: git

Requires: nginx-filesystem = %{epoch}:%{version}-%{release}
%if 0%{?el7}
@@ -107,6 +109,7 @@

Requires: openssl
Requires: pcre
+Requires: expat
Requires(pre): nginx-filesystem
%if 0%{?with_mailcap_mimetypes}
Requires: nginx-mimetypes
@@ -140,6 +143,7 @@
Requires: nginx-mod-http-xslt-filter = %{epoch}:%{version}-%{release}
Requires: nginx-mod-mail = %{epoch}:%{version}-%{release}
Requires: nginx-mod-stream = %{epoch}:%{version}-%{release}
+Requires: nginx-mod-ct = %{epoch}:%{version}-%{release}

%description all-modules
Meta package that installs all available nginx modules.
@@ -236,12 +240,22 @@
%description mod-devel
%{summary}.

+%package mod-ct
+Summary: Nginx ct modules
+Requires: nginx
+
+%description mod-ct
+%{summary}.
+

%prep
# Combine all keys from upstream into one file
cat %{S:2} %{S:3} %{S:4} > %{_builddir}/%{name}.gpg
%{gpgverify} --keyring='%{_builddir}/%{name}.gpg' --signature='%{SOURCE1}' --data='%{SOURCE0}'
%autosetup -p1
+git clone https://github.com/arut/nginx-dav-ext-module.git
+git clone https://github.com/openresty/headers-more-nginx-module.git
+git clone https://github.com/grahamedgecombe/nginx-ct.git
cp %{SOURCE200} %{SOURCE210} %{SOURCE10} %{SOURCE12} .

%if 0%{?rhel} > 0 && 0%{?rhel} < 8
@@ -322,6 +336,9 @@
--with-stream=dynamic \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
+ --add-module=./nginx-dav-ext-module \
+ --add-module=./headers-more-nginx-module \
+ --add-dynamic-module=./nginx-ct \
--with-threads \
--with-cc-opt="%{optflags} $(pcre-config --cflags)" \
--with-ld-opt="$nginx_ldopts"; then
@@ -421,6 +438,14 @@
> %{buildroot}%{nginx_moduleconfdir}/mod-mail.conf
echo 'load_module "%{nginx_moduledir}/ngx_stream_module.so";' \
> %{buildroot}%{nginx_moduleconfdir}/mod-stream.conf
+echo 'load_module "%{_libdir}/nginx/modules/ngx_ssl_ct_module.so";' \
+ > %{buildroot}%{_datadir}/nginx/modules/mod-ct.conf
+echo 'load_module "%{_libdir}/nginx/modules/ngx_http_ssl_ct_module.so";' \
+ > %{buildroot}%{_datadir}/nginx/modules/mod-http-ct.conf
+echo 'load_module "%{_libdir}/nginx/modules/ngx_mail_ssl_ct_module.so";' \
+ > %{buildroot}%{_datadir}/nginx/modules/mod-mail_ct.conf
+echo 'load_module "%{_libdir}/nginx/modules/ngx_stream_ssl_ct_module.so";' \
+ > %{buildroot}%{_datadir}/nginx/modules/mod-stream_ct.conf

# Install files for supporting nginx module builds
## Install source files
@@ -479,6 +504,11 @@
/usr/bin/systemctl reload nginx.service >/dev/null 2>&1 || :
fi

+%post mod-ct
+if [ $1 -eq 1 ]; then
+ /usr/bin/systemctl reload nginx.service >/dev/null 2>&1 || :
+fi
+
%preun
%systemd_preun nginx.service

@@ -576,6 +606,16 @@
%{_fileattrsdir}/nginxmods.attr
%{nginx_srcdir}/

+%files mod-ct
+%{_datadir}/nginx/modules/mod-ct.conf
+%{_datadir}/nginx/modules/mod-http-ct.conf
+%{_datadir}/nginx/modules/mod-mail_ct.conf
+%{_datadir}/nginx/modules/mod-stream_ct.conf
+%{_libdir}/nginx/modules/ngx_http_ssl_ct_module.so
+%{_libdir}/nginx/modules/ngx_mail_ssl_ct_module.so
+%{_libdir}/nginx/modules/ngx_ssl_ct_module.so
+%{_libdir}/nginx/modules/ngx_stream_ssl_ct_module.so
+

%changelog
* Mon Oct 18 2021 Felix Kaechele <heffer@fedoraproject.org> - 1:1.20.1-9

5. ビルド、インストール

ビルドを実行する。
$ rpmbuild --with geoip -ba rpmbuild/SPECS/nginx.spec

RPM が出来上がったらインストールする。すでに EPEL や nginx 公式 RPM をインストールしてしまっている場合は、先に削除しておくこと。

既存パッケージの削除:
$ sudo yum erase `rpm -qa | grep nginx`

カスタマイズした RPM のインストール:
$ sudo yum localinstall rpmbuild/RPMS/x86_64/nginx-1.*.rpm rpmbuild/RPMS/x86_64/nginx-mod-*.rpm rpmbuild/RPMS/noarch/nginx-*.rpm

6. 起動

デーモンを起動する。
$ sudo systemctl enable nginx
$ sudo systemctl start nginx

DNSSEC ルートゾーン KSK ロールオーバーについて

DNSSECのルートゾーンKSKロールオーバーについて、ロールオーバー前後でDNSの検索に支障が出ないよう、各所から通達が出ている。

ルートゾーンKSKロールオーバーによる影響とその確認方法について (JPRS)
KSKロールオーバーについて (JPNIC)

(2017/10月予定だった切り替えが延期され、現在は 2018/10/11 に予定されています)

1. 管理下の DNS キャッシュは DNSSEC 検証をしているか

DNS キャッシュサーバーを管理している場合は、一応気を付けたほうが良い。管理下の DNS キャッシュサーバーに対して、dig コマンドでDNSSEC 対応済みドメイン (例: jprs.jp) の情報を検索したときに、回答に ad フラグが付いていたら「キャッシュサーバーでDNSSEC署名検証が有効になっている」状態なので、更新後の鍵を設定してやる必要があるかもしれない。

adフラグが付いている例:

$ dig jprs.jp. @mydns.example.com

; <<>> DiG 9.10.3-P4-Ubuntu <<>> jprs.jp.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26772
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 9
...

(参考: DNSSECチュートリアル~実践編~)

2. RHEL 7 / CentOS 7 + BIND の場合

named.confにデフォルトで以下の設定が入っていて、DNSSEC署名検証が有効になっている。

options {
...
        dnssec-enable yes;
        dnssec-validation yes;

        /* Path to ISC DLV key */
        bindkeys-file "/etc/named.iscdlv.key";

        managed-keys-directory "/var/named/dynamic";
...
};
...
include "/etc/named.root.key";

対処法1. パッケージアップデート

/etc/named.iscdlv.key と /etc/named.root.key に、ルートゾーンの鍵が入っている。パッケージバージョンがbind-9.9.4-38.4以降であれば、上記2ファイルに新しい鍵が追加されるので、bindのパッケージをアップデートしてしまうのが一番手っ取り早く安心できる方法ではある。

対処法2. 自動更新に任せる

9.9.4-38.3以前のパッケージを使っている場合でも、RFC5011 の自動更新に対応している。named を起動すると更新後の鍵は /var/named/dynamic/managed-keys.bind{,.jnl} として自動保存される。このため、特に何かをする必要はない。

# とはいえ、CVE-2017-3142、CVE-2017-3143への対処が9.9.4-38.5以降で行われているので、パッケージを更新した方が良い。

3. RHEL 7 / CentOS 7 + Unbound の場合

デフォルトの /var/lib/unbound/root.key には古い鍵しか入っていないが、/etc/unbound/unbound.conf に以下の記述があり、自動更新が有効になっている。

server:
...
        auto-trust-anchor-file: "/var/lib/unbound/root.key"
...

unbound のデーモンを起動すると、/var/lib/unbound/root.key に新しい鍵が追加される。

このため、これらの設定を変更していなければ、特に対処の必要はない。

4. 確認、その他

EDNS0を無効化していないこと、経路上でTCP53が通ること、フラグメントパケットが通ることも確認しておく。

大きなサイズの DNS 応答に対応できているかどうかは、DNS-OARCが確認用のレコードを用意してくれているので、以下の dig コマンドで確認できる。

$ dig +bufsize=4096 +short rs.dns-oarc.net txt

非対応のキャッシュサーバだと、以下のような回答が返ってくる。

rst.x476.rs.dns-oarc.net.
rst.x485.x476.rs.dns-oarc.net.
rst.x490.x485.x476.rs.dns-oarc.net.
"203.0.113.1 DNS reply size limit is at least 490"
"203.0.113.1 lacks EDNS, defaults to 512"
"Tested at 2017-08-31 01:19:47 UTC"

HTTP/2 (ALPN) 対応の nginx を SRPM からビルド

※以下はCentOS 7.3までの古い内容です。CentOS 7.4 では OpenSSL 1.0.2 が標準となったため、以下の作業は不要です。

CentOS7.3 に含まれる標準パッケージの OpenSSL が 1.0.1 系なので、それをリンクしてビルドした nginx 公式のバイナリでは HTTP/2 (ALPN) が利用できない。そこで、openssl-1.0.2 系のソースツリーを使って nginx 公式の SRPM をリビルドすることとする。

ついでに、geoipモジュールとdav_extモジュールも使いたいので、追加した上でビルドする。

1. コンパイルに必要なパッケージをインストール

$ sudo yum install expat-devel pcre-devel zlib-devel GeoIP-devel

2. nginxの公式レポジトリを追加

レポジトリファイルを作成する。
$ sudo vi /etc/yum.repos.d/nginx.repo

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

[nginx-source]
name=nginx repo - Source
baseurl=http://nginx.org/packages/centos/$releasever/SRPMS/
gpgcheck=0
enabled=1

3. ダウンロード

SRPMをダウンロード・インストールする。
$ sudo yum install -y yum-utils
$ yumdownloader --source nginx
$ rpm -ivh --nosignature nginx-1.12.1-1.el7.ngx.src.rpm

今後yum updateで勝手にアップデートされないように、nginxレポジトリを無効化しておく。
$ sudo yum-config-manager --disable nginx
$ sudo yum-config-manager --disable nginx-source

OpenSSL 1.0.2 のソースをダウンロードして展開する。
$ cd /tmp
$ wget https://www.openssl.org/source/openssl-1.0.2l.tar.gz
$ tar xzf openssl-1.0.2l.tar.gz
$ cd ~

OpenSSL のビルドはしなくてよい。

4. カスタマイズ

SRPM の spec ファイルを編集する。
$ vi rpmbuild/SPECS/nginx.spec

青字の部分は追加、赤字で打消し線のところは削除する。

#
%define nginx_home %{_localstatedir}/cache/nginx
%define nginx_user nginx
%define nginx_group nginx
%define nginx_loggroup adm

# distribution specific definitions
%define use_systemd (0%{?fedora} && 0%{?fedora} >= 18) || (0%{?rhel} && 0%{?rhel
} >= 7) || (0%{?suse_version} == 1315)

%if 0%{?rhel} == 5
%define _group System Environment/Daemons
Requires(pre): shadow-utils
Requires: initscripts >= 8.36
Requires(post): chkconfig
Requires: openssl
BuildRequires: openssl-devel
%endif

%if 0%{?rhel} == 6
%define _group System Environment/Daemons
Requires(pre): shadow-utils
Requires: initscripts >= 8.36
Requires(post): chkconfig
Requires: openssl >= 1.0.1
BuildRequires: openssl-devel >= 1.0.1
%endif

%if 0%{?rhel} == 7
%define _group System Environment/Daemons
%define epoch 1
Epoch: %{epoch}
Requires(pre): shadow-utils
Requires: systemd
Requires: openssl >= 1.0.1
BuildRequires: systemd
BuildRequires: openssl-devel >= 1.0.1
BuildRequires: GeoIP-devel
BuildRequires: expat-devel
%endif

%if 0%{?suse_version} == 1315
%define _group Productivity/Networking/Web/Servers
%define nginx_loggroup trusted
Requires(pre): shadow
Requires: systemd
BuildRequires: libopenssl-devel
BuildRequires: systemd
%endif

# end of distribution specific definitions

%define main_version 1.12.1
%define main_release 1%{?dist}.ngx

%define bdir %{_builddir}/%{name}-%{main_version}

%define WITH_CC_OPT $(echo %{optflags} $(pcre-config --cflags)) -fPIC
%define WITH_LD_OPT -Wl,-z,relro -Wl,-z,now -pie
%define BASE_CONFIGURE_ARGS $(echo "--prefix=%{_sysconfdir}/nginx --sbin-path=%{
_sbindir}/nginx --modules-path=%{_libdir}/nginx/modules --conf-path=%{_sysconfdi
r}/nginx/nginx.conf --error-log-path=%{_localstatedir}/log/nginx/error.log --htt
p-log-path=%{_localstatedir}/log/nginx/access.log --pid-path=%{_localstatedir}/r
un/nginx.pid --lock-path=%{_localstatedir}/run/nginx.lock --http-client-body-tem
p-path=%{_localstatedir}/cache/nginx/client_temp --http-proxy-temp-path=%{_local
statedir}/cache/nginx/proxy_temp --http-fastcgi-temp-path=%{_localstatedir}/cach
e/nginx/fastcgi_temp --http-uwsgi-temp-path=%{_localstatedir}/cache/nginx/uwsgi_
temp --http-scgi-temp-path=%{_localstatedir}/cache/nginx/scgi_temp --user=%{ngin
x_user} --group=%{nginx_group} --with-compat --with-file-aio --with-threads --wi
th-http_addition_module --with-http_auth_request_module --with-http_dav_module -
-with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module -
-with-http_mp4_module --with-http_random_index_module --with-http_realip_module 
--with-http_secure_link_module --with-http_slice_module --with-http_ssl_module -
-with-http_stub_status_module --with-http_sub_module --with-http_v2_module --wit
h-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-s
tream_ssl_module --with-stream_ssl_preread_module --with-http_geoip_module --add
-module=./nginx-dav-ext-module --with-openssl=/tmp/openssl-1.0.2l")

Summary: High performance web server
Name: nginx
Version: %{main_version}
Release: %{main_release}
Vendor: Nginx, Inc.
URL: http://nginx.org/
Group: %{_group}

Source0: http://nginx.org/download/%{name}-%{version}.tar.gz
Source1: logrotate
Source2: nginx.init.in
Source3: nginx.sysconf
Source4: nginx.conf
Source5: nginx.vh.default.conf
Source7: nginx-debug.sysconf
Source8: nginx.service
Source9: nginx.upgrade.sh
Source10: nginx.suse.logrotate
Source11: nginx-debug.service
Source12: COPYRIGHT
Source13: nginx.check-reload.sh

License: 2-clause BSD-like license

BuildRoot: %{_tmppath}/%{name}-%{main_version}-%{main_release}-root
BuildRequires: zlib-devel
BuildRequires: pcre-devel

Provides: webserver

%description
nginx [engine x] is an HTTP and reverse proxy server, as well as
a mail proxy server.

%if 0%{?suse_version} == 1315
%debug_package
%endif

%prep
%setup -q
cp %{SOURCE2} .
sed -e 's|%%DEFAULTSTART%%|2 3 4 5|g' -e 's|%%DEFAULTSTOP%%|0 1 6|g' \
    -e 's|%%PROVIDES%%|nginx|g' < %{SOURCE2} > nginx.init
sed -e 's|%%DEFAULTSTART%%||g' -e 's|%%DEFAULTSTOP%%|0 1 2 3 4 5 6|g' \
    -e 's|%%PROVIDES%%|nginx-debug|g' < %{SOURCE2} > nginx-debug.init
git clone https://github.com/arut/nginx-dav-ext-module.git

%build
./configure %{BASE_CONFIGURE_ARGS} \
    --with-cc-opt="%{WITH_CC_OPT}" \
    --with-ld-opt="%{WITH_LD_OPT}" \
    --with-debug --with-openssl-opt="-fPIC"
make %{?_smp_mflags}
%{__mv} %{bdir}/objs/nginx \
    %{bdir}/objs/nginx-debug
./configure %{BASE_CONFIGURE_ARGS} \
    --with-cc-opt="%{WITH_CC_OPT}" \
    --with-ld-opt="%{WITH_LD_OPT}" --with-openssl-opt="-fPIC"
make %{?_smp_mflags}

(以下略)

5. ビルド、インストール

ビルドを実行する。
$ rpmbuild -ba rpmbuild/SPECS/nginx.spec

出来上がったら、RPMをインストールする。
$ sudo yum localinstall rpmbuild/RPMS/x86_64/nginx-1.12.1-1.el7.centos.ngx.x86_64.rpm

展開した openssl ソースを掃除しておく。
$ rm -r /tmp/openssl-1.0.2l

6. 起動

デーモンを起動する。
$ sudo systemctl enable nginx
$ sudo systemctl start nginx

参考URL:
HTTP/2対応nginxのrpmパッケージ作成とインストール

CentOS7でmastodon自分インスタンスを立てる

VPS上に自分用のインスタンスを立ててみた。

1. dockerインストール

dockerをパッケージでインストールする。レポジトリとしては、dockerの公式を使う。
$ sudo yum install yum-utils
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum-config-manager --disable docker-ce-edge
$ sudo yum-config-manager --disable docker-ce-stable

docker-ce-edgeレポジトリで最新のバージョン名を取得してインストールする。
$ yum --enablerepo=docker-ce-edge list docker-ce.x86_64 --showduplicates | sort -r
docker-ce.x86_64 17.05.0.ce-1.el7.centos docker-ce-edge
docker-ce.x86_64 17.04.0.ce-1.el7.centos docker-ce-edge
$ sudo yum --enablerepo=docker-ce-edge install docker-ce-17.05.0.ce-1.el7.centos

dockerデーモンを起動する。
$ sudo systemctl enable docker
$ sudo systemctl start docker

docker-composeをgithubからダウンロードして/usr/bin以下に配置する。
$ sudo -i
# curl -L https://github.com/docker/compose/releases/download/1.12.0/docker-compose-`uname -s`-`uname -m` > /usr/bin/docker-compose
# chmod +x /usr/bin/docker-compose
$ exit

2. mastodon

mastodonのソースツリーを用意する。

最初に、mastodon用の作業用一般ユーザを追加する。
$ sudo useradd mastodon
$ sudo passwd mastodon
$ sudo usermod -aG docker mastodon

mastodonのソースツリーを/home/mastodon/liveに展開する。これ以降はmastodonユーザで作業する。
$ sudo -i -u mastodon
$ git clone https://github.com/tootsuite/mastodon.git live
$ cd live
$ git tag
バージョンタグの一覧が表示されるので、最新のリリースタグを選ぶ。
$ git checkout v1.3.3

ソースツリーに付属している、dockerコンテナの設定ファイル docker-compose.yml を編集する。
$ vi docker-compose.yml

version: '2'
services:

  db:
    restart: always
    image: postgres:alpine
### Uncomment to enable DB persistance
    volumes: ←ここの行頭コメント記号を外す
      - ./postgres:/var/lib/postgresql/data ←ここの行頭コメント記号を外す

  redis:
    restart: always
    image: redis:alpine
### Uncomment to enable REDIS persistance
    volumes: ←ここの行頭コメント記号を外す
      - ./redis:/data ←ここの行頭コメント記号を外す

  web:
    restart: always
    build: .
    image: gargron/mastodon
    env_file: .env.production
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    ports:
      - "3000:3000"
    links: ←depends_onをlinksに変更する
      - db
      - redis
    volumes:
      - ./public/assets:/mastodon/public/assets
      - ./public/system:/mastodon/public/system

  streaming:
    restart: always
    build: .
    image: gargron/mastodon
    env_file: .env.production
    command: npm run start
    ports:
      - "4000:4000"
    links: ←depends_onをlinksに変更する
      - db
      - redis

  sidekiq:
    restart: always
    build: .
    image: gargron/mastodon
    env_file: .env.production
    command: bundle exec sidekiq -q default -q mailers -q pull -q push
    links: ←depends_onをlinksに変更する
      - db
      - redis
    volumes:
      - ./public/system:/mastodon/public/system

次に、.env.productionを編集する。
$ cp -p .env.production.sample .env.production
$ vi .env.production

以下のような行を編集する。

DB_USER=mastodon ←この後PostgreSQLで設定する
DB_NAME=mastodon ←同上
DB_PASS=password ←同上
LOCAL_DOMAIN=mastodon.example.com ←mastodonサーバのFQDN
SMTP_SERVER=mail.example.com ←メールサーバのホスト名
SMTP_PORT=587 ←メールサーバのポート SMTP AUTHが使えるポートを指定
SMTP_LOGIN=mastodon ←SMTP AUTHのユーザ名
SMTP_PASSWORD=password ←SMTP AUTHのパスワード
SMTP_FROM_ADDRESS=postmaster@example.com

dockerコンテナをダウンロードし、ビルドする。ここは時間がかかる。
$ docker-compose build

次に、同じコマンドを3回実行してキーを作成する。
$ docker-compose run --rm web rake secret
3d3748d778c215f269c18c4c46dc2fb94da50ec569b2bc0c593353b5f54f2f4b6e4307978bc0304042f8d086716f1896046751d4b0fc8b9420a79c33454caa81
$ docker-compose run --rm web rake secret
5377ae140e0c1eaf857b5423067c4295029c9cdb23feefa9f382c7aa94753f224ed097834f15447c419d31065ce0dc816ef6efeec594de8996b776910b2e3326
$ docker-compose run --rm web rake secret
772fab57e3e71fa6c57f14e8ab42e986daf0aaf67a1ebe469d04fc3187f989ec77bd8bebdc08b62c4a456e8851755140000286c8babc1b8e4c9203782aadd6f2

出力された鍵文字列を、.env.production設定ファイルに記述する。
$ vi .env.production

PAPERCLIP_SECRET=3d3748d778c215f269c18c4c46dc2fb94da50ec569b2bc0c593353b5f54f2f4b6e4307978bc0304042f8d086716f1896046751d4b0fc8b9420a79c33454caa81
SECRET_KEY_BASE=5377ae140e0c1eaf857b5423067c4295029c9cdb23feefa9f382c7aa94753f224ed097834f15447c419d31065ce0dc816ef6efeec594de8996b776910b2e3326
OTP_SECRET=772fab57e3e71fa6c57f14e8ab42e986daf0aaf67a1ebe469d04fc3187f989ec77bd8bebdc08b62c4a456e8851755140000286c8babc1b8e4c9203782aadd6f2

コンテナを起動する。
$ docker-compose up -d

dbコンテナ内のPostgreSQLに、ユーザとデータベースを作成する。
$ docker exec -it live_db_1 bash
# su - postgres
43e296a2871c:~$ createuser -P mastodon
Enter password for new role: password
Enter it again: password
43e296a2871c:~$ createdb mastodon -O mastodon
43e296a2871c:~$ exit
# exit

dbコンテナの変更部分をアップデートする。また、assetsファイル(静的コンテンツ)を生成する。
$ docker-compose run --rm web rails db:migrate
$ docker-compose run --rm web rails assets:precompile

いったんコンテナを再起動する。
$ docker-compose stop
$ docker-compose up -d

3. certbot (letsencrypt)

Let’s EncryptプロジェクトCAに、証明書を発行してもらう。

certbotソースツリーを、/opt以下に展開してcertbot-autoを実行する。
$ sudo -i
# cd /opt
# chgrp wheel .
# chmod g+w .
# exit
$ cd /opt
$ git clone https://github.com/certbot/certbot
$ cd certbot
$ ./certbot-auto certonly -n --standalone --agree-tos -m 管理者メールアドレス -d www.example.com,mail.example.com,mastodon.example.com

今回は直接関係ないが、-dオプションで SubjectAltNameを指定することで、他のバーチャルホストと証明書を共用する。

4. nginx のインストールと設定

nginxはpuma+railsのリバースプロキシ兼、静的コンテンツを自前で返すWebサーバとなる。

nginx のインストール用 repo を追加する。
$ sudo vi /etc/yum.repos.d/nginx.repo

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=0

nginxをインストールする。
$ sudo yum --enablerepo=nginx install nginx

nginxの設定
$ sudo vi /etc/nginx/conf.d/mastodon.conf

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  listen 80;
  listen [::]:80;
  server_name mastodon.example.com;
  location / { return 301 https://$host$request_uri; }
}

server {
  listen 443 ssl;
  listen [::]:443 ssl;
  server_name mastodon.example.com;

  ssl_protocols TLSv1.2;
  ssl_ciphers EECDH+AESGCM:EECDH+AES;
  ssl_ecdh_curve prime256v1;
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;

  ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  ssl_dhparam         /etc/pki/tls/dhparam.pem;

  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 0;

  root /home/mastodon/live/public;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  add_header Strict-Transport-Security "max-age=31536000";

  location / {
    try_files $uri @proxy;
  }

  location /assets {
    add_header Cache-Control "public, max-age=31536000, immutable";
  }

  location @proxy {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";
    proxy_pass_header Server;

    proxy_pass http://127.0.0.1:3000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  location /api/v1/streaming {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";

    proxy_pass http://localhost:4000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  error_page 500 501 502 503 504 /500.html;
}

nginxを起動する。
$ sudo openssl dhparam 2048 -out /etc/pki/tls/dhparam.pem
$ sudo systemctl enable nginx
$ sudo systemctl restart nginx

5. 起動後の設定

mastodonの画面にWebブラウザでアクセスし、最初のユーザを作成する。

mastodon上の最初のユーザを作成してから、以下のコマンドで管理者ユーザ化する
$ docker-compose run --rm web rails mastodon:make_admin USERNAME=firstusername

さらにシングルユーザーモード化して、ほかのユーザではアクセスできなくする
$ vi .env.production
SINGLE_USER_MODE=true

設定を反映するため、再起動する。
$ docker-compose stop
$ docker-compose up -d

systemd起動スクリプトを作成して、VPSを再起動したときも自動でmastodon用コンテナが起動するようにする。
$ sudo vi /etc/systemd/system/mastodon.service

[Unit]
Description=Mastodon
Requires=docker.service
After=network.target
After=docker.service

[Service]
Type=simple
User=mastodon
Group=mastodon
WorkingDirectory=/home/mastodon/live
ExecStart=/usr/bin/docker-compose up
ExecStop=/usr/bin/docker-compose stop

[Install]
WantedBy=multi-user.target

systemctlを使ってmastodonコンテナを再起動してみる。
$ sudo systemctl enable mastodon
$ sudo systemctl stop mastodon
$ sudo systemctl start mastodon

以上で完了である。

HP mini 5101 に CentOS 6 をインストール

Windows XP プリインストールの旧型ネットブック HP mini 5101 に CentOS 6 をインストールしてみたのでメモしておく。

1. インストール:

DVD-Rなどを焼くのが面倒なので、UNetbootinでUSBメモリインストーラを作成する。ベースのISOファイルはCentOS-6.5-i386-minimal.isoである。

このノートPCのCPUはAtom N280なので32bitのみ。よってi386版をダウンロードするように気をつける。

$ wget http://ftp.iij.ad.jp/pub/linux/centos/6.5/isos/i386/CentOS-6.5-i386-minimal.iso

UNetbootin を起動して ISO イメージから USB メモリを作成するが、どうもバグがあるようでインストールが途中で止まってしまう。出来上がった USB メモリの repodata ディレクトリの中身を削除し、CentOS-6.5-i386-minimal.iso の repodata ディレクトリの中身をコピーすることで修正できる。

参考URL:
SBメモリでLinuxをインストールする 2

2. インストール後の設定

minimal インストール後は色々パッケージが足りないので、yum groupinstall でごっそり追加する。最初はNICがオフになっているので、まず有効化すること(後述)。X 環境が必要なら、”Desktop” “Desktop Platform” “Input Methods” “X Window System” “Fonts”あたりをインストールする。

$ sudo yum groupinstall "Desktop" "Desktop Platform" "Input Methods" "X Window System" "Fonts"

ノースブリッジ内蔵 Intel GMA 950 については X.org 標準のドライバで対応しているので、上記のように “X Window System” をインストールするだけで動作する。

NICについては、有線LANが Marvell 88E8072 であり、これは minimal インストール直後から利用できる (最初の設定は ONBOOT=no になっているので、ifup eth0 で使えるようになる)。

無線LANについては Intel PRO/Wireless 5100 AGN というのが乗っているが、これは minimal インストールではファイルが足りないため動作しない。iwl5000-firmware パッケージが必要である。

$ sudo yum install iwl5000-firmware

これで再起動すれば無線LANが使えるようになる。

iOS/Android 端末からの L2TP/IPsec 接続 (strongswan+xl2tpd)

iOSやAndroid端末、あるいは Windows PC などからもリモートアクセスできるよう、VPS マシンに VPN 接続を設定しておく。

PPTPについては既に脆弱性が発見されており、OSによってはサポート対象外になっているため、VPN プロトコルとしては L2TP/IPsec を使う。

前提:
対象サーバはVPSのCentOS 7。

IPsec 実装としては strongswan、L2TP 実装としては xl2tpd を利用する。

ネットワーク図は以下の通り。
05

1. インストール

[user@myvps1 ~]$ sudo apt-get install strongswan xl2tpd

カーネルパラメータをパケット転送できるよう設定する。
[user@myvps1 ~]$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #28行目のコメントを外す

[user@myvps1 ~]$ sudo sysctl -p /etc/sysctl.conf

ファイアウォール(ufw)を閉じている場合は、ESP、UDP 500・4500 を空けておくこと。

2. ipsec.confの設定

[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.conf

以下の内容を追記する。

conn L2TP-PSK
        authby=secret
        auto=add
        closeaction=clear
        dpdaction=clear
        type=transport
        rekey=no
        left=203.0.113.180
        leftprotoport=17/1701
        right=%any
        rightprotoport=17/%any

IPsec はトランスポートモードを使用する。ペイロードに L2TP を通すので、ルーティングはそちらに任せる。

再接続等はクライアント側に任せたいため、こちらからは何もしない設定である。接続が切れた場合はセッションをクリアする。

3. IPsecの事前共有鍵の設定

[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.secrets

事前共有鍵を平文で記述する。

: PSK "mypresharedkey"

4. xl2tpd.conf の設定

[user@myvps1 ~]$ sudo vi /etc/xl2tpd/xl2tpd.conf

以下の設定を追記する。

[global]
port = 1701

[lns default]
ip range = 172.16.1.11-172.16.1.30
local ip = 172.16.1.254
length bit = yes
require chap = yes
refuse pap = yes
require authentication = yes
name = myvps1.vpsnet.example.jp
ppp debug = no
pppoptfile = /etc/ppp/xl2tpd-options

接続クライアント側には、172.16.1.11 から 30 の間でアドレスが割り振られる。

5. xl2tpd-options の設定

[user@myvps1 ~]$ sudo vi /etc/ppp/xl2tpd-options

L2TPの設定を記述する。

ipcp-accept-local
ipcp-accept-remote
ms-dns 172.16.1.254  (myvps1:172.16.1.254にキャッシュDNSサーバが立っている前提)
noccp
auth
crtscts
idle 1800
mtu 1300
mru 1300
nodefaultroute
lock
connect-delay 5000
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2

6. chap-secrets の設定

[user@myvps1 ~]$ sudo vi /etc/ppp/chap-secrets

username	*	"l2tppassworddesu"	*

一般ユーザで読めない権限にしておく。

7. デーモンの起動

[user@myvps1 ~]$ sudo service strongswan restart
[user@myvps1 ~]$ sudo service xl2tpd restart

この状態で、iPhoneなどから接続してみる。
iPhoneであれば「設定」→「VPN」→「VPN構成を追加…」で「L2TP」を選択して設定を追加する。
「サーバ」欄にはVPSのホスト名(IPアドレス)、「アカウント」にはL2TPユーザ名、「パスワード」にはL2TPパスワード、「シークレット」にはIPsec事前共有鍵を設定する。

クライアント機器が公衆無線LANなどのプライベートネットワーク中に居る状態では、自動的に NAT-Traversal が利用される。ESP だけでなく、UDP 4500番ポートについてファイアウォールが空いている必要がある。

自宅-VPS間でIPsec (strongswan X.509証明書認証)

前の記事と同じ構成で、認証に証明書を導入してみた。

ネットワーク構成は前の記事と同じで、以下の図のようになる。

前提:
・VPS の OS は CentOS 7.5、自宅側サーバは Raspbian 9.4 である。
・IPsec 実装には strongswan を利用する。
・証明書作成にはOpenSSLを使い、PEM ファイルの形で管理する。
・自宅側のIPsec端点 (ホスト名:myserver1) と同一のサーバに CA を作成しておき、この CA 上で両側の端点用の証明書を発行する。

1. strongswan インストール

user@myserver1:~$ sudo apt-get install strongswan
[user@myvps1 ~]$ sudo yum install epel-release
[user@myvps1 ~]$ sudo yum install strongswan

カーネルパラメータは前々回の記事と同一の設定をしておく。

自宅内サーバ側の設定。
user@myserver1:~$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #28行目のコメントを外す

user@myserver1:~$ sudo sysctl -p /etc/sysctl.conf

VPS の方にも同じ設定を実施する。
[user@myvps1 ~]$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #追記する

[user@myvps1 ~]$ sudo sysctl -p /etc/sysctl.conf

ファイアウォール(ufw)を閉じている場合は、UDP 500 と 4500 を空けておくこと。

2. 証明書の作成

myserver1 上に CA のためのディレクトリと設定を準備する。
user@myserver1:~$ sudo mkdir /etc/ssl/CA
user@myserver1:~$ sudo mkdir /etc/ssl/newcerts
user@myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/serial"
user@myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/crlnumber"
user@myserver1:~$ sudo touch /etc/ssl/CA/index.txt
user@myserver1:~$ sudo vi /etc/ssl/openssl.cnf

/etc/ssl/openssl.cnfの抜粋:

dir		= /etc/ssl		# Where everything is kept
database	= $dir/CA/index.txt	# database index file.
certificate	= $dir/certs/ca1.crt 	# The CA certificate
serial		= $dir/CA/serial 		# The current serial number
crlnumber	= $dir/CA/crlnumber # the current crl number
                    # must be commented out to leave a V1 CRL
crl     = $dir/crl/crl.pem
private_key	= $dir/private/ca1.key

CA 鍵・証明書を作成する。
user@myserver1:~$ sudo openssl req -new -x509 -extensions v3_ca -keyout /etc/ssl/private/ca1.key -out /etc/ssl/certs/ca1.crt -days 3652
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Nagoya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
Organizational Unit Name (eg, section) []:CA
Common Name (e.g. server FQDN or YOUR name) []:ca1.home.example.com
Email Address []:

myserver1 の秘密鍵を作成する。
user@myserver1:~$ openssl genrsa -aes256 -out /etc/ssl/private/myserver1.key 2048
Enter pass phrase for myserver1.key:********
(後でパスワードを削除するので、パスワードはここでは適当に決める)
Verifying - Enter pass phrase for myserver1.key:********

秘密鍵ファイルのパスワードを削除しておく。
user@myserver1:~$ openssl rsa -in /etc/ssl/private/myserver1.key -out /etc/ssl/private/myserver1.key
Enter pass phrase for myserver1.key:********
writing RSA key

myserver1 の CSR を作成する。
user@myserver1:~$ openssl req -new -days 1826 -key /etc/ssl/private/myserver1.key -out /etc/ssl/cert/myserver1.csr
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Nagoya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
Organizational Unit Name (eg, section) []:Server
Common Name (e.g. server FQDN or YOUR name) []:myserver1.home.example.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

CA 鍵を使って CSR に署名する。
user@myserver1:~$ sudo openssl ca -in /etc/ssl/cert/myserver1.csr -config /etc/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/private/ca.key:********
(snip)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
(snip)
Data Base Updated

CA 証明書とホスト証明書・鍵を strongswan 用に配置する。
user@myserver1:~$ sudo cp /etc/ssl/certs/ca1.crt /etc/ipsec.d/cacerts/
user@myserver1:~$ sudo cp /etc/ssl/newcerts/01.pem /etc/ipsec.d/certs/myserver1.crt
user@myserver1:~$ sudo cp /etc/ssl/private/myserver1.key /etc/ipsec.d/private/

myvps1 用の証明書も同様に作成する。
user@myserver1:~$ openssl genrsa -aes256 -out /etc/ssl/private/myvps1.key 2048
user@myserver1:~$ openssl rsa -in /etc/ssl/private/myvps1.key -out /etc/ssl/private/myvps1.key
user@myserver1:~$ openssl req -new -days 1826 -key /etc/ssl/private/myvps1.key -out /etc/ssl/cert/myvps1.csr
user@myserver1:~$ sudo openssl ca -in /etc/ssl/cert/myvps1.csr -config /etc/ssl/openssl.cnf

いま作成した myvps1 用のホスト証明書・鍵、CA証明書を myvps1 側にコピーする。
user@myserver1:~$ cp /etc/ssl/certs/ca1.crt .
user@myserver1:~$ cp /etc/ssl/newcerts/02.pem ./myvps1.crt
user@myserver1:~$ sudo cp /etc/ssl/private/myvps1.key .
user@myserver1:~$ sudo chown user myvps1.key
user@myserver1:~$ scp ca1.crt myvps1.crt myvps1.key myvps1:

myvps1 上で証明書・鍵を配置する。
[user@myvps1 ~]$ sudo cp ca1.crt /etc/strongswan/ipsec.d/cacerts/
[user@myvps1 ~]$ sudo cp myvps1.crt /etc/strongswan/ipsec.d/certs/
[user@myvps1 ~]$ sudo cp myvps1.key /etc/strongswan/ipsec.d/private/

作業用ファイルを削除する。
[user@myvps1 ~]$ rm ca1.crt myvps1.crt myvps1.key
user@myserver1:~$ rm ca1.crt myvps1.crt myvps1.key

3. strongswan の設定 (myserver1側)

設定ファイルを編集する。
user@myserver1:~$ sudo vi /etc/ipsec.conf

config setup セクションの後に以下の内容を追加する。

conn myhome-to-vps
	authby=rsasig
	auto=start
	closeaction=restart
	dpdaction=restart
	left=192.168.100.240
	leftsubnet=192.168.100.0/24
	leftcert=myserver1.crt
	right=203.0.113.180
	rightsubnet=203.0.113.180/32
	rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myvps1.vpsnet.example.com"

こちら側から接続を開始するため、auto=start を記述する。また接続が切れたときにはこちら側から再接続を実行するため、closeaction=restart と dpdaction=restart を記述する。

パスワードファイルには秘密鍵のファイル名を記述する。
user@myserver1:~$ sudo vi /etc/ipsec.secrets

: RSA myserver1.key

4. strongswan の設定 (myvps1側)

こちらも設定ファイルを編集する。
[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.conf

以下の内容を追加する。

conn myhome-to-vps
	authby=rsasig
	auto=add
	closeaction=clear
	dpdaction=clear
	left=203.0.113.180
	leftsubnet=203.0.113.180/32
	leftcert=myvps1.crt
	right=%any
	rightsubnet=192.168.100.0/24
	rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myserver1.home.example.com"

パスワードファイルには秘密鍵のファイル名を記述する。
[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.secrets

: RSA myvps1.key

5. サービス起動と確認

サービスを起動する。

user@myserver1:~$ sudo service strongswan start
[user@myvps1 ~]$ sudo service strongswan start

接続できたかどうか、ip xfrm state コマンドで確認する。

user@myserver1:~$ sudo ip xfrm state
src 192.168.100.240 dst 203.0.113.180
	proto esp spi 0xbaef12dc reqid 1 mode tunnel
	replay-window 32 flag af-unspec
	auth-trunc hmac(sha1) 0x6bde34f03f729b5a3c1d93c112ea6a40bf312742 96
	enc cbc(aes) 0x4f2fa3876e41e825be32a4e710a5f193
	encap type espinudp sport 4500 dport 4500 addr 0.0.0.0
src 203.0.113.180 dst 192.168.100.240
	proto esp spi 0xbb4b32e0 reqid 1 mode tunnel
	replay-window 32 flag af-unspec
	auth-trunc hmac(sha1) 0x44b52fad2bf912e10b61706add1337f823ec344e 96
	enc cbc(aes) 0xaf32405118ac467efb02f5f76e59aad1
	encap type espinudp sport 4500 dport 4500 addr 0.0.0.0

自宅-VPS間でIPsec (strongswan)

自宅(動的IPアドレス)とVPS(固定IPアドレス)の間で、IPsec トンネルを常時接続してみる。これには、自宅のIPアドレスが変わっても、VPS 経由で自宅に入れるというメリットがある。

ネットワーク図

VPS の OS: CentOS 7.5
自宅サーバのOS: Raspbian 9.4 (Raspberry Pi)
IPsec ソフトウェア: strongswan

1. VPS 側

strongswan をインストールする。
[user@myvps1 ~]$ sudo yum install epel-release
[user@myvps1 ~]$ sudo yum install strongswan

通過パケットを転送できるように、カーネルパラメータを変更する。
[user@myvps1 ~]$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #追記する

[user@myvps1 ~]$ sudo sysctl -p /etc/sysctl.conf

ipsec.conf を編集する。
[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.conf

conn myhome-to-vps
        authby=secret
        auto=add
        closeaction=clear
        dpdaction=clear
        left=203.0.113.180
        leftsubnet=203.0.113.180/32
        right=%any		#相手側IPアドレスは不明なので%anyにしておく
        rightsubnet=192.168.100.0/24

事前共有鍵を設定する。
[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.secrets

: PSK "mypresharedkey"

サービスを起動する。
[user@myvps1 ~]$ sudo systemctl enable strongswan
[user@myvps1 ~]$ sudo systemctl start strongswan

2. 自宅側

strongswan をインストールする。
user@myserver1:~$ sudo apt install strongswan

通過パケットを転送できるように、カーネルパラメータを変更する。
user@myserver1:~$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #28行目のコメントを外す

user@myserver1:~$ sudo sysctl -p /etc/sysctl.conf

ipsec.conf を編集する。
user@myserver1:~$ sudo vi /etc/ipsec.conf

conn myhome-to-vps
        authby=secret
        auto=start		#自動的にこちらから接続する
        closeaction=restart
        dpdaction=restart
        left=192.168.100.240
        leftsubnet=192.168.100.0/24
        right=203.0.113.180
        rightsubnet=203.0.113.180/32

VPS 側と同じ事前共有鍵を設定する。
user@myserver1:~$ sudo vi /etc/ipsec.secrets

: PSK "mypresharedkey"

サービスを起動する。
user@myserver1:~$ sudo systemctl enable strongswan
user@myserver1:~$ sudo systemctl start strongswan

以上の設定で接続できる。NAPT を越えることが自動的に検出されて、IPsec パケットは NAT-Traversal でカプセル化される。iptables で UDP 4500 が閉じられている場合は、ACCEPT するように変更しておく。