カテゴリー別アーカイブ: Ubuntu

Ubuntu に関すること

Ubuntu 16.04 + MariaDB

※以下のサイトを参考に全面改訂しました(2017/09/12)
Ubunt 16.04でMariaDBをインストールするとパスワードが変

MySQL から MariaDB に移行するにあたって、パッケージが前提とする流儀が違ったり、罠があったりするので手当てをする。

1. DB root ユーザでの接続

通常は最初に DB root ユーザで DB エンジンに接続して、アプリケーションの要求するデータベースやユーザを作成するだろう。

このとき、OS の一般ユーザでは、DB に root ログインしようとしても不可能になっている。mysql_secure_installation を実行して DB root ユーザのパスワードを設定しておいてもダメである。

user@xenial:~$ mysql -u root -p
Enter password:
ERROR 1698 (28000): Access denied for user 'root'@'localhost'

この場合、OS の (UNIX ユーザとしての) root 権限を得て mysql コマンドを実行する必要がある。初期状態の DB root ユーザ認証に UNIX ソケット認証プラグインが使われているから、らしい。

つまりは sudo を使うか、su で root になっておく必要がある。OS の root 権限でさえあれば、以下のようにユーザ名指定なし・パスワードなしで接続可能である。

user@xenial:~$ sudo mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 32
Server version: 10.0.31-MariaDB-0ubuntu0.16.04.2 Ubuntu 16.04

Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> 

この初期設定に乗っかっていくなら、DB の root パスワードを設定する必要がない。テストDB等も存在していないため、mysql_secure_installation で初期化してやる必要は特にない (あえてやるなら、mysql_secure_installation を sudo で実行しなければならない)。

この認証方式では、TCP/3306 経由ではログインできないことになる。必ずローカルの UNIX ドメインソケット経由でなければならない。

DB の root ユーザを従来のパスワード認証に変更したい (以前の方式に戻す) 場合は、以下の手順を実行する。

user@xenial:~$ sudo mysql
MariaDB [(none)]> set password for 'root'@'localhost'=password('パスワード文字列');
MariaDB [(none)]> use mysql;
MariaDB [mysql]> update user set plugin='' where user='root';
MariaDB [mysql]> flush privileges;
MariaDB [mysql]> \q

root ユーザの認証プラグインを外し、通常のパスワードを設定している。この対処を実施した場合は、/etc/mysql/debian.cnf に平文パスワードを記述してやらないと systemctl での起動・停止が動作しなくなる。

もしくは、UNIX ソケット認証を使わない管理者 root2 ユーザを新規作成するという形でもよい。

user@xenial:~$ sudo mysql
MariaDB [(none)]> create user 'root2'@'localhost' identified by 'パスワード文字列';
MariaDB [(none)]> grant all on *.* to 'root2'@'localhost' with grant option;
MariaDB [(none)]> \q

※個人的には、このUNIX認証をDBのユーザ認証に対応させる仕組みは筋が悪いと思う。DB の root という弱い権限 (最悪でもDBしか壊せない) を呼び出すためだけに、OS の root という強い権限 (システム全体を壊せる) を呼び出す必要があるのだから。

2. localhost の tcp/3306 に接続できない

アプリケーションから localhost あてに接続すると、システム上 IPv6 (::1) が優先される。しかし MariaDB デフォルト設定の bind-address は 127.0.0.1 になっている。

このせいで、アプリケーションの設定で、DB サーバのホスト名 / IP アドレス指定を “localhost” にしてあると接続できない。アプリケーション側での DB サーバ指定を 127.0.0.1 とするか、MariaDB 側の設定ファイル /etc/mysql/mariadb.conf.d/50-server.cnf で bind-address を ::1 にする必要がある。

Ubuntu 14.04 + nginx で HTTP/2 サーバ

※以下は Ubuntu 14.04 用の内容です。Ubuntu 16.04 であれば、標準パッケージでHTTP/2が使えて、様々な機能が追加された nginx-extras が利用可能です。そちらを使いましょう。

nginx公式で配布されているmainlineバイナリを使えばHTTP/2は利用できるのだが、nginx-dav-ext-moduleが同時にコンパイルされておらずWebDAVが使い物にならないため、リビルドを実行する。

1. ビルド環境を準備する

開発環境をインストールする。

sudo apt-get install build-essential debhelper

nginxのビルドに必要なライブラリ・ヘッダをインストールする。

sudo apt-get install libpcre3-dev libxml2-dev libxslt1-dev libgd-dev libssl-dev libgeoip-dev

2. nginx公式のパッケージをapt-getで利用できるようにする

apt sourceとして登録する。

curl http://nginx.org/keys/nginx_signing.key | sudo apt-key add -
sudo vi /etc/apt/sources.list.d/nginx.list

/etc/apt/sources.list.d/nginx.listファイル:

