セキュアなリバースプロキシの作り方

こんにちは

この記事は BBSakura Networksのアドベントカレンダー 14日目です。

在宅などのリモートでの働き方が増えてくると、困ることの一つに社内のシステムへのアクセスをどうやってセキュアに行うかがあります。クラウドのサービスであれば2段階認証などが提供されていますが、私のようなエンジニアが社内のサーバに立てたツール等は、社内のLANからのみアクセス許可することでセキュリティを保ってる場合も多いと思います。このようなシステムへのリモートアクセスをセキュアにするために、Oauth2による認証連携とクライアント証明書によるアクセス制限が行えるリバースプロキシ の立て方を紹介したいと思います。同様なことは、検索してくだくといろ色々なサイト紹介されていることも多いと思いますが自分用のメモもかねて記事にしたいと思います!

環境

リバースプロキシは ubuntu 上でdockerを使って構築しています。

構築手順

0. 概略

Internet --- reverseproxy(https://reverseproxy.example.co.jp) --- 社内システム(http://10.10.10.10)

oaut2_proxy と連携する oauth2 provider は、oauth2_proxy の default でもある google を使用しています。

1. docker/docker-composeのインストール

 sudo apt install curl
 curl -fsSL get.docker.com | sudo sh
 sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
 sudo chmod +x /usr/local/bin/docker-compose

2. 用意したファイルとディレクト

reverseproxy/
|-- CA
|-- default.conf
|-- docker-compose.yml
`-- Dockerfile

3. ディレクトリ作成

mkdir reverseproxy
mkdir reverseproxy/CA

4. docker-compose.yml

docker-compose.yml は下記の内容でファイルを作成してくだい。

version: '3'
services:
  reverseproxy:
    build: "."
    image: "reverseproxy"
    container_name: "reverseproxy"
    ports:
      - "443:443"
    volumes:
      - ./default.conf:/etc/nginx/conf.d/default.conf
      - /etc/letsencrypt/live/reverseproxy.example.co.jp/privkey.pem:/etc/ssl/private/server.key
      - /etc/letsencrypt/live/reverseproxy.example.co.jp/fullchain.pem:/etc/ssl/certs/server.crt
      - ./CA:/etc/ssl/demoCA
    depends_on:
      - oauth2_proxy
  oauth2_proxy:
    image: "quay.io/pusher/oauth2_proxy:v3.1.0"
    container_name: "oauth2_proxy"
    command: >
      --http-address=0.0.0.0:4180
      --redirect-url=https://reverseproxy.example.co.jp/oauth2/callback
      --cookie-secret=example.co.jp
      --client-id=XXXXXXXXXXXX.apps.googleusercontent.com
      --client-secret=XXXXXXXXXXXX
      --upstream=http://10.10.10.10/
      --email-domain=example.co.jp

reverseproxy のサーバ証明書は、Let's Encrypt で作成したののをdockerのnginxでも使用しています。
Google のクライアントキーとシークレットは Google Developers Console から取得しています。

5. Dockerfile

クライアント証明書を作成するために opensssl をインストールした nginx のイメージを作成するための Dockerfile です。

FROM nginx

RUN apt update && apt install openssl

EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]

6. default.conf

nginx の設定ファイルです。初回立ち上げ時は、CA局の証明書がないため ssl_client_certificatesl_verify_client はコメントにしておきます。

server {
    listen 443 ssl;
    server_name  localhost;
    server_name reverseproxy.example.co.jp;

    ssl_certificate     /etc/ssl/certs/server.crt;
    ssl_certificate_key /etc//ssl/private/server.key;

    #ssl_client_certificate /etc/ssl/demoCA/ca.crt;
    #ssl_verify_client on;

    location / {
        proxy_pass http://oauth2_proxy:4180;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

7. docker 立ち上げ

sudo docker-compose build reverseproxy
sudo docker-compose up -d

8. クライアント証明書作成

問題なく docker のコンテナが起動したら、次はクライアント証明書を作成します

8.1 クライアント証明書作成

reverseproxy コンテナに bash でアクセスし、openssl を使ってクライアント証明書を作成します。

sudo docker-compose exec reverseproxy bash

以下は、reverseproxy コンテナの中で実行します。

CA局の証明書作成
cd /etc/ssl/demoCA
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/C=JP/ST=Tokyo/L=Shinjuku-ku/O=Example/OU=Development/CN=reverseproxy.example.co.jp/emailAddress=admin@example.co.jp"

cd /etc/ssl
openssl ca -name CA_default -gencrl -keyfile ./demoCA/ca.key -cert ./demoCA/ca.crt -out ./demoCA/ca.crl -crldays 3650

touch demoCA/index.txt
echo '01' > demoCA/crlnumber

CA局 の Common Name(CN) には、リバースプロキシの FQDN を指定します。

クライアント証明書作成
cd /etc/ssl
openssl genrsa -out ./demoCA/user01.key 2048
openssl req -new -key ./demoCA/user01.key -out ./demoCA/user01.csr -subj "/C=JP/ST=Tokyo/L=Shinjuku-ku/O=Example/OU=Development/CN=user01/emailAddress=admin@example.co.jp"
openssl x509 -req -days 365 -in ./demoCA/user01.csr -CA ./demoCA/ca.crt -CAkey ./demoCA/ca.key -CAcreateserial -CAserial ./demoCA/ca.seq -out ./demoCA/user01.crt

クライアント証明書 の Common Name(CN) には、ユーザ名(上記例では user01 )を指定します。 作成された証明書を PKCS12 形式に変更します。

openssl pkcs12 -export -clcerts -in ./demoCA/user01.crt -inkey ./demoCA/user01.key -out ./demoCA/user01.p12v
exit

コンテナ中での作業はここまでで、'./reverseproxy/CA/user01.p12' のファイルを Windows や Mac にインストールすればクライアント側の準備は完了です。

NGINXの再起動

サーバ側の証明書も作成し終えたので、最初にコメントした NGINX の ssl_client関連のコンフィグのコメントを外し, コンテナを再起動します。

reverseproxy/default.conf を編集

ssl_client_certificate /etc/ssl/demoCA/ca.crt;
ssl_verify_client on;
````

コンテナの再起動

sudo docker-compose restart reverseproxy ````

以上です。