Skip to content

Commit

Permalink
Support TLS
Browse files Browse the repository at this point in the history
  • Loading branch information
at-wat committed Dec 21, 2019
1 parent 3cc41ea commit fa02b6d
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 9 deletions.
37 changes: 37 additions & 0 deletions client_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package mqtt
import (
"bytes"
"context"
"crypto/tls"
"testing"
)

Expand All @@ -24,6 +25,24 @@ func TestIntegration_Connect(t *testing.T) {
}
}

func TestIntegration_ConnectTLS(t *testing.T) {
cli, err := Dial("tls://localhost:8883",
WithTLSConfig(&tls.Config{InsecureSkipVerify: true}),
)
if err != nil {
t.Fatalf("Unexpected error: '%v'", err)
}

ctx := context.Background()
if err := cli.Connect(ctx, "Client1"); err != nil {
t.Fatalf("Unexpected error: '%v'", err)
}

if err := cli.Disconnect(ctx); err != nil {
t.Fatalf("Unexpected error: '%v'", err)
}
}

func TestIntegration_ConnectWebSocket(t *testing.T) {
cli, err := Dial("ws://localhost:9001")
if err != nil {
Expand All @@ -40,6 +59,24 @@ func TestIntegration_ConnectWebSocket(t *testing.T) {
}
}

func TestIntegration_ConnectWebSockets(t *testing.T) {
cli, err := Dial("wss://localhost:9443",
WithTLSConfig(&tls.Config{InsecureSkipVerify: true}),
)
if err != nil {
t.Fatalf("Unexpected error: '%v'", err)
}

ctx := context.Background()
if err := cli.Connect(ctx, "Client1"); err != nil {
t.Fatalf("Unexpected error: '%v'", err)
}

if err := cli.Disconnect(ctx); err != nil {
t.Fatalf("Unexpected error: '%v'", err)
}
}

func TestIntegration_PublishQoS0(t *testing.T) {
cli, err := Dial("mqtt://localhost:1883")
if err != nil {
Expand Down
56 changes: 51 additions & 5 deletions conn.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mqtt

import (
"crypto/tls"
"errors"
"fmt"
"net"
Expand All @@ -16,26 +17,72 @@ var ErrUnsupportedProtocol = errors.New("unsupported protocol")
var ErrClosedTransport = errors.New("read/write on closed transport")

// Dial creates MQTT client using URL string.
func Dial(urlStr string) (*Client, error) {
func Dial(urlStr string, opts ...DialOption) (*Client, error) {
o := &DialOptions{
Dialer: &net.Dialer{},
}
for _, opt := range opts {
if err := opt(o); err != nil {
return nil, err
}
}
return o.dial(urlStr)
}

// DialOption sets option for Dial.
type DialOption func(*DialOptions) error

// DialOptions stores options for Dial.
type DialOptions struct {
Dialer *net.Dialer
TLSConfig *tls.Config
}

// WithDialer sets dialer.
func WithDialer(dialer *net.Dialer) DialOption {
return func(o *DialOptions) error {
o.Dialer = dialer
return nil
}
}

// WithTLSConfig sets TLS configuration.
func WithTLSConfig(config *tls.Config) DialOption {
return func(o *DialOptions) error {
o.TLSConfig = config
return nil
}
}

func (d *DialOptions) dial(urlStr string) (*Client, error) {
c := &Client{}

u, err := url.Parse(urlStr)
if err != nil {
return nil, err
}
switch u.Scheme {
case "tcp", "mqtt":
conn, err := net.Dial("tcp", u.Host)
conn, err := d.Dialer.Dial("tcp", u.Host)
if err != nil {
return nil, err
}
c.Transport = conn
case "ws":
case "tls", "mqtts":
conn, err := tls.DialWithDialer(d.Dialer, "tcp", u.Host, d.TLSConfig)
if err != nil {
return nil, err
}
c.Transport = conn
case "ws", "wss":
wsc, err := websocket.NewConfig(
fmt.Sprintf("ws://%s:%s%s", u.Hostname(), u.Port(), u.EscapedPath()), "ws://")
fmt.Sprintf("%s://%s:%s%s", u.Scheme, u.Hostname(), u.Port(), u.EscapedPath()), "ws://")
if err != nil {
return nil, err
}
wsc.Protocol = append(wsc.Protocol, "mqtt")
wsc.Dialer = d.Dialer
wsc.TlsConfig = d.TLSConfig
ws, err := websocket.DialConfig(wsc)
if err != nil {
return nil, err
Expand Down Expand Up @@ -79,7 +126,6 @@ func Dial(urlStr string) (*Client, error) {
c.err = err
c.mu.Unlock()
}()

return c, nil
}

Expand Down
5 changes: 5 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ services:
image: eclipse-mosquitto:1.6
ports:
- 1883:1883
- 8883:8883
- 9001:9001
- 9443:9443
volumes:
- ./integration/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro
- ./integration/test.crt:/test.crt:ro
- ./integration/test.key:/test.key:ro
- ./integration/ca.crt:/ca.crt:ro
21 changes: 21 additions & 0 deletions integration/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDZDCCAkygAwIBAgITbfl94Yh57FvuN/1CNZq2u9uxZzANBgkqhkiG9w0BAQsF
ADBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQK
DBNEZWZhdWx0IENvbXBhbnkgTHRkMB4XDTE5MTIyMTE0MjAwNVoXDTI5MTIxODE0
MjAwNVowQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoG
A1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAMOUq3uT1bxlKYwnra9o2MPLEojO4znRMQY09otZi4+U4F2R7ibt
tQK7tKz3XlsTemps6YZSIcl0SzS+HdZtj8D8fzCQc0bCBjwEFBh0jBmzxMC62qNZ
yfOwT5EJYYhCiG1lZHXngVhYm/z2NeUyx/xP10j3lS9a5Dkgbvortee6qGuLJfcA
LvsfNwNQ1E3A7fASZywZgCddDUIL+RK15zOXIG6ugFCs0PeVZdv8KwyHKuRGqFWa
tl4lRapDzJ7uQ5lMIO5OUn+HfwRA2dmMponjDGg/prqXAXSn0AJ1bWhb10+oeP4r
V4c23uzucZblcAlus+c1/k3D29sZ/T6lg+8CAwEAAaNTMFEwHQYDVR0OBBYEFBQt
NTnxwmvXCzudwyLOgUvreAhgMB8GA1UdIwQYMBaAFBQtNTnxwmvXCzudwyLOgUvr
eAhgMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAANTujbG9vG8
tAlNJGNVVgcTjXBSfxMvNGGShi57pPXY32+ZxGuZtvZ2YbCwuP4YkfvhojLNBo7B
bR/h+t+CqplRl5+QiTjxjFWSxPb+YqL1bP4X87jDiVveclgZ82hV5Ezr789DLi7g
E+/KdgEQ+J+RiK1DEBzIVa4Sz0YlvTylVICE3DWVOOhfiUiwJBJsXY5hTXfwwQKH
v05JrCyicJRpT8e4GKaMnOw56yLqafynqtbniOfi74NmdYPTXUjsV/E5PQ4Aaz8J
1TtVhDpfFj08jaVQNjecI8zt9odjJOx145EyjG2/kez+QQGoZP7s9Ncj0nC+Iy8L
9TM35X4tqjA=
-----END CERTIFICATE-----
17 changes: 13 additions & 4 deletions integration/mosquitto.conf
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
listener 1883
listener 9001

#certfile /path/to/cert
#keyfile /path/to/key
#require_certificate false
listener 8883
cafile /ca.crt
keyfile /test.key
certfile /test.crt
require_certificate false

listener 9001
protocol websockets

listener 9443
protocol websockets
cafile /ca.crt
keyfile /test.key
certfile /test.crt
require_certificate false
19 changes: 19 additions & 0 deletions integration/test.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCzCCAfMCFGpaSonan1WUzE1xlFfP9UBGDyLrMA0GCSqGSIb3DQEBCwUAMEIx
CzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0Rl
ZmF1bHQgQ29tcGFueSBMdGQwHhcNMTkxMjIxMTQyMDU4WhcNMjkxMjE4MTQyMDU4
WjBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQK
DBNEZWZhdWx0IENvbXBhbnkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuHbnT3XSyv0D+WjGh7coEgi+yzadiqx4L91Ldi1cxWyy2UVKNKTnAPLy
teCduPHY93z8SqtTX9Cy+4dPfsP8zeqfkqi6aakxsJmoDYS7FYKCCX5ARKXBmttt
PSBdV37ElNnsK2+eFWiTA2/b//3aR93n2XRYfiTsry1nu9oGyw+KAT2h6cI8KVCu
M+zzyeGdWfgm+qpJyDlwavLMkpxhuTGCYdI7/HxkZsnSQphEWe/lmsdLF1GVTwbF
SxDLhOeFisQqvDzIIEN9YkzutMTetVhN7qZoGZOv5kCIcNrrzr6RqySQiyHH28qU
jbx3xhUisnxdeUOUR6E2OjSptf99TQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBK
AkuQq1NL1VFnxDxDarRBlMKihIpItS0r1oothe1Yw4fXE0RVcQm2qJqfYseEDJVk
doaL4ZFq3ZQsAdRMn6IVqSnb/L/2GXpm/k1sh62YdwrK/hVx2dQG/s89VI1EVzKl
qq3T6dXdjy0okmELv9zsP4B6Wvk1VY4uqIBCrOjGujAzBoKE0jk9E7Xi9PhqZ+iY
/e9JGP9+UloFv4W0w5Sp0PwLhQcJCEBDaecH+JFTnVOIuWPs6uwVsZXJ2do60GZm
gtEOe2M9gLvm0FbveeUok6RD1cRh63rLF2Oai/fjcEzRXwRWnOkbbbTrXl4vCuSW
f3JK0OybkC0qdiRrf85T
-----END CERTIFICATE-----
27 changes: 27 additions & 0 deletions integration/test.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuHbnT3XSyv0D+WjGh7coEgi+yzadiqx4L91Ldi1cxWyy2UVK
NKTnAPLyteCduPHY93z8SqtTX9Cy+4dPfsP8zeqfkqi6aakxsJmoDYS7FYKCCX5A
RKXBmtttPSBdV37ElNnsK2+eFWiTA2/b//3aR93n2XRYfiTsry1nu9oGyw+KAT2h
6cI8KVCuM+zzyeGdWfgm+qpJyDlwavLMkpxhuTGCYdI7/HxkZsnSQphEWe/lmsdL
F1GVTwbFSxDLhOeFisQqvDzIIEN9YkzutMTetVhN7qZoGZOv5kCIcNrrzr6RqySQ
iyHH28qUjbx3xhUisnxdeUOUR6E2OjSptf99TQIDAQABAoIBAFarRzMGYOwOxPdC
S0UowSL4COzh1FN7hVy31OTJm3UHBWEgNSVW9VJ006SwzGpA93gQuVk79ghmvjF/
+dHNs9HsEt2NeUh7vmUDTPpNCrmogACF2Rxn5PclccXuluytGx/05Ankf5n/cFOF
ExDL7OsnT+/TwmBCaRJFex+/6MEu1nWsMBbZazQqM/jGDsCXSftISFfuCgiUj9vD
MCEINsq97RGV9cmnmt7/ZrT3Wpy7eD2T9ZbDMxzAKgptcuWyG2NRJ/fArE1Ubgm8
LvTXfpoVVJEFFvm27kQE2YwdO+rGffwHMzSRtt0R4AQ6munKWBtFRCJTnBGmwgH+
YvEUowECgYEA8lNVooPlhWPmlGJSvxM9IIISMhND/Xk+wQuukGbCIz966HpFu8OA
p07Uqi73vYd8dY5ulQFffRnlw+Dk9/VFfs0gYl/pksDRUtww0czeGaFRqnIksH9q
Ocu488EVZ+T76eoia+Prz1kmax2MPPOsS6vQuDeipc3g6sh/jxrkobkCgYEAwt+z
Z/5960Srz/eQKq56XW3LdIlM3+hMW0zAT9LKrpaKLG6KYLMea24R+YygVKOTp3Fo
crALa2m2MwKeP0hKsExVieZDWF/Fvf5XxHAg3yMoXu1toYfSiCuHzPJb5VnxrA5i
QfP9aHVENgZIDDpSef9PRFqBfDubSMcJmR0jEjUCgYEAlgYd2FWMPb8Ru//7dqx0
hbHBjhr7Vuw/e8i9tEzKGIRulYtNrOdmuS5G323glwhQd39M2xdUhOEJrPGJEDJb
ahuY1w7GTsLtVT1ZRCpvvrJvGvU73cGkhE+qG88Ib6AGjlUUJnOfRGnPLTXH4tyB
aP/gYoyfN8N0YibrQi/GKJECgYAIXUu5Ef5bo9XwFkM04cpUykqqVN5c2f61CIVU
p8qVVdbWc2QzJF0Q5WeWG4giOeczj7WY/p9u29m7NMiQFM1H5e7h/WU0nN/C+PDR
eLKggUTRVkWXYloSCDRLArgZDxRFe1SSWiOtYSMtYnWjOLmjjObdGzllmLVgmVJ7
JPoFZQKBgC3y1fThRHbtU44LkO8OooRgmleF87hvrcT1FO3Jww2bMA0vHoKCFrIa
jpoyulamtqH4zEHilmaBY4UBsMQJNIJl9nPe67MZRugOxEvUevQyMP16Fx79aZj3
efNScmxzn0eo/Giszj5rPtBh5Y+MlprHdPGcnEOJ1MHTAxE+IDtH
-----END RSA PRIVATE KEY-----

0 comments on commit fa02b6d

Please sign in to comment.