deb http://nginx.org/packages/mainline/ubuntu/ trusty nginx
deb-src http://nginx.org/packages/mainline/ubuntu/ trusty nginx

3. ソースパッケージを取得してビルドする

sudo apt-get update
apt-get source nginx
cd nginx-1.9.12
git clone https://github.com/arut/nginx-dav-ext-module.git
vi debian/rules

nginx-1.9.12/debian/rulesファイル:

    --add-module=./nginx-dav-ext-module \ この行を追加

実際にビルドする。

dpkg-buildpackage -us -uc -b -d
cd ..

4. ビルドしたパッケージをapt-getでインストールする

ローカルのdebレポジトリを作成する。

sudo mkdir -p /usr/src/deb
sudo mv *.deb /usr/src/deb/
sudo bash
# cd /usr/src/deb
# apt-ftparchive packages . | gzip -c9 > Packages.gz
# apt-ftparchive sources . | gzip -c9 > Sources.gz
# exit
sudo vi /etc/apt/sources.list.d/local.list

/etc/apt/sources.list.d/local.listファイル:

deb file:/usr/src/deb/ ./

インストールを実行する。

sudo apt-get update
sudo apt-get install nginx

参考URL:
Ubuntu (Debian) で nginx に WebDAV拡張モジュール(ngx-dav-ext-module)を組み込むで使ってみる
Nginx で WebDAV 環境構築、PROPFIND 405 が使えなかったのでソースからコンパイルしてみた
ローカルに置いたdebファイルをapt-get installでインストールする
Nginxセキュリティ設定
Ubuntu+php5-fpm+mysql で LEMP 環境に WordPress をインストール
Let’s EncryptとnginxでHTTP/2サーバを立てる

AirPrint非対応のプリンタをUbuntuサーバ経由でAirPrint対応に

avahi-daemon (Apple Bonjour互換) を使ってプリンタ名を広告してやることによって、AirPrint非対応の旧世代プリンタをAirPrint対応にできるらしいので、実験してみた。

そのためには、Linux プリンタサーバ上に、iOS デバイスへプリンタ情報を教えるための avahi 設定が必要になる。

前の記事の内容で、既にUbuntu環境でプリンタの設定はできているものとする。

1. インストール

必要なパッケージをUbuntuデスクトップにインストールする。

desktop$ sudo apt-get install avahi-discover

2. 情報の取得

端末から、avahi-discover コマンドを実行する。標準出力にダンプされる情報を利用するので、ログファイルを取っておく。

desktop$ avahi-discover >log

表示された GUI ウインドウ上で、「Internet Printer」→「EPSON EP-802A @ myserver1」を選択する。その後、×ボタンで GUI を閉じる。

logファイルの内容を確認すると、末尾近くに以下のような行がある。

Host myserver1.local (192.168.100.240), port 631, TXT data: ['printer-type=0xB01E', 'printer-state=3', 'Duplex=T', 'Color=T', 'TLS=1.2', 'UUID=3ae710a1-2d56-928f-4a19-394a152d3eca', 'URF=DM3', 'pdl=application/octet-stream,application/pdf,application/postscript,image/jpeg,image/png,image/urf', 'product=(Epson EP-902A Series)', 'priority=0', 'note=Home', 'adminurl=https://myserver1.local:631/printers/EPSON-EP-802A', 'ty=Epson EP-802A Series - epson-inkjet-printer 1.0.0-1lsb3.2 (Seiko Epson Corporation LSB 3.2)', 'rp=printers/EPSON-EP-802A', 'qtotal=1', 'txtvers=1']

3. 情報ファイルの作成

上記の情報をもとに、avahi のサービス情報ファイルを作成する。

myserver1$ sudo vi /etc/avahi/services/AirPrint-EPSON-EP-802A.service
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">AirPrint EPSON-EP-802A @ %h</name>
<service>
 <type>_ipp._tcp</type>
 <subtype>_universal._sub._ipp._tcp</subtype>
 <port>631</port>
 <txt-record>txtvers=1</txt-record>
 <txt-record>qtotal=1</txt-record>
 <txt-record>rp=printers/EPSON-EP-802A</txt-record>
 <txt-record>ty=Epson EP-802A Series - epson-inkjet-printer 1.0.0-1lsb3.2 (Seiko Epson Corporation LSB 3.2)</txt-record>
 <txt-record>adminurl=https://myserver1.local:631/printers/EPSON-EP-802A</txt-record>
 <txt-record>note=Home</txt-record>
 <txt-record>priority=0</txt-record>
 <txt-record>product=(Epson EP-902A Series)</txt-record>
 <txt-record>pdl=application/octet-stream,application/pdf,application/postscript,image/jpeg,image/png,image/urf</txt-record>
 <txt-record>UUID=3ae710a1-2d56-928f-4a19-394a152d3eca</txt-record>
 <txt-record>TLS=1.2</txt-record>
 <txt-record>Color=T</txt-record>
 <txt-record>Duplex=T</txt-record>
 <txt-record>printer-state=3</txt-record>
 <txt-record>printer-type=0xB01E</txt-record>
 <txt-record>URF=none</txt-record>
