search
LoginSignup
1
Help us understand the problem. What are the problem?

posted at

updated at

actix-webでSSL/TLS通信をしてみたよ

概要

google社の透明性レポート「ウェブ上でのHTTPS暗号化」によると、2022年現在では95%以上のWebサイトがhttps通信に対応しています。残りの5%未満にならないようにhttps通信出来るようにしてみました。

actix-webは高速に動作するRust製のWebフレームワークとして知られていて、ダウンロード数やexampleプロジェクトも多いのでactix-webを利用することにしました。

環境

  • rustc 1.62.0 (on docker container rust:1.62.0-slim)
  • actix-web 4.1 (rust crate)
  • openssl 0.10 (rust crate)
  • openSSL 1.1.1
  • pkg-config 0.29.2
  • mkcert 1.4.4

準備

必要なパッケージをインストールします。libssl-devpkg-configは今回のRustプログラムのコンパイルに必要になります。wgetcurllibnss3-toolsはmkcertのダウンロード&実行に必要なパッケージです。

$ apt update && apt install -y libssl-dev pkg-config wget curl libnss3-tools

自己署名証明書

環境に合わせてmkcertをダウンロードしてきます。ここではlinux-amd64をダウンロードしてきます。ダウンロードしてきたファイル名をmkcertに変更して実行権を与えます。最後にmkcertを/usr/local/binディレクトリに移動します。

$ curl -s https://api.github.com/repos/FiloSottile/mkcert/releases/latest | grep browser_download_url | grep linux-amd64 | cut -d '"' -f 4 | wget -qi - \
    && mv mkcert-v*-linux-amd64 mkcert \
    && chmod a+x mkcert \
    && mv mkcert /usr/local/bin/

$ mkcert --version
v1.4.4

自己認証局の証明書と秘密鍵

自己認証局の証明書と秘密鍵をmkcert -installコマンドで作成します。

$ mkcert -install
Created a new local CA 💥
The local CA is now installed in the system trust store! ⚡️

作成されたディレクトリはmkcert -CAROOTコマンドで確認できます。rootCA-key.pem(秘密鍵)とrootCA.pem(証明書)が作成されているのがわかります。

$ mkcert -CAROOT
/home/rustuser/.local/share/mkcert

$ ls /home/rustuser/.local/share/mkcert/
rootCA-key.pem  rootCA.pem

サーバ証明書

mkcertコマンドでサーバ証明書を発行します。指定したドメイン(IPアドレス)の証明書を発行します。ここではローカル環境で使う予定なのでローカルホストを表す3つのドメイン(IPアドレス)、localhost127.0.0.1::1を指定しています。

$ mkcert localhost 127.0.0.1 ::1

Created a new certificate valid for the following names 📜
 - "localhost"
 - "127.0.0.1"
 - "::1"

The certificate is at "./localhost+2.pem" and the key at "./localhost+2-key.pem" ✅

It will expire on 20 October 2024 🗓

作成されたlocalhost+2.pem(サーバ証明書)とlocalhost+2-key.pem(サーバ秘密鍵)はRustのソースコードで使用します。

ソースコード

actix-webの公式サイトのHTTP/2のページを参考にしています。

main.rs
use actix_web::{get, App, HttpRequest, HttpServer, Responder, HttpResponse};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};

#[get("/")]
async fn index(_req: HttpRequest) -> impl Responder {
    HttpResponse::Ok()
        .content_type("text/plain")
        .body("welcome!!!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let mut builder = SslAcceptor::mozilla_modern_v5(SslMethod::tls_server()).unwrap();
    builder.set_private_key_file("localhost+2-key.pem", SslFiletype::PEM).unwrap();
    builder.set_certificate_chain_file("localhost+2.pem").unwrap();

    HttpServer::new(|| App::new().service(index))
        .bind_openssl("0.0.0.0:8080", builder)?
        .run()
        .await
}

SslAcceptor::mozilla_modern_v5メソッドはMozillaのサーバサイドTLS勧告バージョン5で定義されているConfigurationのうちの一つのモダンを利用します。プロトコルはtlsとdtlsを選択できますがここではSslMethod::tls_serverメソッドでtlsを選択しています。set_private_key_fileメソッドでサーバの秘密鍵(localhost+2-key.pem)、set_certificate_chain_fileメソッドでサーバ証明書(localhost+2.pem)を指定します。

MozillaのサーバサイドTLS勧告ではオールド、インターメディエイト、モダンの3つの構成を定義していますが詳しくはリンクを張っておきます。

ビルド&実行

cargo runコマンドでコンパイル&実行します。

$ cargo run
   Compiling web v0.1.0 (/web)
    Finished dev [unoptimized + debuginfo] target(s) in 3.28s
     Running `target/debug/web`

ブラウザで接続

証明書リストへの追加

作成した自己認証局の証明書(rootCA.pem)をブラウザの証明書リストへ追加します。ここではChromeを使います。Chromeのアドレス欄にchrome://settings/certificatesと入力して認証局-->インポートと進んでrootCA.pemを選択肢します。

Screenshot from 2022-07-21 01-36-53.png

ウェブサイトの識別でこの証明書を信頼しますをチェックしてOKを押します。

Screenshot from 2022-07-21 01-37-51.png

認証局リストにorg-mkcert~~~の項目があれば完了です。

Screenshot from 2022-07-21 01-38-52.png

接続

chromeで https://localhost:8080 に接続して「welcome!!!」が表示されて「この接続は保護されています」と出ているのでOKそうです。

Screenshot from 2022-07-21 12-45-41.png

rustプログラムはdockerコンテナで動かしていて、ホストの8080番ポートとコンテナの8080番ポートを対応させているのでlocalhost:8080にアクセスしています。

curlで接続

curlコマンドでhttps接続するときは --cacert オプションで認証局証明書を指定すれば接続できます。

$ curl https://localhost:8080 --cacert rootCA.pem 
welcome!!!

postmanで接続

postmanでhttps接続する場合もpostmanに認証局証明書を登録します。メニュー-->Settingsと進んでCertificatesタブの CA CertificatesをONにします。 PEM filerootCA.pem を指定します。この状態でGETメソッドで https://localhost:8080 にアクセスすると「welcome!!!」が返ってくるのでOKそうです。

Screenshot from 2022-07-21 14-37-49.png

Screenshot from 2022-07-21 14-38-31.png

Screenshot from 2022-07-21 14-39-11.png

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1
Help us understand the problem. What are the problem?