chore: 初始化 opencode 配置
This commit is contained in:
277
skill/mqtts-developer/mqtts-quick-reference.md
Normal file
277
skill/mqtts-developer/mqtts-quick-reference.md
Normal file
@@ -0,0 +1,277 @@
|
||||
# MQTTS Quick Reference
|
||||
|
||||
## Quick Start
|
||||
For fast MQTTS setup with default settings:
|
||||
|
||||
```bash
|
||||
# 1. Set domain
|
||||
DOMAIN="mq.example.com"
|
||||
|
||||
# 2. Verify DNS
|
||||
dig $DOMAIN +short
|
||||
|
||||
# 3. Issue certificate
|
||||
~/.acme.sh/acme.sh --issue --dns dns_ali -d $DOMAIN --keylength 2048
|
||||
|
||||
# 4. Install with auto-reload
|
||||
~/.acme.sh/acme.sh --install-cert -d $DOMAIN \
|
||||
--cert-file /root/certs/$DOMAIN/cert.pem \
|
||||
--key-file /root/certs/$DOMAIN/key.pem \
|
||||
--fullchain-file /root/certs/$DOMAIN/fullchain.pem \
|
||||
--reloadcmd "docker restart emqx"
|
||||
|
||||
# 5. Fix permissions
|
||||
chmod 755 /root/certs/$DOMAIN
|
||||
chmod 644 /root/certs/$DOMAIN/*.pem
|
||||
|
||||
# 6. Recreate EMQX container with cert mount
|
||||
docker stop emqx && docker rm emqx
|
||||
docker run -d --name emqx --restart unless-stopped \
|
||||
-p 1883:1883 -p 8083-8084:8083-8084 -p 8883:8883 -p 18083:18083 \
|
||||
-v /root/emqx/data:/opt/emqx/data \
|
||||
-v /root/emqx/log:/opt/emqx/log \
|
||||
-v /root/certs/$DOMAIN:/opt/emqx/etc/certs:ro \
|
||||
emqx/emqx:5.8.8
|
||||
|
||||
# 7. Verify
|
||||
sleep 5
|
||||
docker exec emqx emqx ctl listeners | grep ssl
|
||||
openssl s_client -connect $DOMAIN:8883 -servername $DOMAIN < /dev/null
|
||||
```
|
||||
|
||||
## Client Connection
|
||||
|
||||
### Python (System CA)
|
||||
```python
|
||||
import paho.mqtt.client as mqtt
|
||||
import ssl
|
||||
|
||||
client = mqtt.Client()
|
||||
client.username_pw_set("user", "pass")
|
||||
client.tls_set(cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2)
|
||||
client.connect("mq.example.com", 8883, 60)
|
||||
```
|
||||
|
||||
### Python (with fullchain.pem)
|
||||
```python
|
||||
client.tls_set(ca_certs="fullchain.pem", cert_reqs=ssl.CERT_REQUIRED)
|
||||
client.connect("mq.example.com", 8883, 60)
|
||||
```
|
||||
|
||||
### Node.js
|
||||
```javascript
|
||||
const mqtt = require('mqtt');
|
||||
const client = mqtt.connect('mqtts://mq.example.com:8883', {
|
||||
username: 'user',
|
||||
password: 'pass',
|
||||
rejectUnauthorized: true
|
||||
});
|
||||
```
|
||||
|
||||
### ESP32
|
||||
```cpp
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <PubSubClient.h>
|
||||
|
||||
const char* root_ca = "-----BEGIN CERTIFICATE-----\n"...; // from fullchain.pem
|
||||
|
||||
WiFiClientSecure espClient;
|
||||
PubSubClient client(espClient);
|
||||
|
||||
void setup() {
|
||||
espClient.setCACert(root_ca);
|
||||
client.setServer("mq.example.com", 8883);
|
||||
client.connect("ESP32", "user", "pass");
|
||||
}
|
||||
```
|
||||
|
||||
## Common Commands
|
||||
|
||||
### Certificate Management
|
||||
```bash
|
||||
# List certificates
|
||||
~/.acme.sh/acme.sh --list
|
||||
|
||||
# Check certificate info
|
||||
~/.acme.sh/acme.sh --info -d $DOMAIN
|
||||
|
||||
# Force renewal
|
||||
~/.acme.sh/acme.sh --renew -d $DOMAIN --force
|
||||
|
||||
# View certificate details
|
||||
openssl x509 -in /root/certs/$DOMAIN/cert.pem -text -noout
|
||||
|
||||
# Check expiry
|
||||
openssl x509 -in /root/certs/$DOMAIN/cert.pem -noout -dates
|
||||
|
||||
# Get fingerprint
|
||||
openssl x509 -in /root/certs/$DOMAIN/cert.pem -noout -fingerprint -sha256
|
||||
```
|
||||
|
||||
### EMQX Management
|
||||
```bash
|
||||
# Check listeners
|
||||
docker exec emqx emqx ctl listeners
|
||||
|
||||
# Check connections
|
||||
docker exec emqx emqx ctl broker stats
|
||||
|
||||
# View logs
|
||||
docker logs emqx --tail 100 -f
|
||||
|
||||
# Restart container
|
||||
docker restart emqx
|
||||
|
||||
# Check certificate files
|
||||
docker exec emqx ls -l /opt/emqx/etc/certs/
|
||||
```
|
||||
|
||||
### Testing
|
||||
```bash
|
||||
# Test SSL connection
|
||||
openssl s_client -connect $DOMAIN:8883 -servername $DOMAIN
|
||||
|
||||
# Test with mosquitto
|
||||
mosquitto_pub -h $DOMAIN -p 8883 \
|
||||
--capath /etc/ssl/certs \
|
||||
-t "test/topic" -m "hello" \
|
||||
-u "username" -P "password"
|
||||
|
||||
# Test with custom CA
|
||||
mosquitto_pub -h $DOMAIN -p 8883 \
|
||||
--cafile fullchain.pem \
|
||||
-t "test/topic" -m "hello" \
|
||||
-u "username" -P "password"
|
||||
```
|
||||
|
||||
### Backup & Export
|
||||
```bash
|
||||
# Create backup
|
||||
cd /root/certs
|
||||
tar czf $DOMAIN-backup-$(date +%Y%m%d).tar.gz $DOMAIN/
|
||||
|
||||
# Download (from local machine)
|
||||
scp root@SERVER_IP:/root/certs/$DOMAIN-backup-*.tar.gz ./
|
||||
|
||||
# Extract public key
|
||||
openssl rsa -in $DOMAIN/key.pem -pubout -out $DOMAIN/public.pem
|
||||
|
||||
# Get public key fingerprint
|
||||
openssl rsa -in $DOMAIN/key.pem -pubout 2>/dev/null | openssl md5
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### DNS not resolving
|
||||
```bash
|
||||
dig $DOMAIN +short
|
||||
nslookup $DOMAIN
|
||||
# Wait 5-10 minutes for propagation
|
||||
```
|
||||
|
||||
### Certificate issuance failed
|
||||
```bash
|
||||
# Check DNS API credentials
|
||||
cat ~/.acme.sh/account.conf | grep Ali_
|
||||
|
||||
# Test with debug mode
|
||||
~/.acme.sh/acme.sh --issue --dns dns_ali -d $DOMAIN --debug 2
|
||||
```
|
||||
|
||||
### SSL connection failed
|
||||
```bash
|
||||
# Check port is open
|
||||
nc -zv $DOMAIN 8883
|
||||
|
||||
# Check firewall
|
||||
iptables -L -n | grep 8883
|
||||
|
||||
# Test with insecure (testing only)
|
||||
mosquitto_pub -h $DOMAIN -p 8883 --insecure -t test -m hello
|
||||
```
|
||||
|
||||
### Container won't start
|
||||
```bash
|
||||
# Check logs
|
||||
docker logs emqx
|
||||
|
||||
# Check permissions
|
||||
ls -la /root/certs/$DOMAIN/
|
||||
|
||||
# Fix permissions
|
||||
chmod 755 /root/certs/$DOMAIN
|
||||
chmod 644 /root/certs/$DOMAIN/*.pem
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Single-Direction TLS (Current Setup)
|
||||
- Client verifies server identity (via certificate)
|
||||
- Server authenticates client (via username/password)
|
||||
- Client needs: System CA OR fullchain.pem
|
||||
- Client does NOT need: server public key, server private key
|
||||
|
||||
### File Purpose
|
||||
- `cert.pem`: Server certificate (contains public key)
|
||||
- `key.pem`: Server private key (CONFIDENTIAL)
|
||||
- `fullchain.pem`: Server cert + intermediate + root CA
|
||||
- `public.pem`: Public key extracted from private key
|
||||
- `cacert.pem`: CA certificate (usually symlink to fullchain)
|
||||
|
||||
### Client Requirements
|
||||
| Client Type | Needs | Reason |
|
||||
|-------------|-------|--------|
|
||||
| PC/Mac/Server | Nothing (system CA) | OS trusts ZeroSSL |
|
||||
| Android/iOS | Nothing (system CA) | OS trusts ZeroSSL |
|
||||
| ESP32/Arduino | fullchain.pem | No system CA access |
|
||||
| Docker | System CA or fullchain.pem | Depends on base image |
|
||||
|
||||
### Auto-Renewal
|
||||
- Cron: Daily at 00:34
|
||||
- Threshold: 60 days before expiry
|
||||
- Action: Renew cert → Install → Restart EMQX
|
||||
- No client action needed (unless using public key pinning)
|
||||
|
||||
## Important Notes
|
||||
|
||||
1. **Domain Required**: Must use domain name (mq.example.com), NOT IP address
|
||||
2. **DNS Must Resolve**: A record must point to server before certificate issuance
|
||||
3. **Port 8883**: Ensure firewall allows port 8883 for MQTTS
|
||||
4. **Time Sync**: Server and client clocks must be accurate for TLS
|
||||
5. **Key Reuse**: acme.sh reuses private key by default (public key stays same)
|
||||
6. **Certificate Chain**: Modern clients need full chain, not just server cert
|
||||
|
||||
## Quick Diagnosis
|
||||
|
||||
### Check Everything
|
||||
```bash
|
||||
DOMAIN="mq.example.com"
|
||||
|
||||
echo "=== DNS ==="
|
||||
dig $DOMAIN +short
|
||||
|
||||
echo "=== Certificate ==="
|
||||
openssl x509 -in /root/certs/$DOMAIN/cert.pem -noout -dates -subject
|
||||
|
||||
echo "=== EMQX Container ==="
|
||||
docker ps | grep emqx
|
||||
|
||||
echo "=== Listeners ==="
|
||||
docker exec emqx emqx ctl listeners | grep -A 5 ssl
|
||||
|
||||
echo "=== SSL Test ==="
|
||||
timeout 5 openssl s_client -connect $DOMAIN:8883 -servername $DOMAIN < /dev/null 2>&1 | grep -E "Verify return|subject=|issuer="
|
||||
|
||||
echo "=== Auto-Renewal ==="
|
||||
~/.acme.sh/acme.sh --list | grep $DOMAIN
|
||||
|
||||
echo "=== Cron ==="
|
||||
crontab -l | grep acme
|
||||
```
|
||||
|
||||
## Reference
|
||||
- EMQX Config: `/opt/emqx/etc/emqx.conf` (in container)
|
||||
- Certificates: `/root/certs/$DOMAIN/` (on host) → `/opt/emqx/etc/certs/` (in container)
|
||||
- acme.sh: `~/.acme.sh/`
|
||||
- Logs: `/root/emqx/log/` (host) or `docker logs emqx`
|
||||
- Dashboard: http://SERVER_IP:18083 (default: admin/public)
|
||||
Reference in New Issue
Block a user