</service>
</service-group>

ファイルができたら、サービスを再起動する。

myserver1$ sudo service avahi-daemon restart
myserver1$ sudo service cups restart

設定が終わったら、iOS デバイスのアプリケーション (例えばSafari) からテスト印刷する。「メニューボタン」→「プリント」を選択して、「プリンタ」に「EP-802A」が表示されたら選択して印刷してみる。自分の環境では、きちんと印刷できた。

参考URL: 今日はLinuxのCUPSプリントサーバをAirPrintサーバにして、iPhoneからAirPrintで印刷するとPDFファイルが生成されるようにしてみた

UbuntuでEPSONプリンタを使う

自分の場合は通常使わないのだが、念のためUbuntuサーバからも印刷ができるようにしてみた。
環境:
プリンタサーバ: Ubuntu 14.04 server (64bit) ホスト名 myserver1
操作用デスクトップ: Ubuntu 14.04 desktop (64bit) ホスト名 desktop
プリンタ: EPSON EP-802A
プリンタサーバ-プリンタ間接続形式: ネットワーク経由

1. プリンタドライバのダウンロード

EPSON Download Center でプリンタ型番をキーワードに検索し、ダウンロードする。
自分の環境の場合は、以下の4つをダウンロードした。
iscan-data_1.29.0-2_all.deb
iscan_2.29.3-1~usb0.1.ltdl7_amd64.deb
epson-inkjet-printer-ep-902a-series_1.0.0-1lsb3.2_amd64.deb
epson-inkjet-printer-escpr_1.4.1-1lsb3.2_amd64.deb

2. プリンタドライバのインストール

必要なパッケージをインストールする。

myserver1$ sudo apt-get install lsb xsltproc

さらに、ダウンロードしたファイルをインストールする。

myserver1$ sudo dpkg -i iscan-data_1.29.0-2_all.deb \
iscan_2.29.3-1~usb0.1.ltdl7_amd64.deb \
epson-inkjet-printer-ep-902a-series_1.0.0-1lsb3.2_amd64.deb \
epson-inkjet-printer-escpr_1.4.1-1lsb3.2_amd64.deb

3. CUPSの設定

今回の設定対象は X 環境の無いUbuntuサーバなので、他のマシン(Ubuntuデスクトップ)からリモートで設定したい。そのため、CUPSの設定を変更して同一ネットワークのマシンからはリモート管理ができるようにする。

myserver1$ sudo vi /etc/cups/cupsd.conf

以下、cupsd.confの編集内容をdiff -u形式で表示する。

@@ -13,11 +13,12 @@
 MaxLogSize 0

 # Only listen for connections from the local machine.
-Listen localhost:631
+#Listen localhost:631
 Listen /var/run/cups/cups.sock
+Port 631

 # Show shared printers on the local network.
-Browsing Off
+Browsing On
 BrowseLocalProtocols dnssd

 # Default authentication type, when authentication is required...
@@ -29,11 +30,13 @@
 # Restrict access to the server...
 
   Order allow,deny
+  Allow @LOCAL
 

 # Restrict access to the admin pages...
 
   Order allow,deny
+  Allow @LOCAL
 

 # Restrict access to configuration files...
@@ -41,6 +44,7 @@
   AuthType Default
   Require user @SYSTEM
   Order allow,deny
+  Allow @LOCAL
 

 # Set the default printer/job policies...

サービスを再起動する。

myserver1$ sudo service cups restart

4. Ubuntu デスクトップからの設定

次にUbuntuデスクトップ側で、system-config-printerを使って先のサーバにリモート接続して設定を実施する。system-config-printerがインストールされていなければ、インストールしておく。

desktop$ sudo apt-get install system-config-printer-gnome

手元のUbuntu 14.04 Desktopでは、システム設定 (unity-control-center) にプリンタの設定アイコンが無かったので、端末から直接実行して GUI を起動した。

desktop$ system-config-printer

「サーバー」メニューから「接続」を選択して、「CUPSサーバー」欄にUbuntuサーバのIPアドレスを入力して接続する。

あとは「追加」ボタンを押して「ネットワークプリンター」の中から「Epson EP-802A (aa.bb.cc.dd)」、接続は「DNS-SD 経由の LPD ネットワークプリンター」を選択する。ドライバは自動検索され、高機能版が自動的に選ばれる。

設定が終わったら、テスト印刷を実行して確認する。

