転送先毎にサブドメインを用意しておき、TLS の SNI 拡張と Nginx の stream_ssl_module モジュールを利用して、SNI 拡張のドメイン名で転送先を切り替えます。
Nginx
次の設定では、外からのアクセスは 443 ポートでのみ待ち受けていますが、www1.example.com で接続してきた場合は HTTP サーバ(8080)へ、www2.example.com で接続してきた場合は MQTT ブローカー(1883)へ転送しています。
ngixn.conf
http {
server {
listen 127.0.0.1:8080;
server_name www1.example.com;
location / {
root html;
}
}
}
stream {
upstream www1.example.com {
server 127.0.0.1:8080;
}
upstream www2.example.com {
server 127.0.0.1:1883;
}
server {
listen 443 ssl;
proxy_pass $ssl_server_name;
ssl_certificate /home/ubuntu/certs/server.pem;
ssl_certificate_key /home/ubuntu/certs/server.key;
ssl_protocols TLSv1.2;
}
}
証明書
SANs に www1.example.com と www2.example.com を指定した証明書を用意します。
$ openssl x509 -noout -text -in server.pem | grep -A1 'X509v3 Subject Alternative Name'
X509v3 Subject Alternative Name:
DNS:www1.example.com, DNS:www2.example.com
動作の確認
HTTP (www1.example.com)
$ curl -s -D - -o /dev/null -X GET --tlsv1.2 --cacert ca.pem https://www1.example.com
HTTP/1.1 200 OK
Server: nginx/1.13.7
Date: Fri, 19 Jan 2018 17:13:29 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Fri, 19 Jan 2018 15:34:24 GMT
Connection: keep-alive
ETag: "5a621000-264"
Accept-Ranges: bytes
MQTT (www2.example.com)
paho-mqtt で subscriber と publisher を用意して確認します。
- 最初に subscriber.py を実行しておき、別途 publisher.py を実行
(vs) $ python subscriber.py
b'Hello, World'
- subscriber
import ssl
import paho.mqtt.client as mqtt
def on_message(client, userdata, msg):
print(str(msg.payload))
client = mqtt.Client()
client.tls_set("ca.pem", cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2)
client.on_message = on_message
client.connect("www2.example.com", 443, 60)
client.subscribe("a/b")
client.loop_forever()
- publisher
import ssl
import paho.mqtt.client as mqtt
client = mqtt.Client()
client.tls_set("ca.pem", cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2)
client.connect("www2.example.com", 443, 60)
client.publish("a/b", "Hello, World")