I’ve been trying to make a simple WAMP RPC based application using Autobahn(Python) and Crossbar. The script connects and everything works when I try using an unsecured WebSocket connection, but I am not able to figure out what I am doing wrong when connecting using SSL Certificates.
Crossbar config.json
:-
{
"$schema": "https://raw.githubusercontent.com/crossbario/crossbar/master/crossbar.json",
"version": 2,
"controller": {
},
"workers": [
{
"type": "router",
"realms": [
{
"name": "name_1",
"roles": [
{
"name": "anonymous",
"permissions": [
{
"uri": "",
"match": "prefix",
"allow": {
"call": true,
"register": true,
"publish": true,
"subscribe": true
},
"disclose": {
"caller": false,
"publisher": false
},
"cache": false
}
]
}
]
}
],
"transports": [
{
"type": "websocket",
"endpoint": {
"type": "tcp",
"port": 8080,
"tls": {
"key": "path/to/letsencrypt/keys/privkey.pem",
"certificate": "path/to/letsencrypt/keys/cert.pem",
"chain_certificates": ["path/to/letsencrypt/keys/chain.pem"],
"ca_certificates": [
"isrgrootx1.pem",
"letsencryptauthorityx1.pem",
"letsencryptauthorityx2.pem"
],
"ciphers": "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AES:RSA+3DES:!ADH:!AECDH:!MD5:!DSS"
}
},
"url": "wss://[domain]",
"serializers": ["json"],
"auth": {
"ticket": {
"type": "static",
"principals": {
"user_1": {
"ticket": "ticket_1",
"role": "anonymous"
}
}
}
},
"options": {
"allowed_origins": ["*"],
"allow_null_origin": true,
"enable_webstatus": true,
"max_frame_size": 1048576,
"max_message_size": 1048576,
"auto_fragment_size": 65536,
"fail_by_drop": true,
"open_handshake_timeout": 2500,
"close_handshake_timeout": 1000,
"auto_ping_interval": 10000,
"auto_ping_timeout": 5000,
"auto_ping_size": 4,
"compression": {
"deflate": {
"request_no_context_takeover": false,
"request_max_window_bits": 13,
"no_context_takeover": false,
"max_window_bits": 13,
"memory_level": 5
}
}
}
},
{
"type": "websocket",
"endpoint": {
"type": "tcp",
"port": 8081
},
"url": "ws://[domain]",
"serializers": ["json"],
"options": {
"allowed_origins": ["*"],
"allow_null_origin": true,
"enable_webstatus": false,
"max_frame_size": 1048576,
"max_message_size": 1048576,
"auto_fragment_size": 65536,
"fail_by_drop": true,
"open_handshake_timeout": 2500,
"close_handshake_timeout": 1000,
"auto_ping_interval": 10000,
"auto_ping_timeout": 5000,
"auto_ping_size": 4,
"compression": {
"deflate": {
"request_no_context_takeover": false,
"request_max_window_bits": 13,
"no_context_takeover": false,
"max_window_bits": 13,
"memory_level": 5
}
}
}
}
]
}
]
}
Python script:-
import os, sys
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.wamp import ApplicationSession, ApplicationRunner
from autobahn.wamp.types import PublishOptions
PRINCIPAL = "user_1"
PRINCIPAL_TICKET = "ticket_1"
class ClientSession(ApplicationSession):
def onConnect(self):
print("Client session connected. Starting WAMP-Ticket authentication on realm '{}' as principal '{}' ..".format(self.config.realm, PRINCIPAL))
self.join(self.config.realm, ["ticket"], PRINCIPAL)
def onChallenge(self, challenge):
if challenge.method == "ticket":
print("WAMP-Ticket challenge received: {}".format(challenge))
return PRINCIPAL_TICKET
else:
raise Exception("Invalid authmethod {}".format(challenge.method))
@inlineCallbacks
def onJoin(self, details):
print("Client session joined: {}".format(details))
print("\nHooray! We've been successfully authenticated with WAMP-Ticket using static configuration!\n")
## call a procedure we are allowed to call (so this should succeed)
##
try:
res = yield self.call('com.example.add2', 2, 3)
print("call result: {}".format(res))
except Exception as e:
print("call error: {}".format(e))
## (try to) register a procedure where we are not allowed to (so this should fail)
##
try:
reg = yield self.register(lambda x, y: x * y, 'com.example.mul2')
except Exception as e:
print("registration failed (this is expected!) {}".format(e))
## publish to a couple of topics we are allowed to publish to.
##
for topic in [
'com.example.topic1',
'com.foobar.topic1']:
try:
yield self.publish(topic, "hello", options = PublishOptions(acknowledge = True))
print("ok, event published to topic {}".format(topic))
except Exception as e:
print("publication to topic {} failed: {}".format(topic, e))
## (try to) publish to a couple of topics we are not allowed to publish to (so this should fail)
##
for topic in [
'com.example.topic2',
'com.foobar.topic2']:
try:
yield self.publish(topic, "hello", options = PublishOptions(acknowledge = True))
print("ok, event published to topic {}".format(topic))
except Exception as e:
print("publication to topic {} failed (this is expected!) {}".format(topic, e))
self.leave()
def onLeave(self, details):
print("Client session left: {}".format(details))
self.disconnect()
def onDisconnect(self):
print("Client session disconnected.")
reactor.stop()
runner = ApplicationRunner(url='wss://[domain]:8080', realm='name_1')
runner.run(ClientSession)
Crossbar trace:-
[Router 32589 crossbar.router.protocol.WampWebSocketServerProtocol] connection accepted from peer tcp4:[ip_address]:5259
[Router 32589 crossbar.router.protocol.WampWebSocketServerProtocol] Connection made to tcp4:[ip_address]:5259
[Router 32589 crossbar.router.protocol.WampWebSocketServerProtocol] SSL error: tlsv1 alert unknown ca (in ssl3_read_bytes)
[Router 32589 crossbar.router.protocol.WampWebSocketServerProtocol] _connectionLost: [Failure instance: Traceback: <class 'OpenSSL.SSL.Error'>: [('SSL routines', 'ssl3_read_bytes', 'tlsv1 alert unknown ca')]
Python error: SSL error: certificate verify failed (in tls_process_server_certificate)
Initially, I did not have CA certificates in the Crossbar config (no changes in the errors). I figured that I should add them because it may have something to do with this so I got them from https://letsencrypt.org/2015/06/04/isrg-ca-certs.html (not sure if this is correct). Also tried from https://letsencrypt.org/certificates/, but this went over my head (wth do I even need?).
I think that it’s because the CA sent by the machine trying to connect is not recognised by the server.
Now, I can’t figure out how to change either the CA or the Certificates that are being sent by the script and even if I had another way (I have some alternative scripts I can try but they’re for plain WebSocket) then what should I change it to.
Help, please?