参考URL: Ubuntu Weekly Recipe 第286回 UbuntuからEPSON複合機EP-805Aを使用する

外部からVPSへのL2TP/IPsecとVPS-自宅間IPsecの組み合わせ

前回記事のリモートアクセスVPN (L2TP/IPsec) と、さらにその前の記事で構築済みのVPS-自宅間VPN (IPsec) を組み合わせて利用する。

これにより、動的IPアドレスの自宅へ、外部からいつでもログイン可能となる。

前提:
・サーバはすべて Ubuntu 14.04 LTS である。
・IPsec実装は strongswan を利用し、サーバ間はRSA証明書認証を行う。
・外部端末-VPS間はL2TP/IPsecとし、認証はIPsec事前共有鍵+L2TPのMSCHAPv2とする。

ネットワーク構成は以下の通り。
06

すでに記事としては前回前々回で記述している。
今回のポイントは、VPS への L2TP アクセスで割り振られる PPP IPアドレスを、VPS-自宅間IPsecのトンネルに入るよう設定することである。

1. myvps1 と myserver1 の /etc/sysctl.conf

$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #28行目のコメントを外す
# 以下、追記する
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.eth0.accept_redirects=0
net.ipv4.conf.eth0.send_redirects=0
net.ipv4.conf.lo.accept_redirects=0
net.ipv4.conf.lo.send_redirects=0
net.ipv6.conf.eth0.accept_redirects=0
net.ipv6.conf.lo.accept_redirects=0
vpn1:~$ sudo sysctl -p /etc/sysctl.conf

2. myserver1上にCAを作成し、myserver1用とmyvps1用の証明書・秘密鍵の組を作成する

前々回記事を参照。

myserver1 には
/etc/ipsec.d/cacerts/ca1.crt (CA証明書)
/etc/ipsec.d/certs/myserver1.crt (サーバ証明書)
/etc/ipsec.d/private/myserver1.key (サーバ秘密鍵)

myvps1 には
/etc/ipsec.d/cacerts/ca1.crt (CA証明書)
/etc/ipsec.d/certs/myvps1.crt (サーバ証明書)
/etc/ipsec.d/private/myvps1.key (サーバ秘密鍵)

以上のファイルを配置する。

3. strongswan の設定 (myserver1側)

/etc/ipsec.conf:

config setup セクションの後に以下の内容を追加する。rightsubnet に L2TP クライアントの IP アドレス領域を追加しておく。

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,172.16.1.0/24 # ←L2TPのクライアントアドレスを追加
	rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myvps1.vpsnet.example.jp"

※strongswan だと leftsubnet / rightsubnet に複数のサブネットが記述できるが、openswan で複数サブネットの場合は leftsubnets / rightsubnets と書く必要がある。

/etc/ipsec.secrets:

: RSA myserver1.key

4. strongswan の設定 (myvps1側)

/etc/ipsec.conf:

config setup セクションの後に、以下の2つの記述を追加する。
myhome-to-vps の方の leftsubnet には、L2TP クライアントアドレス領域を追加しておく。

conn myhome-to-vps
	authby=rsasig
	auto=add
	closeaction=clear
	dpdaction=clear
	left=203.0.113.180
	leftsubnet=203.0.113.180/32,172.16.1.0/24 # ←L2TPのクライアントアドレスを追加
	leftcert=myvps1.crt
	right=%any
	rightsubnet=192.168.100.0/24
	rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myserver1.domain.local"

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

/etc/ipsec.secrets:
自宅IPsec用のRSA秘密鍵と、L2TP/IPsec用の事前共有鍵文字列を両方記述する。

: RSA myvps1.key
: PSK "mypresharedkey"

5. xl2tpd の設定 (myvps1側)

/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

/etc/ppp/xl2tpd-options:

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

/etc/ppp/chap-secrets:

username	*	"l2tppassworddesu"	*

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

6. サービス起動と確認

myserver1:~$ sudo service strongswan restart
myvps1:~$ sudo service strongswan restart
myvps1:~$ sudo service xl2tpd restart

milter-greylist で GeoIP を使えるようにする

Ubuntu 標準パッケージの milter-greylist は libGeoIP をリンクするようにコンパイルされていないので、GeoIP (IPアドレスベースの国別判定) をポリシーに利用することが出来ない。そこで Ubuntu ソースパッケージを微修正してリビルドすることで GeoIP を使えるようにする。また、ついでにPostfixへの対応を入れておく。

必要なパッケージのインストール

myserver1:~$ sudo apt-get install build-essential quilt debhelper autotools-dev bison flex
myserver1:~$ sudo apt-get install libgeoip-dev libspf2-dev libmilter-dev

ソースパッケージのダウンロード

myserver1:~$ apt-get source milter-greylist

パッケージ情報ファイルの編集

GeoIP をリンクするように、パッケージ情報ファイルを編集する。

