1.実行環境
・Windows10にVirtualBoxの仮想マシンがインストールされている
・仮想マシンのOSはCentOS8で、Apatch(HTTPサーバ)がインストールされている
(1)HTTPサーバのバージョンの確認
# httpd -v
(2)httpサーバの起動
# systemctl start httpd
# systemctl is-active httpd
(3)ブラウザから接続
/var/www/html
のフォルダにあるindex.html
が表示される
2.HttpサーバのSSL化
(1)SSLモジュールのインストール
ApacheでSSLを利用ため必要なソフトウェア
・OpenSSL:SSLを利用するために必要なソフトウェア
・mod_ssl:OpenSSLを使ってApacheをSSLに対応させるモジュール
OpenSSLはCentOSをデフォルト設定でインストールされる。OpenSSLがインストールされているかどうか確認する。
# rpm -qa | grep openssl
インストールされていないときは、下記のコマンドでインストールする。
# yum install openssl
バージョンの確認
# openssl version
CentOS8が2021年末にサポート切れでミラーサイトが停止され、パッケージのインストールに失敗した。
(対策)
下記のファイルで、参照先のリポジトリをミラーサイトからhttp://vault.centos.orgに変更する。
/etc/yum.repos.d/CentOS*repo
①CentOS-Linux-AppStream.repo
②CentOS-Linux-BaseOS.repo
:
変更前:
[appstream]
name=CentOS Linux $releasever – AppStream
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=AppStream&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/AppStream/$basearch/os/
:
↓
mirrorlist=・・・をコメント化し、#baseurl=http://mirror.centos.org/・・・のコメントを外し、”mirror”を”vault”に変更
変更後:
[appstream]
name=CentOS Linux $releasever – AppStream
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=AppStream&infra=$infra
baseurl=http://vault.centos.org/$contentdir/$releasever/AppStream/$basearch/os/
参照先のリポジトリを変更したあと再度、下記コマンドでインストールする
# yum install mod_ssl
下記コマンドでインストールされたことを確認する
# rpm -qa | grep mod_ssl
※rpmコマンド
オプション-q:問い合わせ(パッケージ情報の表示と検索)
-a:情報問い合わせ関連(-q、-Vと一緒に使用するオプション)でall
(4)秘密鍵とサーバ証明書の作成
・秘密鍵の作成
# openssl genrsa > server.key
・サーバ証明書の作成
CSRファイル(認証局にサーバ証明書を発行してもらう時に使用するファイル)を作成
# openssl req -new -key server.key > server.csr
下記はEnterでテストでは入力無しとした
:
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server’s hostname) []:
Email Address []:
Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
・サーバ証明書への署名
本来はこのCSRファイルを認証局に渡して署名してもらう必要があるが、ここではテストのため、自分で署名するため、以下のコマンドを実行。
# openssl x509 -req -signkey server.key < server.csr > server.crt
(5)秘密鍵とサーバ証明書の配置
作成した鍵と証明書を/etc/httpd/以下に配置する。
ここでは
/etc/httpd/conf/ssl.keyおよび/etc/httpd/conf/ssl.crt配下に置く
# mkdir /etc/httpd/conf/ssl.key
# mkdir /etc/httpd/conf/ssl.crt
# mv server.key /etc/httpd/conf/ssl.key/
# mv server.crt /etc/httpd/conf/ssl.crt/
(6)SSLモジュールの設定
/etc/httpd/conf.d/ssl.confの中に、配置した鍵と証明書のパスを設定する。
# vi /etc/httpd/conf.d/ssl.conf
:
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateFile /etc/httpd/conf/ssl.crt/server.crt
:
#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
SSLCertificateKeyFile /etc/httpd/conf/ssl.key/server.key
:
(7)Apacheを再起動して接続する
# systemctl restart httpd
# systemctl is-active httpd
ssl.confを修正したあと、起動に失敗する
SELinuxが影響していると考えられるため、テストではSELinuxを無効とする
現在
[root@localhost conf.d]# getenforce
Enforcing
一時的にpermissiveモードに変更
[root@localhost conf.d]# getenforce
Permissive
上記の変更をしてhttpサーバが起動できた
[root@localhost conf.d]# systemctl restart httpd
[root@localhost conf.d]# systemctl is-active httpd
active
(8)ブラウザからHttpsサーバに接続
CentOSのディスクトップのブラウザから接続
https://localhost
サーバから取得したサーバ証明書では、ルート証明書との正当性が確認できないため、エラーになったと考えられる。
「詳細情報」を選択して、次に進み、強制的に許可する。
また、ホストPC(Windows10)のブラウザからアクセスしたとき
http://localhostでは接続できるが、https://localhostでは接続できない
コマンドプロンプトからcurlコマンドで、SSL接続で証明書エラーをスキップして接続することで、httpsサーバからのレスポンスが正常に処理される。
# curl -k https://localhost
3.Httpsクライアントの作成
(1)openssl-devel パッケージのインストール
openssl-devel は各種の暗号化アルゴリズムとプロトコルをサポートしたアプリケーションを開発するために必要な静的ライブラリとヘッダーファイルが含まれている。
# yum install openssl-devel
(2)クライアントのソースファイル
client.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <openssl/ssl.h> #include <openssl/err.h> int main(void) { int mysocket; struct sockaddr_in server;// ホストのIPアドレスなど情報を保持する構造体 struct addrinfo hints, *res; SSL *ssl; SSL_CTX *ctx; char msg[100]; char *host = "localhost"; char *path = "/"; int port = 443; // IPアドレスの解決 memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET;//インターネットプロトコル hints.ai_socktype = SOCK_STREAM; char *service = "https"; int err = 0; if ((err = getaddrinfo(host, service, &hints, &res)) != 0) { fprintf(stderr, "Fail to resolve ip address - %d\n", err); return EXIT_FAILURE; } //ソケット if ((mysocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) { fprintf(stderr, "Fail to create a socket.\n"); return EXIT_FAILURE; } //コネクト if (connect(mysocket, res->ai_addr, res->ai_addrlen) != 0) { printf("Connection error.\n"); return EXIT_FAILURE; } //SSLセットアップ SSL_load_error_strings();/OpenSSLのエラー文の読み込み SSL_library_init();//SSLの初期化 //SSL_CTX構造体生成 ctx = SSL_CTX_new(SSLv23_client_method()); //引数は使用するプロトコルの種類 //SSLの構造体生成 ssl = SSL_new(ctx); err = SSL_set_fd(ssl, mysocket);//SSL構造体とソケットの関連付け SSL_connect(ssl);/サーバとハンドシェイクを行う printf("Conntect to %s\n", host); //HTTPリクエストの送信 sprintf(msg, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", path, host); SSL_write(ssl, msg, strlen(msg)); int buf_size = 256; char buf[buf_size]; int read_size; //レスポンスの受信 do { read_size = SSL_read(ssl, buf, buf_size); write(1, buf, read_size); } while(read_size > 0); //SSLとソケットの終了処理 SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx); ERR_free_strings(); close(mysocket); return EXIT_SUCCESS; } |
(3)クライアントソースファイルのコンパイル
# gcc client.c -o client -lssl -lcrypto
(4)httpsサーバの起動
# setenforce 0
# systemctl start httpd
(5)httpsクライアントの起動
# ./client
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Conntect to localhost HTTP/1.1 200 OK Date: Sun, 22 May 2022 00:50:46 GMT Server: Apache/2.4.37 (centos) OpenSSL/1.1.1k Last-Modified: Sun, 08 May 2022 01:59:00 GMT ETag: "c3-5de766f65c100" Accept-Ranges: bytes Content-Length: 195 Connection: close Content-Type: text/html; charset=UTF-8 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>画像テスト</title> </head> <body> <p>画像のテスト</p> <img src="test.jpg"> </body> </html> |
httpサーバにsslで接続できて、レスポンスのhtmlファイルが返却された
The end