From a4fb219bb1a115259383d138b4e613b0ea1c10fe Mon Sep 17 00:00:00 2001 From: Colin Sullivan Date: Sat, 6 Feb 2021 15:54:08 -0700 Subject: [PATCH 1/8] add websocket configuration Signed-off-by: Colin Sullivan --- SUMMARY.md | 1 + nats-server/configuration/websockets.md | 60 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 nats-server/configuration/websockets.md diff --git a/SUMMARY.md b/SUMMARY.md index 39a8193..f0eb82d 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -98,6 +98,7 @@ * [Monitoring](nats-server/configuration/monitoring.md) * [System Events](nats-server/configuration/sys_accounts/README.md) * [System Events & Decentralized JWT Tutorial](nats-server/configuration/sys_accounts/sys_accounts.md) + * [Websockets](nats-server/configuration/websockets.md) * [Managing A NATS Server](nats-server/nats_admin/README.md) * [Upgrading a Cluster](nats-server/nats_admin/upgrading_cluster.md) * [Slow Consumers](nats-server/nats_admin/slow_consumers.md) diff --git a/nats-server/configuration/websockets.md b/nats-server/configuration/websockets.md new file mode 100644 index 0000000..571f037 --- /dev/null +++ b/nats-server/configuration/websockets.md @@ -0,0 +1,60 @@ +# Websocket Support + +*Supported since NATS server version 2.2* + +Websocket support can be enabled in the server and may be used alongside the +traditional TCP socket connections. TLS, compression and +Origin Header checking are supported. + +To enable websocket support in the server, add a `websockets` configuration +block in the server's configuration file like the following: + +``` +websocket { + # Specify a host and port to listen for websocket connections + # listen: "host:port" + + # It can also be configured with individual parameters, + # namely host and port. + # host: "hostname" + # port: 4443 + + # This will optionally specify what host:port for websocket + # connections to be advertised in the cluster + # advertise: "host:port" + + # TLS configuration is required + tls { + cert_file: "/path/to/cert.pem" + key_file: "/path/to/key.pem" + } + + # If same_origin is true, then the Origin header of the + # client request must match the request's Host. + # same_origin: true + + # This list specifies the only accepted values for + # the client's request Origin header. The scheme, + # host and port must match. By convention, the + # absence of port for an http:// scheme will be 80, + # and for https:// will be 443. + # allowed_origins [ + # "http://www.example.com" + # "https://www.other-example.com" + # ] + + # This enables support for compressed websocket frames + # in the server. For compression to be used, both server + # and client have to support it. + # compression: true + + # This is the total time allowed for the server to + # read the client request and write the response back + # to the client. This includes the time needed for the + # TLS handshake. + # handshake_timeout: "2s" +} +``` + +Leaf nodes support outbound websocket connections by specifying the `ws` as the +scheme component of the remote server URL, for example `ws://hostname:4443`. \ No newline at end of file From 33acdbe454fb1d2c626f09cf4ce83f003c7c1e7a Mon Sep 17 00:00:00 2001 From: Ginger Collison Date: Mon, 8 Feb 2021 09:18:37 -0600 Subject: [PATCH 2/8] Update websockets.md --- nats-server/configuration/websockets.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nats-server/configuration/websockets.md b/nats-server/configuration/websockets.md index 571f037..64844fb 100644 --- a/nats-server/configuration/websockets.md +++ b/nats-server/configuration/websockets.md @@ -1,6 +1,6 @@ # Websocket Support -*Supported since NATS server version 2.2* +*Supported since NATS Server version 2.2* Websocket support can be enabled in the server and may be used alongside the traditional TCP socket connections. TLS, compression and @@ -57,4 +57,4 @@ websocket { ``` Leaf nodes support outbound websocket connections by specifying the `ws` as the -scheme component of the remote server URL, for example `ws://hostname:4443`. \ No newline at end of file +scheme component of the remote server URL, for example `ws://hostname:4443`. From 4f428bce64850fa97b0bc726075747d6c5cfc959 Mon Sep 17 00:00:00 2001 From: Ivan Kozlovic Date: Mon, 8 Feb 2021 09:59:02 -0700 Subject: [PATCH 3/8] Updates Signed-off-by: Ivan Kozlovic --- .../configuration/leafnodes/leafnode_conf.md | 26 +++++ nats-server/configuration/websockets.md | 103 +++++++++++++++++- 2 files changed, 123 insertions(+), 6 deletions(-) diff --git a/nats-server/configuration/leafnodes/leafnode_conf.md b/nats-server/configuration/leafnodes/leafnode_conf.md index a3df027..6f7e5aa 100644 --- a/nats-server/configuration/leafnodes/leafnode_conf.md +++ b/nats-server/configuration/leafnodes/leafnode_conf.md @@ -93,6 +93,32 @@ If other form of credentials are used \(jwt, nkey or other\), then the server wi | `account` | [Account](../securing_nats/accounts.md) name or jwt public key identifying the local account to bind to this remote server. Any traffic locally on this account will be forwarded to the remote server. | | `credentials` | Credential file for connecting to the leafnode server. | | `tls` | A [TLS configuration](leafnode_conf.md#tls-configuration-block) block. Leafnode client will use specified TLS certificates when connecting/authenticating. | +| `ws_compression` | If connecting with [Websocket](leafnode_conf#connecting-using-websocket-protocol) protocol, this boolean (`true` or `false`) indicates to the remote server that it wishes to use compression. The default is `false`. | +| `ws_no_masking` | If connecting with [Websocket](leafnode_conf#connecting-using-websocket-protocol) protocol, this boolean indicates to the remote server that it wishes not to mask outbound websocket frames. The default is `false`, which means that outbound frames will be masked. | + +### Connecting using Websocket protocol + +Since NATS 2.2.0, Leaf nodes support outbound websocket connections by specifying `ws` as the scheme component of the remote server URLs: +``` +leafnodes { + remotes [ + {urls: ["ws://hostname1:443", "ws://hostname2:443"]} + ] +} +``` + +Note that if a URL has the `ws` scheme, all URLs the list must be `ws`. You cannot mix and match. +Therefore this would be considered an invalid configuration: +``` + remotes [ + # Invalid configuration that will prevent the server from starting + {urls: ["ws://hostname1:443", "nats-leaf://hostname2:7422"]} + ] +``` + +Note that the decision to make a TLS connection is not based on `wss://` (as opposed to `ws://`) but instead in the presence of a TLS configuration in the `leafnodes{}` or the specific remote configuration block. + +To configure Websocket in the remote server, check the [Websocket](../websockets.md) secion. ### `tls` Configuration Block diff --git a/nats-server/configuration/websockets.md b/nats-server/configuration/websockets.md index 64844fb..4b0c1e4 100644 --- a/nats-server/configuration/websockets.md +++ b/nats-server/configuration/websockets.md @@ -17,18 +17,22 @@ websocket { # It can also be configured with individual parameters, # namely host and port. # host: "hostname" - # port: 4443 + port: 443 # This will optionally specify what host:port for websocket # connections to be advertised in the cluster # advertise: "host:port" - # TLS configuration is required + # TLS configuration is required by default tls { cert_file: "/path/to/cert.pem" key_file: "/path/to/key.pem" } + # For test environments, you can disable the need for TLS + # by explicitly setting this option to `true` + # no_tls: true + # If same_origin is true, then the Origin header of the # client request must match the request's Host. # same_origin: true @@ -36,8 +40,8 @@ websocket { # This list specifies the only accepted values for # the client's request Origin header. The scheme, # host and port must match. By convention, the - # absence of port for an http:// scheme will be 80, - # and for https:// will be 443. + # absence of TCP port in the URL will be port 80 + # for an "http://" scheme, and 443 for "https://". # allowed_origins [ # "http://www.example.com" # "https://www.other-example.com" @@ -53,8 +57,95 @@ websocket { # to the client. This includes the time needed for the # TLS handshake. # handshake_timeout: "2s" + + # Name of the cookie, which if present in WebSocket upgrade headers, + # will be treated as the JWT during CONNECT phase as long as + # the "jwt" field specified in the CONNECT protocol is missing or empty. + # Note that the server needs to be running in operator mode for this + # option to be used. + # jwt_cookie: "my_jwt_cookie_name" + + # If no user name is provided when a websocket client connects, will default + # this user name in the authentication phase. If specified, this will + # override, for websocket clients, any `no_auth_user` value defined in the + # main configuration file. + # Note that this is not compatible with running the server in operator mode. + # no_auth_user: "my_username_for_apps_not_providing_credentials" + + # See below to know what is the normal way of limiting websocket clients + # to specific users. + # If there are no users specified in the configuration, this simple authorization + # block allows you to override the values that would be configured in the + # equivalent block in the main section. + # authorization { + # # If this is specified, the client has to provide the same username + # # and password to be able to connect. + # # username: "my_user_name" + # # password: "my_password" + # + # # If this is specified, the password field in the CONNECT has to + # # match this token. + # # token: "my_token" + # + # # This overrides the main's authorization timeout. For consistency + # # with the main's authorization configuration block, this is expressed + # # as a number of seconds. + # # timeout: 2.0 + #} } ``` -Leaf nodes support outbound websocket connections by specifying the `ws` as the -scheme component of the remote server URL, for example `ws://hostname:4443`. +## Authorization of Websocket Users + +A new field when configuring users allows you to restrict which type of connections are allowed for a specific user. + +Consider this configuration: + +``` +authorization { + users [ + {user: foo password: foopwd, permission: {...}} + {user: bar password: barpwd, permission: {...}} + ] +} +``` + +If a websocket client were to connect and use the username `foo` and password `foopwd`, it would be accepted. +Now suppose that you would want websocket client to only be accepted if it connected using the username `bar` +and password `barpwd`, then you would use the option `allowed_connection_types` to restrict which type +of connections can bind to this user. + +``` +authorization { + users [ + {user: foo password: foopwd, permission: {...}} + {user: bar password: barpwd, permission: {...}, allowed_connection_types: ["WEBSOCKET"]} + ] +} +``` + +The option `allowed_connection_types` (also can be named `connection_types` or `clients`) as you can see +is a list, and you can allow several type of clients. Suppose you want the user `bar` to accept both +standard NATS clients and websocket clients, you would configure the user like this: + +``` +authorization { + users [ + {user: foo password: foopwd, permission: {...}} + {user: bar password: barpwd, permission: {...}, allowed_connection_types: ["STANDARD", "WEBSOCKET"]} + ] +} +``` + +The absence of `allowed_connection_types` means that all type of connections are allowed (the default behavior). + +The possible values are currently: +* `STANDARD` +* `WEBSOCKET` +* `LEAFNODE` +* `MQTT` + +## Leaf nodes connections + +You can configure remote Leaf node connections so that they connect to the Websocket port instead of the Leaf node port. +See [Leafnode](leafnodes/leafnode_conf.md#connecting-using-websocket-protocol) section. From 2e36c79791342d8f9f6888746131071c2c141dca Mon Sep 17 00:00:00 2001 From: Ivan Kozlovic Date: Mon, 8 Feb 2021 11:49:32 -0700 Subject: [PATCH 4/8] Some updates taken from Alberto's closed PR. Signed-off-by: Ivan Kozlovic --- nats-server/configuration/websockets.md | 37 +++++++++++++++++-------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/nats-server/configuration/websockets.md b/nats-server/configuration/websockets.md index 4b0c1e4..2cce11c 100644 --- a/nats-server/configuration/websockets.md +++ b/nats-server/configuration/websockets.md @@ -12,18 +12,22 @@ block in the server's configuration file like the following: ``` websocket { # Specify a host and port to listen for websocket connections + # # listen: "host:port" # It can also be configured with individual parameters, # namely host and port. + # # host: "hostname" port: 443 # This will optionally specify what host:port for websocket - # connections to be advertised in the cluster + # connections to be advertised in the cluster. + # # advertise: "host:port" # TLS configuration is required by default + # tls { cert_file: "/path/to/cert.pem" key_file: "/path/to/key.pem" @@ -31,17 +35,19 @@ websocket { # For test environments, you can disable the need for TLS # by explicitly setting this option to `true` + # # no_tls: true - # If same_origin is true, then the Origin header of the - # client request must match the request's Host. + # [Cross-origin resource sharing option](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). When set to `true`, the HTTP origin header must match the request’s hostname. + # The default is `false`. + # # same_origin: true - # This list specifies the only accepted values for - # the client's request Origin header. The scheme, - # host and port must match. By convention, the - # absence of TCP port in the URL will be port 80 + # [Cross-origin resource sharing option](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). List of accepted origins. When empty, and `same_origin` is `false`, clients from any origin are allowed to connect. + # This list specifies the only accepted values for the client's request Origin header. The scheme, + # host and port must match. By convention, the absence of TCP port in the URL will be port 80 # for an "http://" scheme, and 443 for "https://". + # # allowed_origins [ # "http://www.example.com" # "https://www.other-example.com" @@ -50,19 +56,24 @@ websocket { # This enables support for compressed websocket frames # in the server. For compression to be used, both server # and client have to support it. + # # compression: true # This is the total time allowed for the server to # read the client request and write the response back # to the client. This includes the time needed for the # TLS handshake. + # # handshake_timeout: "2s" - # Name of the cookie, which if present in WebSocket upgrade headers, - # will be treated as the JWT during CONNECT phase as long as - # the "jwt" field specified in the CONNECT protocol is missing or empty. - # Note that the server needs to be running in operator mode for this - # option to be used. + # Name for an HTTP cookie, that if present will be used as a client JWT. + # If the client specifies a JWT in the CONNECT protocol, this option is ignored. + # The cookie should be set by the HTTP server as described [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies). + # This setting is useful when generating NATS `Bearer` client JWTs as the + # result of some authentication mechanism. The HTTP server after correct + # authentication can issue a JWT for the user, that is set securely preventing + # access by unintended scripts. Note these JWTs must be [NATS JWTs](https://docs.nats.io/nats-server/configuration/securing_nats/jwt). + # # jwt_cookie: "my_jwt_cookie_name" # If no user name is provided when a websocket client connects, will default @@ -70,6 +81,7 @@ websocket { # override, for websocket clients, any `no_auth_user` value defined in the # main configuration file. # Note that this is not compatible with running the server in operator mode. + # # no_auth_user: "my_username_for_apps_not_providing_credentials" # See below to know what is the normal way of limiting websocket clients @@ -77,6 +89,7 @@ websocket { # If there are no users specified in the configuration, this simple authorization # block allows you to override the values that would be configured in the # equivalent block in the main section. + # # authorization { # # If this is specified, the client has to provide the same username # # and password to be able to connect. From 093b6459c673251f3280db583d3f09d666cd592f Mon Sep 17 00:00:00 2001 From: Ginger Collison Date: Mon, 8 Feb 2021 13:41:32 -0600 Subject: [PATCH 5/8] update link to JWT --- nats-server/configuration/websockets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nats-server/configuration/websockets.md b/nats-server/configuration/websockets.md index 2cce11c..235a8cd 100644 --- a/nats-server/configuration/websockets.md +++ b/nats-server/configuration/websockets.md @@ -72,7 +72,7 @@ websocket { # This setting is useful when generating NATS `Bearer` client JWTs as the # result of some authentication mechanism. The HTTP server after correct # authentication can issue a JWT for the user, that is set securely preventing - # access by unintended scripts. Note these JWTs must be [NATS JWTs](https://docs.nats.io/nats-server/configuration/securing_nats/jwt). + # access by unintended scripts. Note these JWTs must be [NATS JWTs](securing_nats/jwt). # # jwt_cookie: "my_jwt_cookie_name" From 6d00a5523b3f0c7b4bf3b9479eac07ee5b03fd61 Mon Sep 17 00:00:00 2001 From: Ginger Collison Date: Mon, 8 Feb 2021 13:46:16 -0600 Subject: [PATCH 6/8] Update websockets.md --- nats-server/configuration/websockets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nats-server/configuration/websockets.md b/nats-server/configuration/websockets.md index 235a8cd..2cce11c 100644 --- a/nats-server/configuration/websockets.md +++ b/nats-server/configuration/websockets.md @@ -72,7 +72,7 @@ websocket { # This setting is useful when generating NATS `Bearer` client JWTs as the # result of some authentication mechanism. The HTTP server after correct # authentication can issue a JWT for the user, that is set securely preventing - # access by unintended scripts. Note these JWTs must be [NATS JWTs](securing_nats/jwt). + # access by unintended scripts. Note these JWTs must be [NATS JWTs](https://docs.nats.io/nats-server/configuration/securing_nats/jwt). # # jwt_cookie: "my_jwt_cookie_name" From 44fa12e358906c5c56abba0b0e8c64f67631c8b1 Mon Sep 17 00:00:00 2001 From: Ivan Kozlovic Date: Wed, 10 Feb 2021 13:18:37 -0700 Subject: [PATCH 7/8] Add note about frame types and content of a frame wrt NATS protocols Signed-off-by: Ivan Kozlovic --- nats-server/configuration/websockets.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nats-server/configuration/websockets.md b/nats-server/configuration/websockets.md index 2cce11c..7e742d2 100644 --- a/nats-server/configuration/websockets.md +++ b/nats-server/configuration/websockets.md @@ -6,6 +6,11 @@ Websocket support can be enabled in the server and may be used alongside the traditional TCP socket connections. TLS, compression and Origin Header checking are supported. +**Important** + +- NATS Supports only Websocket data frames in Binary, not Text format (https://tools.ietf.org/html/rfc6455#section-5.6). The server will always send in Binary and your clients MUST send in Binary too. +- For writers of client libraries: a Websocket frame is not guaranteed to contain a full NATS protocol (actually will generally not). Any data from a frame must be going through a parser that can handle partial protocols. See the protocol description [here](../../nats-protocol/nats-protocol/README.md). + To enable websocket support in the server, add a `websockets` configuration block in the server's configuration file like the following: From 6bacb945b4d00aed938befdb63146085d262e2ba Mon Sep 17 00:00:00 2001 From: Ivan Kozlovic Date: Tue, 16 Feb 2021 10:29:41 -0700 Subject: [PATCH 8/8] Restructe layout, add README and config page, etc.. Resolves #205 Signed-off-by: Ivan Kozlovic --- SUMMARY.md | 2 +- nats-server/configuration/README.md | 1 + .../configuration/leafnodes/leafnode_conf.md | 2 +- nats-server/configuration/websocket/README.md | 12 ++++++++++++ .../websocket_conf.md} | 17 +++-------------- 5 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 nats-server/configuration/websocket/README.md rename nats-server/configuration/{websockets.md => websocket/websocket_conf.md} (86%) diff --git a/SUMMARY.md b/SUMMARY.md index f0eb82d..eb680a1 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -98,7 +98,7 @@ * [Monitoring](nats-server/configuration/monitoring.md) * [System Events](nats-server/configuration/sys_accounts/README.md) * [System Events & Decentralized JWT Tutorial](nats-server/configuration/sys_accounts/sys_accounts.md) - * [Websockets](nats-server/configuration/websockets.md) + * [Websocket](nats-server/configuration/websocket/README.md) * [Managing A NATS Server](nats-server/nats_admin/README.md) * [Upgrading a Cluster](nats-server/nats_admin/upgrading_cluster.md) * [Slow Consumers](nats-server/nats_admin/slow_consumers.md) diff --git a/nats-server/configuration/README.md b/nats-server/configuration/README.md index bbe1b84..214582c 100644 --- a/nats-server/configuration/README.md +++ b/nats-server/configuration/README.md @@ -117,6 +117,7 @@ authorization: { | [`cluster`](clustering/cluster_config.md) | Configuration map for [cluster](clustering/). | | | [`gateway`](gateways/gateway.md#gateway-configuration-block) | Configuration map for [gateway](gateways/). | | | [`leafnode`](leafnodes/leafnode_conf.md) | Configuration map for a [leafnode](leafnodes/). | | +| [`websocket`](websocket/websocket_conf.md) | Configuration map for [websocket](websocket/). | | ### Connection Timeouts diff --git a/nats-server/configuration/leafnodes/leafnode_conf.md b/nats-server/configuration/leafnodes/leafnode_conf.md index 6f7e5aa..f7ff7e2 100644 --- a/nats-server/configuration/leafnodes/leafnode_conf.md +++ b/nats-server/configuration/leafnodes/leafnode_conf.md @@ -118,7 +118,7 @@ Therefore this would be considered an invalid configuration: Note that the decision to make a TLS connection is not based on `wss://` (as opposed to `ws://`) but instead in the presence of a TLS configuration in the `leafnodes{}` or the specific remote configuration block. -To configure Websocket in the remote server, check the [Websocket](../websockets.md) secion. +To configure Websocket in the remote server, check the [Websocket](../websocket/websocket_conf.md) secion. ### `tls` Configuration Block diff --git a/nats-server/configuration/websocket/README.md b/nats-server/configuration/websocket/README.md new file mode 100644 index 0000000..2c17afa --- /dev/null +++ b/nats-server/configuration/websocket/README.md @@ -0,0 +1,12 @@ +# Websocket + +*Supported since NATS Server version 2.2* + +Websocket support can be enabled in the server and may be used alongside the +traditional TCP socket connections. TLS, compression and +Origin Header checking are supported. + +**Important** + +- NATS Supports only Websocket data frames in Binary, not Text format (https://tools.ietf.org/html/rfc6455#section-5.6). The server will always send in Binary and your clients MUST send in Binary too. +- For writers of client libraries: a Websocket frame is not guaranteed to contain a full NATS protocol (actually will generally not). Any data from a frame must be going through a parser that can handle partial protocols. See the protocol description [here](../../../nats-protocol/nats-protocol/README.md). diff --git a/nats-server/configuration/websockets.md b/nats-server/configuration/websocket/websocket_conf.md similarity index 86% rename from nats-server/configuration/websockets.md rename to nats-server/configuration/websocket/websocket_conf.md index 7e742d2..889fc00 100644 --- a/nats-server/configuration/websockets.md +++ b/nats-server/configuration/websocket/websocket_conf.md @@ -1,17 +1,6 @@ -# Websocket Support +# Configuration -*Supported since NATS Server version 2.2* - -Websocket support can be enabled in the server and may be used alongside the -traditional TCP socket connections. TLS, compression and -Origin Header checking are supported. - -**Important** - -- NATS Supports only Websocket data frames in Binary, not Text format (https://tools.ietf.org/html/rfc6455#section-5.6). The server will always send in Binary and your clients MUST send in Binary too. -- For writers of client libraries: a Websocket frame is not guaranteed to contain a full NATS protocol (actually will generally not). Any data from a frame must be going through a parser that can handle partial protocols. See the protocol description [here](../../nats-protocol/nats-protocol/README.md). - -To enable websocket support in the server, add a `websockets` configuration +To enable websocket support in the server, add a `websocket` configuration block in the server's configuration file like the following: ``` @@ -166,4 +155,4 @@ The possible values are currently: ## Leaf nodes connections You can configure remote Leaf node connections so that they connect to the Websocket port instead of the Leaf node port. -See [Leafnode](leafnodes/leafnode_conf.md#connecting-using-websocket-protocol) section. +See [Leafnode](../leafnodes/leafnode_conf.md#connecting-using-websocket-protocol) section.