rules ファイルを編集し、configure オプションの中に –with-libGeoIP \ を追加する。configure 実行時に libGeoIP を探してくれるようになる。

myserver1:~$ cd milter-greylist-4.3.9
myserver1:milter-greylist-4.3.9$ vi debian/rules
override_dh_auto_configure:
    dh_auto_configure -- \
    --with-user=greylist \
    --sysconfdir=/etc/milter-greylist \
    --with-conffile=/etc/milter-greylist/greylist.conf \
    --with-dumpfile=/var/lib/milter-greylist/greylist.db \
    --with-libspf2=/usr \
    --with-libmilter=/usr \
    --with-libGeoIP \  ←ここを追加
    --enable-postfix \  ←ここを追加
    --enable-dnsrbl \
    --disable-rpath \
    LDFLAGS=" -Wl,-z,defs -L/usr/lib/libmilter " \
    CFLAGS=" -fno-strict-aliasing "

また、controlファイルを編集して、Build-Depends 行に libgeoip-dev を追加する。

myserver1:milter-greylist-4.3.9$ vi debian/control
Build-Depends: quilt, debhelper (>= 8), autotools-dev, libmilter-dev, bison, flex, libspf2-dev, libgeoip-dev

パッケージバージョン番号を変更するために、changelogも編集する。内容は適当。

myserver1:milter-greylist-4.3.9$ vi debian/changelog
milter-greylist (4.3.9-101) unstable; urgency=low

  * Build with --with-libGeoIP
  * Build with --enable-postfix

 -- My Name <myname@example.com>  Mon, 30 Jun 2014 10:00:00 +0900

バージョン番号を元のパッケージより大きくしておかないと、apt-get upgrade した時に公式パッケージで置き換えられてしまう。ここでは 4.3.9-1 から 4.3.9-101 にしておいた。

ビルド

編集が終わったら、実際にビルドする。

myserver1:milter-greylist-4.3.9$ dpkg-buildpackage -us -uc

インストール

.deb パッケージが出来上がったら、公式パッケージをアンインストールして入れ換える。

myserver1:milter-greylist-4.3.9$ sudo apt-get purge milter-greylist
myserver1:milter-greylist-4.3.9$ sudo dpkg -i ../milter-greylist_4.3.9-101_amd64.deb

設定

milter-greylist を入れ換えたら、/etc/milter-greylist/greylist.conf に geoip の記述が使えるようになる。例えば自宅のサーバでは、CN からメールを受け取る予定が無いのでこれをブラックリストに入れてみる。

myserver1:~$ sudo vi /etc/milter-greylist/greylist.conf

greylist.conf の中身:

geoipdb "/usr/share/GeoIP/GeoIP.dat"
...
racl blacklist geoip "CN"

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

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

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

前提:
対象サーバはVPSのUbuntu 14.04。

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

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

1. インストール

myvps1:~$ sudo apt-get install strongswan xl2tpd

カーネルパラメータをパケット転送できるよう設定する。

myvps1:~$ sudo vi /etc/sysctl.conf
net.ipv4.ip_forward=1  #28行目のコメントを外す
# 以下、追記する
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.eth0.accept_redirects=0
net.ipv4.conf.eth0.send_redirects=0
net.ipv4.conf.lo.accept_redirects=0
net.ipv4.conf.lo.send_redirects=0
net.ipv6.conf.eth0.accept_redirects=0
net.ipv6.conf.lo.accept_redirects=0
myvps1:~$ sudo sysctl -p /etc/sysctl.conf

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

2. ipsec.confの設定

myvps1:~$ sudo vi /etc/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の事前共有鍵の設定

myvps1:~$ sudo vi /etc/ipsec.secrets

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

: PSK "mypresharedkey"

4. xl2tpd.conf の設定

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 の設定

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 の設定

myvps1:~$ sudo vi /etc/ppp/chap-secrets
username	*	"l2tppassworddesu"	*

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

7. デーモンの起動

myvps1:~$ sudo service strongswan restart
myvps1:~$ sudo service xl2tpd restart

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

クライアント機器が、公衆無線LANなどのプライベートネットワーク中に居る状態も想定しなければならない。その場合は NAT-Traversal を使うことになるが、Ubuntu 14.04 の strongswan は標準でNAT-Traversal を自動検出してくれるようなので、特別な設定をしなくても接続できる (ただし、UDP 4500番ポートについてファイアウォールが空いている必要はある)。

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

IPsecトンネルの認証に証明書認証を導入する検証を実施してみたが、Ubuntu 14.04 標準パッケージの openswan では trusted_ca returning with failed というエラーが出てうまくいかなかった。

strongswan で試したところ成功したので、この設定を以下に説明する。(strongswanとopenswanの比較はこちら)

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

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

1. strongswan インストール

