#topicpath
*relayd + DeleGate + acme-client = SSLVPN [#f6ff4c62]
RIGHT:EBUG 第60回会合 ~
2017年 2月11日、万代市民会館 ~
川俣吉広、kaw@on.rim.or.jp

**発端 [#ab0755fb]
本件の例では、以下の構成で[[SSL-VPNの運用>SslVpn]]を行っていた。
本件の実以前、従来は以下の構成で[[SSL-VPNの運用>SslVpn]]を行っていた。
 INTERNET                      || INTRANET LAN
 https://gw.foobar.com/bee/*   || http://sv.inner.foobar.com/quux/baz/*
                               ||
                           +-----------+
                           |OpenBSD 5.8|
  [Web Browser]---HTTPS--->*DeleGate   *---HTTP--->[Web Server]
                          /|     9.9.13|
                         / +-----------+
                        /      ||
                   Basic       ||
                   Auth.       ||
このGWではDeleGateを用いて、以下のことをやっている;
-(A) SSL/TLSの終端 (証明書はDeleGate内蔵の自己署名されたもの)
-(B) ユーザの認証  (リバースプロキシのBasic認証)
-(C) URLのリダイレクト(書換え)

 #!/bin/sh
 
 function dgcmd {
     /usr/fuguita/sbin/delegated \
         DGROOT=/home/delegated \
         OWNER=delegated/delegated \
         LOGDIR='log/[date+archived/%Y%m]' \
         "$@"
 }
 
 umask 0027
 
 case X"$1" in
     Xstart)  dgcmd \
                 -Pgw.foobar.com:443 \       <-(A)
                  SERVER=https \             <-(A)
                  FCL=sslway \               <-(A)
                  REMITTABLE="http,https" \                  <-許可するプロトコル
                  RELIABLE="*.jp,*.gfngfn.net" \             <-許可するアクセス元
                  REACHABLE="inner.foobar.com,google.com" \  <-許可するアクセス先
                  AUTH=proxy:pauth \                                                        <-(B)
                  AUTHORIZER='-list{guest:welcome772,kaw:op2p29eje,ouquser:pvs/neue288}' \  <-(B)
                  MOUNT='/proj1/* http://gwe1.inner.foobar.com/bd/proj1/*' \   <-(C)
                  MOUNT='/proj2/* http://iwf.inner.foobar.com/wf/ntp8x16/*' \  <-(C)
                  MOUNT='/* https://google.com/?q=*' ;;                        <-(C)
     Xstop)    dgcmd -Pfoobar.com:443 -Fkill ;;
     Xrestart) $0 stop; sleep 15; $0 start;;
     *)        echo "$0 start|stop|restart" >&2 ;;
 esac
このサーバを更新し、OpenBSD 5.8 -> OpenBSD 6.0 に変更したところ、DeleGateがlibssl, libcryptoをロードしなくなった。~
外部よりアクセスすると、ブラウザに
 このサイトにアクセスできません
  foobar.com により途中で接続が切断されました。
と表示され(Google Chromeの場合)、接続できない。また、DeleGateのログでは、起動時に
 --ERROR: can't link the SSL/Crypto library.
ブラウザ接続時、DeleGateのログに
 [OpenBSD/6.0] not OOB: BrokenSocket[25] <= _-select.c91 ####
というエラーが記録される。

代替策として、SSL/TLSの終端を行う部分を他のソフトウェアで置き換えることとした。~
候補としては、Squid, Nginx, Varnishなどのリバースプロキシがあるが、今回はOpenBSDネイティブのrelaydを使用した。

併せて、SSL/TLSのサーバ証明書を自己署名のものから、Let's Encryptから発行されたものに変更した。

