(ws) Implement simple header based websocket authorization technique to reject
This commit is contained in:
parent
93ad709dfd
commit
461a645704
@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
All changes to this project will be documented in this file.
|
All changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [11.0.5] - 2020-12-17
|
||||||
|
|
||||||
|
(ws) Implement simple header based websocket authorization technique to reject
|
||||||
|
client which do not supply a certain header ("Authorization") with a special
|
||||||
|
value (see doc).
|
||||||
|
|
||||||
## [11.0.4] - 2020-11-16
|
## [11.0.4] - 2020-11-16
|
||||||
|
|
||||||
(ixwebsocket) Handle EINTR return code in ix::poll and IXSelectInterrupt
|
(ixwebsocket) Handle EINTR return code in ix::poll and IXSelectInterrupt
|
||||||
|
57
docs/ws.md
57
docs/ws.md
@ -195,6 +195,63 @@ Server: Python/3.7 websockets/8.0.2
|
|||||||
Upgrade: websocket
|
Upgrade: websocket
|
||||||
```
|
```
|
||||||
|
|
||||||
|
It is possible to pass custom HTTP header when doing the connection handshake,
|
||||||
|
the remote server might process them to implement a simple authorization
|
||||||
|
scheme.
|
||||||
|
|
||||||
|
```
|
||||||
|
src$ ws connect -H Authorization:supersecret ws://localhost:8008
|
||||||
|
Type Ctrl-D to exit prompt...
|
||||||
|
[2020-12-17 22:35:08.732] [info] Authorization: supersecret
|
||||||
|
Connecting to url: ws://localhost:8008
|
||||||
|
> [2020-12-17 22:35:08.736] [info] ws_connect: connected
|
||||||
|
[2020-12-17 22:35:08.736] [info] Uri: /
|
||||||
|
[2020-12-17 22:35:08.736] [info] Headers:
|
||||||
|
[2020-12-17 22:35:08.736] [info] Connection: Upgrade
|
||||||
|
[2020-12-17 22:35:08.736] [info] Sec-WebSocket-Accept: 2yaTFcdwn8KL6IzSMj2u6Le7KTg=
|
||||||
|
[2020-12-17 22:35:08.736] [info] Sec-WebSocket-Extensions: permessage-deflate; server_max_window_bits=15; client_max_window_bits=15
|
||||||
|
[2020-12-17 22:35:08.736] [info] Server: ixwebsocket/11.0.4 macos ssl/SecureTransport zlib 1.2.11
|
||||||
|
[2020-12-17 22:35:08.736] [info] Upgrade: websocket
|
||||||
|
[2020-12-17 22:35:08.736] [info] Received 25 bytes
|
||||||
|
ws_connect: received message: Authorization suceeded!
|
||||||
|
[2020-12-17 22:35:08.736] [info] Received pong ixwebsocket::heartbeat::30s::0
|
||||||
|
hello
|
||||||
|
> [2020-12-17 22:35:25.157] [info] Received 7 bytes
|
||||||
|
ws_connect: received message: hello
|
||||||
|
```
|
||||||
|
|
||||||
|
If the wrong header is passed in, the server would close the connection with a custom close code (>4000, and <4999).
|
||||||
|
|
||||||
|
```
|
||||||
|
[2020-12-17 22:39:37.044] [info] Upgrade: websocket
|
||||||
|
ws_connect: connection closed: code 4001 reason Permission denied
|
||||||
|
```
|
||||||
|
|
||||||
|
## echo server
|
||||||
|
|
||||||
|
The ws echo server will respond what the client just sent him. If we use the
|
||||||
|
simple --http_authorization_header we can enforce that client need to pass a
|
||||||
|
special value in the Authorization header to connect.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ws echo_server --http_authorization_header supersecret
|
||||||
|
[2020-12-17 22:35:06.192] [info] Listening on 127.0.0.1:8008
|
||||||
|
[2020-12-17 22:35:08.735] [info] New connection
|
||||||
|
[2020-12-17 22:35:08.735] [info] remote ip: 127.0.0.1
|
||||||
|
[2020-12-17 22:35:08.735] [info] id: 0
|
||||||
|
[2020-12-17 22:35:08.735] [info] Uri: /
|
||||||
|
[2020-12-17 22:35:08.735] [info] Headers:
|
||||||
|
[2020-12-17 22:35:08.735] [info] Authorization: supersecret
|
||||||
|
[2020-12-17 22:35:08.735] [info] Connection: Upgrade
|
||||||
|
[2020-12-17 22:35:08.735] [info] Host: localhost:8008
|
||||||
|
[2020-12-17 22:35:08.735] [info] Sec-WebSocket-Extensions: permessage-deflate; server_max_window_bits=15; client_max_window_bits=15
|
||||||
|
[2020-12-17 22:35:08.735] [info] Sec-WebSocket-Key: eFF2Gf25dC7eC15Ab1135G==
|
||||||
|
[2020-12-17 22:35:08.735] [info] Sec-WebSocket-Version: 13
|
||||||
|
[2020-12-17 22:35:08.735] [info] Upgrade: websocket
|
||||||
|
[2020-12-17 22:35:08.735] [info] User-Agent: ixwebsocket/11.0.4 macos ssl/SecureTransport zlib 1.2.11
|
||||||
|
[2020-12-17 22:35:25.157] [info] Received 7 bytes
|
||||||
|
```
|
||||||
|
|
||||||
## Websocket proxy
|
## Websocket proxy
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IXConnectionState.h"
|
#include "IXConnectionState.h"
|
||||||
|
#include "IXNetSystem.h"
|
||||||
#include "IXSelectInterrupt.h"
|
#include "IXSelectInterrupt.h"
|
||||||
#include "IXSocketTLSOptions.h"
|
#include "IXSocketTLSOptions.h"
|
||||||
#include "IXNetSystem.h"
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define IX_WEBSOCKET_VERSION "11.0.4"
|
#define IX_WEBSOCKET_VERSION "11.0.5"
|
||||||
|
34
ws/ws.cpp
34
ws/ws.cpp
@ -1367,7 +1367,8 @@ namespace ix
|
|||||||
const ix::SocketTLSOptions& tlsOptions,
|
const ix::SocketTLSOptions& tlsOptions,
|
||||||
bool ipv6,
|
bool ipv6,
|
||||||
bool disablePerMessageDeflate,
|
bool disablePerMessageDeflate,
|
||||||
bool disablePong)
|
bool disablePong,
|
||||||
|
const std::string& httpHeaderAuthorization)
|
||||||
{
|
{
|
||||||
spdlog::info("Listening on {}:{}", hostname, port);
|
spdlog::info("Listening on {}:{}", hostname, port);
|
||||||
|
|
||||||
@ -1393,9 +1394,9 @@ namespace ix
|
|||||||
}
|
}
|
||||||
|
|
||||||
server.setOnClientMessageCallback(
|
server.setOnClientMessageCallback(
|
||||||
[greetings](std::shared_ptr<ConnectionState> connectionState,
|
[greetings, httpHeaderAuthorization](std::shared_ptr<ConnectionState> connectionState,
|
||||||
WebSocket& webSocket,
|
WebSocket& webSocket,
|
||||||
const WebSocketMessagePtr& msg) {
|
const WebSocketMessagePtr& msg) {
|
||||||
auto remoteIp = connectionState->getRemoteIp();
|
auto remoteIp = connectionState->getRemoteIp();
|
||||||
if (msg->type == ix::WebSocketMessageType::Open)
|
if (msg->type == ix::WebSocketMessageType::Open)
|
||||||
{
|
{
|
||||||
@ -1409,6 +1410,19 @@ namespace ix
|
|||||||
spdlog::info("{}: {}", it.first, it.second);
|
spdlog::info("{}: {}", it.first, it.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!httpHeaderAuthorization.empty())
|
||||||
|
{
|
||||||
|
auto authorization = msg->openInfo.headers["Authorization"];
|
||||||
|
if (authorization != httpHeaderAuthorization)
|
||||||
|
{
|
||||||
|
webSocket.close(4001, "Permission denied");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
webSocket.sendText("Authorization suceeded!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (greetings)
|
if (greetings)
|
||||||
{
|
{
|
||||||
webSocket.sendText("Welcome !");
|
webSocket.sendText("Welcome !");
|
||||||
@ -3039,6 +3053,7 @@ int main(int argc, char** argv)
|
|||||||
std::string publisherRolesecret;
|
std::string publisherRolesecret;
|
||||||
std::string sendMsg("hello world");
|
std::string sendMsg("hello world");
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
std::string httpHeaderAuthorization;
|
||||||
ix::SocketTLSOptions tlsOptions;
|
ix::SocketTLSOptions tlsOptions;
|
||||||
ix::CobraConfig cobraConfig;
|
ix::CobraConfig cobraConfig;
|
||||||
ix::CobraBotConfig cobraBotConfig;
|
ix::CobraBotConfig cobraBotConfig;
|
||||||
@ -3185,6 +3200,7 @@ int main(int argc, char** argv)
|
|||||||
echoServerApp->fallthrough();
|
echoServerApp->fallthrough();
|
||||||
echoServerApp->add_option("--port", port, "Port");
|
echoServerApp->add_option("--port", port, "Port");
|
||||||
echoServerApp->add_option("--host", hostname, "Hostname");
|
echoServerApp->add_option("--host", hostname, "Hostname");
|
||||||
|
echoServerApp->add_option("--http_authorization_header", httpHeaderAuthorization, "Hostname");
|
||||||
echoServerApp->add_flag("-q", quiet, "Quiet / only display warnings and errors");
|
echoServerApp->add_flag("-q", quiet, "Quiet / only display warnings and errors");
|
||||||
echoServerApp->add_flag("-g", greetings, "Greet");
|
echoServerApp->add_flag("-g", greetings, "Greet");
|
||||||
echoServerApp->add_flag("-6", ipv6, "IpV6");
|
echoServerApp->add_flag("-6", ipv6, "IpV6");
|
||||||
@ -3507,8 +3523,14 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
else if (app.got_subcommand("echo_server"))
|
else if (app.got_subcommand("echo_server"))
|
||||||
{
|
{
|
||||||
ret = ix::ws_echo_server_main(
|
ret = ix::ws_echo_server_main(port,
|
||||||
port, greetings, hostname, tlsOptions, ipv6, disablePerMessageDeflate, disablePong);
|
greetings,
|
||||||
|
hostname,
|
||||||
|
tlsOptions,
|
||||||
|
ipv6,
|
||||||
|
disablePerMessageDeflate,
|
||||||
|
disablePong,
|
||||||
|
httpHeaderAuthorization);
|
||||||
}
|
}
|
||||||
else if (app.got_subcommand("push_server"))
|
else if (app.got_subcommand("push_server"))
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user