myserver1:~$ sudo apt-get purge openswan
myserver1:~$ sudo apt-get install strongswan
myvps1:~$ sudo apt-get purge openswan
myvps1:~$ sudo apt-get install strongswan

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

vpn1:~$ sudo vi /etc/sysctl.conf
net.ipv4.ip_forward=1  #28行目のコメントを外す
# 以下、追記する
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.eth0.accept_redirects=0
net.ipv4.conf.eth0.send_redirects=0
net.ipv4.conf.lo.accept_redirects=0
net.ipv4.conf.lo.send_redirects=0
net.ipv6.conf.eth0.accept_redirects=0
net.ipv6.conf.lo.accept_redirects=0
vpn1:~$ sudo sysctl -p /etc/sysctl.conf

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

2. myserver1上にCAのためのディレクトリと設定を準備する

myserver1:~$ sudo mkdir /etc/ssl/CA
myserver1:~$ sudo mkdir /etc/ssl/newcerts
myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/serial"
myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/crlnumber"
myserver1:~$ sudo touch /etc/ssl/CA/index.txt
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

3. CAの証明書・鍵を作成する

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.domain.local
Email Address []:

4. myserver1ホストの秘密鍵を作成する

myserver1:~$ openssl genrsa -aes256 -out myserver1.key 2048
Enter pass phrase for myserver1.key:********
(後でパスワードを削除するので、パスワードはここでは適当に決める)
Verifying - Enter pass phrase for myserver1.key:********

秘密鍵ファイルのパスワードを削除しておく

myserver1:~$ openssl rsa -in myserver1.key -out myserver1.key
Enter pass phrase for myserver1.key:********
writing RSA key

5. CSRを作成する

myserver1:~$ openssl req -new -days 1826 -key myserver1.key -out 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.domain.local
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

6. CA鍵を使って署名する

myserver1:~$ sudo openssl ca -in 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

7. CA証明書とホスト証明書・鍵を /etc/ipsec.d にコピーしておく

myserver1:~$ sudo cp -p /etc/ssl/certs/ca1.crt /etc/ipsec.d/cacerts/
myserver1:~$ sudo cp -p /etc/ssl/newcerts/01.pem /etc/ipsec.d/certs/myserver1.crt
myserver1:~$ sudo cp myserver1.key /etc/ipsec.d/private/

8. myvps1用の証明書も同様に作成する

myserver1:~$ openssl genrsa -aes256 -out myvps1.key 2048
myserver1:~$ openssl rsa -in myvps1.key -out myvps1.key
myserver1:~$ openssl req -new -days 1826 -key myvps1.key -out myvps1.csr
myserver1:~$ sudo openssl ca -in myvps1.csr -config /etc/ssl/openssl.cnf

9. myvps1 にホスト証明書・鍵、CA証明書をコピーする

myserver1:~$ cp /etc/ssl/certs/ca1.crt .
myserver1:~$ cp /etc/ssl/newcerts/02.pem ./myvps1.crt
myserver1:~$ scp ca1.crt myvps1.crt myvps1.key myvps1:

myvps1:~$ sudo cp ca1.crt /etc/ipsec.d/cacerts/
myvps1:~$ sudo cp myvps1.crt /etc/ipsec.d/certs/
myvps1:~$ sudo cp myvps1.key /etc/ipsec.d/private/
myvps1:~$ rm ca1.crt myvps1.crt myvps1.key
myserver1:~$ rm ca1.crt myvps1.crt myvps1.key

10. strongswan の設定 (myserver1側)

設定ファイルを編集する。

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.jp"

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

パスワードファイルには秘密鍵のファイル名を記述する。

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

/etc/ipsec.secrets:

: RSA myserver1.key

11. strongswan の設定 (myvps1側)

こちらも設定ファイルを編集する。

myvps1:~$ sudo vi /etc/ipsec.conf

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

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.domain.local"

パスワードファイルには秘密鍵のファイル名を記述する。

myvps1:~$ sudo vi /etc/ipsec.secrets

/etc/ipsec.secrets:

: RSA myvps1.key

12. サービス起動と確認

サービスを起動する。

myserver1:~$ sudo service strongswan start
myvps1:~$ sudo service strongswan start

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

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

myserver1:~$ sudo ip xfrm policy
src 203.0.113.180/32 dst 192.168.100.0/24 
	dir fwd priority 1827 
	tmpl src 203.0.113.180 dst 192.168.100.240
		proto esp reqid 1 mode tunnel
src 203.0.113.180/32 dst 192.168.100.0/24 
	dir in priority 1827 
	tmpl src 203.0.113.180 dst 192.168.100.240
		proto esp reqid 1 mode tunnel
src 192.168.100.0/24 dst 203.0.113.180/32 
	dir out priority 1827 
	tmpl src 192.168.100.240 dst 203.0.113.180
		proto esp reqid 1 mode tunnel