**relaydとは [#b1d506bc]
OpenBSDネイティブなL7ゲートウェイ。これを使用してロードバランサを構築可能。
-http://www.slideshare.net/GiovanniBechis/relayd-a-load-balancer-for-openbsd とか

 OpenBSDのウェブ関連daemonの系譜
 
 [4.1]           [4.3]
 hoststated------>relayd------+---------------->[6.0]
                              |
                              |
 Customized                   V
 Apache 1.3.x-------|Nginx---|+OpenBSD httpd--->[6.0]
 [2.3]              [5.1]    [5.7]
relaydの機能
-Incoming Connectionの中継
-バックエンドのサーバへのロードバランス(HTTP, HTTPS, DNS)
-同、死活監視
-SSL/TLS終端
-HTTPのフィルタリング
-...etc

 LBとしての動作例
                                              +--------+
                                         +--->|Web     |
                                   server|   /|Server 2|
                            health checks|  / +--------+
         +-GW-------------------------+  | /
         |               |relayd      *--+/
         |               ----*--------|  / 
         |     rdr rewriting/         | /|    +--------+
         |-----------------*----------|/ +--->|Web     |
 ------->| PF | rdr-anchor "relayd/*" *-------|Server 2|
 Incoming+----------------------------+\ |    +--------+
 Access                                 \|     
                                         \ 
                                         |\
                                         | \  +--------+
                                         +--\->Web     |
                                             \|Server 3|
                                              +--------+
PFを使わずに、relayd単体でも運用可能

**Let's Encryptとacme-clientについて [#pd5f684f]
[[Let's Encrypt>https://letsencrypt.org/]]とは、SSL/TLSのサーバ証明書を発行するCA(Certificate Authority: 認証局)の一つ。
- インターネット上のウェブサーバで、SSL/TLSを容易に導入・運用できるようにし、ウェブの安全性を高めることを目標とする。

- 証明書の発行は、ACME (Automated Certificate Management Environment)というプロトコルを用いて[[自動で行う>https://letsencrypt.org/how-it-works/]]。
--発行する証明書の種類はDV(Domain Validation: ドメイン認証)のみ、OV(Organization Validation: 組織認証)やEV(Extended Validation: 拡張認証)はサポートしていない。
--証明書の有効期間は90日。更新処理も自動で行う。

[[ACMEのクライアントプログラムは幾つもの実装がある>https://letsencrypt.org/docs/client-options/]]。[[acme-client>https://kristaps.bsd.lv/acme-client/]]はmandocの作者でもあるKristaps DzonsonsによってC言語で作成されたもの。以前はletskencryptと称していた。acme-clientはOpenBSD 6.1ではベースシステムに加えられる予定。

**SSL-VPNの再実装例 [#s0949dd2]
SSLの終端部分をrelaydで置き換え、以下のように構成を変更する。
 INTERNET                      || INTRANET LAN
 https://gw.foobar.com/bee/*   || http://sv.inner.foobar.com/quux/baz/*
                               ||
                           OpenBSD 6.0
                           +---------------+
  [Web Browser]---HTTPS--->*relayd         |
                           |----|----------|
                           |    v127.0.0.1 |
                           |----*----------|
                           |       DeleGate*---HTTP--->[Web Server]
                          /+---------------+
                         /     ||
                        /      ||
                   Basic       ||
                    Auth.      ||

-rcctlにてrelayd起動設定
 # rcctl enable relayd

-/etc/relayd.conf追加
 # $OpenBSD: relayd.conf,v 1.3 2014/12/12 10:05:09 reyk Exp $
 #
 # Macros
 #
 ext_addr="229.112.43.88"
 webhost1="127.0.0.1"
 
 #
 # Global Options
 #
 # interval 10
 # timeout 1000
 # prefork 5
 
 #
 # Each table will be mapped to a pf table.
 #
 table <webhosts> { $webhost1 }
 table <fallback> { 127.0.0.1 }
 
 #
 # Relay and protocol for HTTP layer 7 loadbalancing and SSL/TLS acceleration
 #
 http protocol https {
         match request header append "X-Forwarded-For" value "$REMOTE_ADDR"
         match request header append "X-Forwarded-By" \
             value "$SERVER_ADDR:$SERVER_PORT"
         match request header set "Connection" value "close"
 
         # Various TCP performance options
         tcp { nodelay, sack, socket buffer 65536, backlog 128 }
 
 }
 
 relay wwwtls {
         # Run as a SSL/TLS accelerator
         listen on $ext_addr port 443 tls
         protocol https
 
         # Forward to hosts in the webhosts table using a src/dst hash
         forward to <webhosts> port 10080 mode loadbalance
 }

-acme-clientをインストールし、ACMEのチャレンジの置き場所をhttpd.confで設定する。
 # $OpenBSD: httpd.conf,v 1.14 2015/02/04 08:39:35 florian Exp $
 
 #
 # Macros
 #
 ext_addr="*"
 
 #
 # Global Options
 #
 # prefork 3
 
 #
 # Servers
 #
 
 # A minimal default server
 server "default" {
         listen on $ext_addr port 32180
 }
 
 # For acme-client challenge-response
 #
 server "acme-challenge" {
         listen on * port 80
 
         location "/.well-known/acme-challenge/*" {
                 root "/acme"
                 root strip 2
         }
 }
 
 # Include MIME types instead of the built-in ones
 types {
         include "/usr/share/misc/mime.types"
 }

-relaydが参照するSSLの鍵及び証明書の作成・追加
 # acme-client -Nnv gw.foobar.com
 # ls -l /etc/acme /etc/ssl/acme /etc/ssl/acme/private
 /etc/acme:
 total 8
 -r--------  1 root  wheel  3272 Jan 30 11:53 privkey.pem
 
 /etc/ssl/acme:
 total 32
 -r--r--r--  1 root  wheel  2143 Jan 30 11:54 cert.pem
 -r--r--r--  1 root  wheel  1647 Jan 30 11:54 chain.pem
 -r--r--r--  1 root  wheel  3790 Jan 30 11:54 fullchain.pem
 drwx------  2 root  wheel    48 Jan 30 11:53 private
 
 /etc/ssl/acme/private:
 total 8
 -r--------  1 root  wheel  3272 Jan 30 11:53 privkey.pem

-relaydが参照しようとする証明書をacme-clientが取得した証明書に合わせる。
 # ls -l /etc/ssl/*.crt /etc/ssl/private/*.key
 lrwxr-xr-x  1 root  wheel  18 Feb  2 07:53 /etc/ssl/229.112.43.88.crt
                                            -> acme/fullchain.pem
 lrwxr-xr-x  1 root  wheel  27 Jan 30 11:58 /etc/ssl/private/229.112.43.88.key
                                            -> ../acme/private/privkey.pem

-鍵更新のスクリプトをcronに登録する。
 # cat /root/sbin/update-acme.sh
 #!/bin/sh
 acme-client gw.foobar.com
 
 if [ $? -eq 0 ]; then
     rcctl restart relayd
 fi

-/home/delegate/sbin/rc.delegate-sslvpnの変更
--FCL=sslway削除
--Listen Port変更(127.0.0.1/10080)
--RELIABLEパラメータにlocalhost追加

**まとめ [#pe1c57b5]
-従来のシステムと等価なものを構築できた。

-Let's Encryptはできてしまえば簡単。ウェブサーバを運営されている方は、SHA-1→SHA-2移行、常時SSL化, HTTP/2普及の流れに合わせ、準備しておいて損はないかも。

-最近のdaemon類は設定が簡単。従来の定番ソフトからの移行も検討の価値あり。

-POSTでフォームをサブミットした場合に、ブラウザがずっとレスポンス待ちの状態になることがある。要原因調査。(サーバ側ではPOSTデータのサブミット自体はされている)
----
#topicpath

Front page   Edit Diff History Attach Copy Rename Reload   New Page list Search Recent changes   Help   RSS of recent changes