MQTTでもProxy経由でAWS IoT Coreに接続する

AWS IoT Device SDK v2 for Pythonが更新されまして、リリースノートの中にMQTTでもプロキシ経由でアクセスできるようになったよ的な記載がありました。

> Http proxies can now be used with direct mqtt connections, not just websockets

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180441/7ced5817-94d5-2fa2-13d5-aa1ee9ab9e63.png)

https://github.com/aws/aws-iot-device-sdk-python-v2/releases/tag/v1.5.17



# 解説

```python
proxy_options = None
if (args.proxy_host):
    proxy_options = http.HttpProxyOptions(host_name=args.proxy_host, port=args.proxy_port)
```

でつくった`proxy_options`を

```python
mqtt_connection = mqtt_connection_builder.mtls_from_path(
    endpoint=args.endpoint,
    port=args.port,
    cert_filepath=args.cert,
    pri_key_filepath=args.key,
    client_bootstrap=client_bootstrap,
    ca_filepath=args.root_ca,
    on_connection_interrupted=on_connection_interrupted,
    on_connection_resumed=on_connection_resumed,
    client_id=args.client_id,
    clean_session=False,
    keep_alive_secs=6,
    http_proxy_options=proxy_options)
```

に渡すみたいですね。かんたんですね。

サンプルがあったので、やってみました。

# AWS IoT Device SDK v2 for Pythonのインストール

```bash
python3 -m pip install awsiotsdk
```

# サンプルの実行（プロキシなし）

このサンプルを実行してみます。
https://github.com/aws/aws-iot-device-sdk-python-v2/blob/main/samples/pubsub.py

```bash
python3 pubsub.py --endpoint <endpoint> --root-ca <file> --cert <file> --key <file>
```

```console
AWS libcrypto resolve: searching process and loaded modules
AWS libcrypto resolve: found static aws-lc HMAC symbols
AWS libcrypto resolve: found static aws-lc libcrypto 1.1.1 EVP_MD symbols
Connecting to a33z4z6fq9g7s5-ats.iot.ap-northeast-1.amazonaws.com with client ID 'test-c12663b2-a914-4da1-8ffa-f40d0ec17b08'...
Connected!
Subscribing to topic 'test/topic'...
Subscribed with QoS.AT_LEAST_ONCE
Sending 10 message(s)
Publishing message to topic 'test/topic': Hello World! [1]
Received message from topic 'test/topic': b'Hello World! [1]'
Publishing message to topic 'test/topic': Hello World! [2]
Received message from topic 'test/topic': b'Hello World! [2]'
Publishing message to topic 'test/topic': Hello World! [3]
Received message from topic 'test/topic': b'Hello World! [3]'
Publishing message to topic 'test/topic': Hello World! [4]
Received message from topic 'test/topic': b'Hello World! [4]'
Publishing message to topic 'test/topic': Hello World! [5]
Received message from topic 'test/topic': b'Hello World! [5]'
Publishing message to topic 'test/topic': Hello World! [6]
Received message from topic 'test/topic': b'Hello World! [6]'
Publishing message to topic 'test/topic': Hello World! [7]
Received message from topic 'test/topic': b'Hello World! [7]'
Publishing message to topic 'test/topic': Hello World! [8]
Received message from topic 'test/topic': b'Hello World! [8]'
Publishing message to topic 'test/topic': Hello World! [9]
Received message from topic 'test/topic': b'Hello World! [9]'
Publishing message to topic 'test/topic': Hello World! [10]
Received message from topic 'test/topic': b'Hello World! [10]'
10 message(s) received.
Disconnecting...
Disconnected!
```

うまくいきました。

# Proxyサーバー（Squid）の起動

Squidを導入します。

```bash
sudo apt update
DEBIAN_FRONTEND=noninteractive sudo apt install -y squid --no-install-recommends
```

Squidを起動します。フロントエンドで起動してみます。

```bash
sudo squid -N
```

試しにCurlでプロキシ経由でアクセスできるか確認します。

ヘッダーだけ取得するパラメーターはこちらを参照しました
https://qiita.com/yousan/items/fcc15e1046939c465ab7

```bash
curl https://www.yahoo.co.jp -x localhost:3128 -D - -s  -o /dev/null
```

```console
HTTP/1.1 200 Connection established

HTTP/2 200 
accept-ranges: none
cache-control: private, no-cache, no-store, must-revalidate
content-type: text/html; charset=UTF-8
date: Sat, 29 May 2021 07:31:54 GMT
expires: -1
pragma: no-cache
set-cookie: B=el7dv9hgb3rfa&b=3&s=dn; expires=Tue, 30-May-2023 07:31:54 GMT; path=/; domain=.yahoo.co.jp
vary: Accept-Encoding
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-vcap-request-id: a5c1689e-8dcd-4642-78a3-738a296485f7
x-xss-protection: 1; mode=block
age: 0
server: ATS
set-cookie: XB=el7dv9hgb3rfa&b=3&s=dn; expires=Tue, 30-May-2023 07:31:54 GMT; path=/; domain=.yahoo.co.jp; secure; samesite=none
```

プロキシサーバーの準備はできました。

# サンプルの実行（プロキシあり）

パラメーターにプロキシサーバーのホスト名とポートを指定するだけです。

```bash
python3 pubsub.py --endpoint <endpoint> --root-ca <file> --cert <file> --key <file> --proxy-host localhost --proxy-port 3128
```

```console
AWS libcrypto resolve: searching process and loaded modules
AWS libcrypto resolve: found static aws-lc HMAC symbols
AWS libcrypto resolve: found static aws-lc libcrypto 1.1.1 EVP_MD symbols
Connecting to a33z4z6fq9g7s5-ats.iot.ap-northeast-1.amazonaws.com with client ID 'test-4c29ac6f-2a90-4ea5-b80b-99968f0e2d12'...
Connected!
Subscribing to topic 'test/topic'...
Subscribed with QoS.AT_LEAST_ONCE
Sending 10 message(s)
Publishing message to topic 'test/topic': Hello World! [1]
Received message from topic 'test/topic': b'Hello World! [1]'
Publishing message to topic 'test/topic': Hello World! [2]
Received message from topic 'test/topic': b'Hello World! [2]'
Publishing message to topic 'test/topic': Hello World! [3]
Received message from topic 'test/topic': b'Hello World! [3]'
Publishing message to topic 'test/topic': Hello World! [4]
Received message from topic 'test/topic': b'Hello World! [4]'
Publishing message to topic 'test/topic': Hello World! [5]
Received message from topic 'test/topic': b'Hello World! [5]'
Publishing message to topic 'test/topic': Hello World! [6]
Received message from topic 'test/topic': b'Hello World! [6]'
Publishing message to topic 'test/topic': Hello World! [7]
Received message from topic 'test/topic': b'Hello World! [7]'
Publishing message to topic 'test/topic': Hello World! [8]
Received message from topic 'test/topic': b'Hello World! [8]'
Publishing message to topic 'test/topic': Hello World! [9]
Received message from topic 'test/topic': b'Hello World! [9]'
Publishing message to topic 'test/topic': Hello World! [10]
Received message from topic 'test/topic': b'Hello World! [10]'
10 message(s) received.
Disconnecting...
Disconnected!
```

できました。