(snip)

自宅-VPS間でIPsec (openswan)

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

ネットワーク図 (IPアドレスは例示用)
03

OS: Ubuntu 14.04 LTS
ソフトウェア: openswan

1. VPS側
ipsec.confを編集する。

myvps:~$ sudo vi /etc/ipsec.conf

/etc/ipsec.conf:

config setup
	protostack=netkey #autoから変更
(snip)
conn myhome-to-vps
    authby=secret
    auto=add
    left=203.0.113.180
    leftsubnet=203.0.113.180/32
    right=%any
    rightsubnet=192.168.24.0/24
    rightid=192.168.24.252

事前共有鍵を設定する。

myvps:~$ sudo vi /etc/ipsec.secrets

/etc/ipsec.secrets:

: PSK "mypresharedkey"

2. 自宅側
ipsec.confを編集する。

myvps:~$ sudo vi /etc/ipsec.conf

/etc/ipsec.conf:

config setup
	protostack=netkey #autoから変更
(snip)
conn myhome-to-vps
    authby=secret
    auto=start
    left=192.168.24.252
    leftsubnet=192.168.24.0/24
    right=203.0.113.180
    rightsubnet=203.0.113.180/32

VPS側と同じ事前共有鍵を設定する。

myvps:~$ sudo vi /etc/ipsec.secrets

/etc/ipsec.secrets:

: PSK "mypresharedkey"

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

自宅グローバルIPアドレスは不定のため、IPsecのピアIDとしては適当な文字列(ここではプライベートIPアドレス)を使う。通常、片側の端点が動的IPアドレスの場合は Aggressive モードを使うものだが、上記の設定であれば Main モードでつながるようだ。このへんの仕組みがよくわからない…

また、上記は事前共有鍵による認証を使っているが、OpenSSLで生成したRSA証明書認証を設定しようとするとうまくいかない。このあたり試行錯誤が必要だ。
(※追記: openswanだとうまくいかないので、strongswanに切り替えました。strongswanとopenswanの比較はこちら)

Linux サーバ間 IPsec 接続 (openswan)

Linuxサーバ同士の間で通常のIPsecを接続したことが無かったので、検証してみた。

I. 前提

環境は以下の通り。
01

vpn1、vpn2、host1、host2、router1 OSは全てUbuntu 14.04である。

vpn1←→vpn2の間で、openswanでトンネルモードIPsec接続をする。10.0.1.0/24 から 10.0.2.0/24 へのパケット、またその逆方向のパケットはトンネルへ入るようにする。つまり、例えばhost1からhost2へpingを打つとトンネルを通ることになる。10.0.1.0/24や10.0.2.0/24へのスタティックルートはrouter1に追加しないようにしておくので、VPNトンネルが出来なければhost1からhost2へのpingは到達できない。

vpn2側に自動接続開始の設定を入れることで、VPNトンネルを自動的に張ることにする。

II. 設定

以下、設定を記述する(IPアドレス設定など基本的なところは省略)

1. router1 の設定:

router1:~$ sudo vi /etc/sysctl.conf
net.ipv4.ip_forward=1  #28行目のコメントを外す
router1:~$ sudo sysctl -p /etc/sysctl.conf

2. vpn1の設定:

デフォルトルートは router1 に向けておく。向いていなかったら /etc/network/interfaces などを編集して変更する。

vpn1$ ip route
default via 1.2.3.1 dev eth1
1.2.3.0/24 dev eth1  proto kernel  scope link  src 1.2.3.4
10.0.1.0/24 dev eth0  proto kernel  scope link  src 10.0.1.1

OpenSWANをインストールする。

vpn1:~$ sudo apt-get install openswan

カーネルパラメータを設定する。

vpn1:~$ sudo vi /etc/sysctl.conf
net.ipv4.ip_forward=1  #28行目のコメントを外す
# 以下、追記する
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.eth0.accept_redirects=0
net.ipv4.conf.eth0.send_redirects=0
net.ipv4.conf.lo.accept_redirects=0
net.ipv4.conf.lo.send_redirects=0
net.ipv6.conf.eth0.accept_redirects=0
net.ipv6.conf.lo.accept_redirects=0
vpn1:~$ sudo sysctl -p /etc/sysctl.conf

IPsecの事前共有鍵を設定する。

vpn1:~$ sudo vi /etc/ipsec.secrets
# 以下の行を追記
: PSK "passwordstring"

IPsecの接続設定を記述する。

vpn1:~$ sudo vi /etc/ipsec.conf
config setup	# protostack以外はデフォルトのまま
	dumpdir=/var/run/pluto/
	nat_traversal=yes
	virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v6:fd00::/8,%v6:fe80::/10
	oe=off
	protostack=netkey	# auto から変更
