[C/C++]libwebsocketsを試してみる。その3。SSL通信を試す。

libwebsocketsのサンプルでSSL通信を試す。
まず、libwebsocketsのサンプルで試してみます。
SSL通信によりサンプルサーバーを動作させるにはconfigureにオプションを付加してMakefileを作ります。

$./congifure --enable-openssl
$ make clean
$ make && sudo make install

test-serverにあるlibwebsockets-test-serverを起動します。
SSL通信を有効にするにはパラメータ付きで起動させます。

$ ./libwebsockets-test-server -h
Usage: test-server [--port=<p>] [--ssl] [-d <log bitfield>]

起動

$ ./libwebsockets-test-server --ssl
lwsts[25447]: libwebsockets test server - (C) Copyright 2010-2013 Andy Green <andy@warmcat.com> - licensed under LGPL2.1
lwsts[25447]: Initial logging level 7
lwsts[25447]: Library version: 1.2 
lwsts[25447]:  Started with daemon pid 0
lwsts[25447]:  static allocation: 5472 + (12 x 1024 fds) = 17760 bytes
lwsts[25447]:  canonical_hostname = ubuntu
lwsts[25447]:  Compiled with OpenSSL support
lwsts[25447]:  Using SSL mode
lwsts[25447]:  per-conn mem: 184 + 1328 headers + protocol rx buf
lwsts[25447]:  Listening on port 7681

ブラウザからアクセスしてみる。
httpsでアクセスします。サンプルの認証鍵を使用しているので、ブラウザが信頼されないサイト、とか、セキュリティ証明書に問題あるとかいわれますが、続行して接続してみます。
Img20130317011820
※ちなみに、IE10ではHTMLは表示されますが、WebSocketの部分は動作しませんでした。たぶんセキュリティかなぁ。

その2のチャットサーバーをSSL通信化。
その2で作成したチャットソフトをSSL通信化させてみます。SSLの認証関連が面倒なので、サンプルサーバー同様、Webサーバー経由でhtmlをロードさせてからhtmlの中でWebSocketを使ってみます。

今回の実行環境
Ubuntu 12.04 LTS
Apache/2.2.22
OpenSSL 1.0.1
Windows7(クライアント実行環境)

apache2+SSLの準備
apache2+SSLを設定し、そこで設定した認証鍵をWebSocketサーバーで使用したいと思います。
今回はテストなのでSSL通信に必要な設定はサンプル等を使用します。

apache2+SSLのデフォルト設定を使用。

$ sudo aptitude -y install apache2
$ sudo a2enmod ssl
$ sudo a2ensite default-ssl
$ sudo /etc/init.d/apache2 restart

default-sslが使用する鍵のパス
設定ファイル:/etc/apache2/sites-available/default-ssl

SSLCertificateFile    /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

チャットフォームの設置
DocumentRoot(/var/www)にhtmlファイルを保存します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>WebSocket Sample</title>
</head>
<body>
    <div class="page">
        <header>
            <div id="title">
                <h1>Chat</h1>
            </div>
        </header>
        <section id="main">
        URI <input id="uri" type="text" />
        <input type="button" value="Connect" onClick="connect()" /><br>
		SEND<input id="chatmessage" type="text" />
		<input type="button" value="Send" onClick="send()" />
		<hr />
		<div id="log"></div>
		<script type="text/javascript">
			var ws;
			
			function connect(){
				if ("WebSocket" in window) {
					ws = new WebSocket(document.querySelector("#uri").value);
				} else if ("MozWebSocket" in window) {
					ws = new MozWebSocket(document.querySelector("#uri").value);
				}
				
				ws.onmessage = function(event){
				    output(event.data);
				}
				
				ws.onopen = function(event){
				    output("WebSocket Open!");
				}

				ws.onclose = function(event){
				    output("WebSocket Close.");
				}				
			}	
			
			function send(){
			    var str = document.querySelector("#chatmessage");
			    ws.send(str.value);
			    str.value="";
			}

			function disconnect(){
				ws.close();
				ws = null;
			}
			
			function output(str) {
			    document.getElementById("log").innerHTML += str + "<hr />";
			}
			
		</script>
        </section>
        <footer>
        </footer>
    </div>
</body>
</html>

サーバー側の改修は楽。
ソース

int main()
{
	int n = 0;
	struct libwebsocket_context *context;
	int opts = 0;
	char interface_name[128] = "";
	const char *iface = NULL;
	int syslog_options = LOG_PID | LOG_PERROR;
	unsigned int oldus = 0;
	struct lws_context_creation_info info;
	int debug_level = 7;
	
	memset(&info, 0, sizeof info);
	info.port = 7681;
	
	lws_set_log_level(debug_level, lwsl_emit_syslog);
	

	info.iface = iface;
	info.protocols = protocols;
    
//	info.ssl_cert_filepath = NULL;
//	info.ssl_private_key_filepath = NULL;
	
	info.ssl_cert_filepath = "/etc/ssl/certs/ssl-cert-snakeoil.pem";
	info.ssl_private_key_filepath = "/etc/ssl/private/ssl-cert-snakeoil.key";
    
	info.gid = -1;
	info.uid = -1;
	info.options = opts;
	
	signal(SIGINT, sighandler);
	
	setlogmask(LOG_UPTO (LOG_DEBUG));
	openlog("lwsts", syslog_options, LOG_DAEMON);
	
    lwsl_notice("libwebsockets chat server -\n");
	
    context = libwebsocket_create_context(&info);
	if (context == NULL) {
		lwsl_err("libwebsocket init failed\n");
		return -1;
	}
	
	n = 0;
	while (n >= 0 && !force_exit) {
		struct timeval tv;

		gettimeofday(&tv, NULL);

 		n = libwebsocket_service(context, 50);
	}

	libwebsocket_context_destroy(context);

	lwsl_notice("libwebsockets-test-server exited cleanly\n");

	return 0;
}

SSL通信を有効にするにはlws_context_creation_info構造体に認証鍵を指定するだけのようです。

	info.ssl_cert_filepath = "/etc/ssl/certs/ssl-cert-snakeoil.pem";
	info.ssl_private_key_filepath = "/etc/ssl/private/ssl-cert-snakeoil.key";

コンパイル。

$g++ cppserver.cpp -lwebsockets -o wsserver_ssl

起動してみる。尚、デフォルトではSSL通信用の認証鍵のパーミッションが無いのでsudoで実行します。

$ sudo ./wsserver_ssl
[sudo] password for user: 
lwsts[27128]: libwebsockets chat server -
lwsts[27128]: Initial logging level 7
lwsts[27128]: Library version: 1.2 
lwsts[27128]:  Started with daemon pid 0
lwsts[27128]:  static allocation: 5472 + (12 x 1024 fds) = 17760 bytes
lwsts[27128]:  canonical_hostname = ubuntu
lwsts[27128]:  Compiled with OpenSSL support
lwsts[27128]:  Using SSL mode
lwsts[27128]:  per-conn mem: 184 + 1328 headers + protocol rx buf
lwsts[27128]: LWS_CALLBACK_ADD_POLL_FD
lwsts[27128]:  Listening on port 7681
lwsts[27128]: LWS_CALLBACK_PROTOCOL_INIT

ブラウザでアクセスしてみる。
Img20130317000419

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


This blog is kept spam free by WP-SpamFree.