LoginSignup
11

More than 5 years have passed since last update.

Nginx を利用して同一ポートの待ち受けで複数のプロトコルを扱う

Posted at

転送先毎にサブドメインを用意しておき、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")

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
  3. You can use dark theme
What you can do with signing up
11