# 以下、追記
conn linux-to-linux
	authby=secret	# 共有鍵認証とする
	left=1.2.3.4	# 自ホストのIPアドレス
	leftsubnet=10.0.1.0/24	# 自分側のプライベートネットワーク
	right=5.6.7.8	# 対向側ホストのIPアドレス
	rightsubnet=10.0.2.0/24	# 対向側のプライベートネットワーク
	auto=add	# こちら側からはVPN接続を自動開始しない

デーモンを再起動する。

vpn1:~$ sudo service ipsec restart

3. vpn2 の設定:

デフォルトルートは router1 に向けておく。向いていなかったら /etc/network/interfaces などを編集して変更する。

vpn1$ ip route
default via 5.6.7.1 dev eth1
5.6.7.0/24 dev eth1  proto kernel  scope link  src 5.6.7.8
10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.1

OpenSWANをインストールする。

vpn1:~$ sudo apt-get install openswan

カーネルパラメータを変更する。

vpn2:~$ sudo vi /etc/sysctl.conf	# vpn1と同じ記述をする。
vpn2:~$ sudo sysctl -p /etc/sysctl.conf

IPsec事前共有鍵を設定する。

vpn2:~$ sudo vi /etc/ipsec.secrets	# これもvpn1と同じ記述をする。

IPsecの設定を記述する。

vpn2:~$ sudo vi /etc/ipsec.conf
config setup	# protostack以外はデフォルトのまま
	dumpdir=/var/run/pluto/
	nat_traversal=yes
	virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v6:fd00::/8,%v6:fe80::/10
	oe=off
	protostack=netkey	# auto から変更
# 以下、追記する。right/leftをvpn1側とは入れ換える。
conn linux-to-linux
	authby=secret
	left=5.6.7.8
	leftsubnet=10.0.2.0/24
	right=1.2.3.4
	rightsubnet=10.0.1.0/24
	auto=start	# こちら側からVPN接続を自動開始する

デーモンを再起動する。

vpn1:~$ sudo service ipsec restart

これで完成。

III. 確認

ipsec verify を実行すると FAILED が出るが、気にしなくてよい。

vpn1:~$ sudo ipsec verify
Two or more interfaces found, checking IP forwarding        [FAILED]

router1でtcpdumpを仕掛けておき、host1からhost2あてにpingを打ってみる。

host1:~$ ping 10.0.2.100
router1:~$ sudo tcpdump -n -i eth1 not tcp port 22
10:49:22.294046 IP 1.2.3.4 > 5.6.7.8: ESP(spi=0x8f3ac7ea,seq=0x1), length 132
10:49:22.294543 IP 5.6.7.8 > 1.2.3.4: ESP(spi=0x0293d289,seq=0x1), length 132
10:49:23.295411 IP 1.2.3.4 > 5.6.7.8: ESP(spi=0x8f3ac7ea,seq=0x2), length 132
10:49:23.295890 IP 5.6.7.8 > 1.2.3.4: ESP(spi=0x0293d289,seq=0x2), length 132

ESPにカプセル化されてパケットが通過していることが確認できた。

※パケットがトンネルに入るか入らないかは、IPルーティングではなくxfrmポリシーによって決まっている。
ip xfrm state、ip xfrm policy コマンドで確認できる。

vpn1:~$ sudo ip xfrm state
src 1.2.3.4 dst 5.6.7.8
	proto esp spi 0x8f3ac7ea reqid 16385 mode tunnel
	replay-window 32 flag af-unspec
	auth-trunc hmac(sha1) 0xdbc2f99d8243e36fc8920c790c0b6b9d85c84a48 96
	enc cbc(aes) 0x506786cc1fbf21c272ddeab0c4deb739
src 5.6.7.8 dst 1.2.3.4
	proto esp spi 0x0293d289 reqid 16385 mode tunnel
	replay-window 32 flag af-unspec
	auth-trunc hmac(sha1) 0x10110db5180fb3773d47cb538b29ae9371137ebd 96
	enc cbc(aes) 0xb29c28de3d0e40111f6f9720fddf117f
vpn1:~$ sudo ip xfrm policy
src 10.0.1.0/24 dst 10.0.2.0/24 
	dir out priority 2344 
	tmpl src 1.2.3.4 dst 5.6.7.8
		proto esp reqid 16385 mode tunnel
src 10.0.2.0/24 dst 10.0.1.0/24 
	dir fwd priority 2344 
	tmpl src 5.6.7.8 dst 1.2.3.4
		proto esp reqid 16385 mode tunnel
src 10.0.2.0/24 dst 10.0.1.0/24 
	dir in priority 2344 
	tmpl src 5.6.7.8 dst 1.2.3.4
		proto esp reqid 16385 mode tunnel
(snip)