1# Secure Streams 2 3Secure Streams is a networking api that strictly separates payload from any 4metadata. That includes the client endpoint address for the connection, the tls 5trust chain and even the protocol used to connect to the endpoint. 6 7The user api just receives and transmits payload, and receives advisory 8connection state information. 9 10The details about how the connections for different types of secure stream should 11be made are held in JSON "policy database" initially passed in to the context 12creation, but able to be updated from a remote copy. 13 14Both client and server networking can be handled using Secure Streams APIS. 15 16![overview](/doc-assets/ss-operation-modes.png) 17 18## Secure Streams CLIENT State lifecycle 19 20![overview](/doc-assets/ss-state-flow.png) 21 22Secure Streams are created using `lws_ss_create()`, after that they may acquire 23underlying connections, and lose them, but the lifecycle of the Secure Stream 24itself is not directly related to any underlying connection. 25 26Once created, Secure Streams may attempt connections, these may fail and once 27the number of failures exceeds the count of attempts to conceal in the retry / 28backoff policy, the stream reaches `LWSSSCS_ALL_RETRIES_FAILED`. The stream becomes 29idle again until another explicit connection attempt is given. 30 31Once connected, the user code can use `lws_ss_request_tx()` to ask for a slot 32to write to the peer, when this if forthcoming the tx handler can send a message. 33If the underlying protocol gives indications of transaction success, such as, 34eg, a 200 for http, or an ACK from MQTT, the stream state is called back with 35an `LWSSSCS_QOS_ACK_REMOTE` or `LWSSSCS_QOS_NACK_REMOTE`. 36 37## SS Callback return handling 38 39SS state(), rx() and tx() can indicate with their return code some common 40situations that should be handled by the caller. 41 42Constant|Scope|Meaning 43---|---|--- 44LWSSSSRET_TX_DONT_SEND|tx|This opportunity to send something was passed on 45LWSSSSRET_OK|state, rx, tx|No error, continue doing what we're doing 46LWSSSSRET_DISCONNECT_ME|state, rx|assertively disconnect from peer 47LWSSSSRET_DESTROY_ME|state, rx|Caller should now destroy the stream itself 48LWSSSSRET_SS_HANDLE_DESTROYED|state|Something handled a request to destroy the stream 49 50Destruction of the stream we're calling back on inside the callback is tricky, 51it's preferable to return `LWSSSSRET_DESTROY_ME` if it is required, and let the 52caller handle it. But in some cases, helpers called from the callbacks may 53destroy the handle themselves, in that case the handler should return 54`LWSSSSRET_SS_HANDLE_DESTROYED` indicating that the handle is already destroyed. 55 56## Secure Streams SERVER State lifecycle 57 58![overview](/doc-assets/ss-state-flow-server.png) 59 60You can also run servers defined using Secure Streams, the main difference is 61that the user code must assertively create a secure stream of the server type 62in order to create the vhost and listening socket. When this stream is 63destroyed, the vhost is destroyed and the listen socket closed, otherwise it 64does not perform any rx or tx, it just represents the server lifecycle. 65 66When client connections randomly arrive at the listen socket, new Secure Stream 67objects are created along with accept sockets to represent each client 68connection. As they represent the incoming connection, their lifecycle is the 69same as that of the underlying connection. There is no retry concept since as 70with eg, http servers, the clients may typically not be routable for new 71connections initiated by the server. 72 73Since connections at socket level are already established, new connections are 74immediately taken through CREATING, CONNECTING, CONNECTED states for 75consistency. 76 77Some underlying protocols like http are "transactional", the server receives 78a logical request and must reply with a logical response. The additional 79state `LWSSSCS_SERVER_TXN` provides a point where the user code can set 80transaction metadata before or in place of sending any payload. It's also 81possible to defer this until any rx related to the transaction was received, 82but commonly with http requests, there is no rx / body. Configuring the 83response there may look like 84 85``` 86 /* 87 * We do want to ack the transaction... 88 */ 89 lws_ss_server_ack(m->ss, 0); 90 /* 91 * ... it's going to be text/html... 92 */ 93 lws_ss_set_metadata(m->ss, "mime", "text/html", 9); 94 /* 95 * ...it's going to be 128 byte (and request tx) 96 */ 97 lws_ss_request_tx_len(m->ss, 128); 98``` 99 100Otherwise the general api usage is very similar to client usage. 101 102## Convention for rx and tx callback return 103 104Function|Return|Meaning 105---|---|--- 106tx|`LWSSSSRET_OK`|Send the amount of `buf` stored in `*len` 107tx|`LWSSSSRET_TX_DONT_SEND`|Do not send anything 108tx|`LWSSSSRET_DISCONNECT_ME`|Close the current connection 109tx|`LWSSSSRET_DESTROY_ME`|Destroy the Secure Stream 110rx|>=0|accepted 111rx|<0|Close the current connection 112 113# JSON Policy Database 114 115Example JSON policy... formatting is shown for clarity but whitespace can be 116omitted in the actual policy. 117 118Ordering is not critical in itself, but forward references are not allowed, 119things must be defined before they are allowed to be referenced later in the 120JSON. 121 122 123``` 124{ 125 "release": "01234567", 126 "product": "myproduct", 127 "schema-version": 1, 128 "retry": [{ 129 "default": { 130 "backoff": [1000, 2000, 3000, 5000, 10000], 131 "conceal": 5, 132 "jitterpc": 20 133 } 134 }], 135 "certs": [{ 136 "isrg_root_x1": "MIIFazCCA1OgAw...AnX5iItreGCc=" 137 }, { 138 "LEX3_isrg_root_x1": "MIIFjTCCA3WgAwIB...WEsikxqEt" 139 }], 140 "trust_stores": [{ 141 "le_via_isrg": ["isrg_root_x1", "LEX3_isrg_root_x1"] 142 }], 143 "s": [{ 144 "mintest": { 145 "endpoint": "warmcat.com", 146 "port": 4443, 147 "protocol": "h1get", 148 "aux": "index.html", 149 "plugins": [], 150 "tls": true, 151 "opportunistic": true, 152 "retry": "default", 153 "tls_trust_store": "le_via_isrg" 154 } 155 }] 156} 157``` 158 159### `Release` 160 161Identifies the policy version 162 163### `Product` 164 165Identifies the product the policy should apply to 166 167### `Schema-version` 168 169The minimum version of the policy parser required to parse this policy 170 171### `via-socks5` 172 173Optional redirect for Secure Streams client traffic through a socks5 174proxy given in the format `address:port`, eg, `127.0.0.1:12345`. 175 176### `retry` 177 178A list of backoff schemes referred to in the policy 179 180### `backoff` 181 182An array of ms delays for each retry in turn 183 184### `conceal` 185 186The number of retries to conceal from higher layers before giving errors. If 187this is larger than the number of times in the backoff array, then the last time 188is used for the extra delays. 65535 means never stop trying. 189 190### `jitterpc` 191 192Percentage of the delay times mentioned in the backoff array that may be 193randomly added to the figure from the array. For example with an array entry of 1941000ms, and jitterpc of 20%, actual delays will be chosen randomly from 1000ms 195through 1200ms. This is to stop retry storms triggered by a single event like 196an outage becoming synchronized into a DoS. 197 198### `certs` 199 200Certificates needed for validation should be listed here each with a name. The 201format is base64 DER, which is the same as the part of PEM that is inside the 202start and end lines. 203 204### `trust_stores` 205 206Chains of certificates given in the `certs` section may be named and described 207inside the `trust_stores` section. Each entry in `trust_stores` is created as 208a vhost + tls context with the given name. Stream types can later be associated 209with one of these to enforce validity checking of the remote server. 210 211Entries should be named using "name" and the stack array defined using "stack" 212 213### `auth` 214 215Optional section describing a map of available authentication streamtypes to 216auth token blob indexes. 217 218``` 219... 220 "auth": [{"name":"newauth","type":"sigv4", "blob":0}] 221... 222``` 223 224Streams can indicate they depend on a valid auth token from one of these schemes 225by using the `"use_auth": "name"` member in the streamtype definition, where name 226is, eg, "sigv4" in the example above. If "use_auth" is not in the streamtype 227definition, default auth is lwa if "http_auth_header" is there. 228 229### `auth[].name` 230 231This is the name of the authentication scheme used by other streamtypes 232 233### `auth[].type` 234 235Indicate the auth type, e.g. sigv4 236 237### `auth[].streamtype` 238 239This is the auth streamtype to be used to refresh the authentication token 240 241### `auth[].blob` 242 243This is the auth blob index the authentication token is stored into and retreived 244from system blob, currently up to 4 blobs. 245 246 247### `s` 248 249These are an array of policies for the supported stream type names. 250 251### `server` 252 253**SERVER ONLY**: if set to `true`, the policy describes a secure streams 254server. 255 256### `endpoint` 257 258**CLIENT**: The DNS address the secure stream should connect to. 259 260This may contain string symbols which will be replaced with the 261corresponding streamtype metadata value at runtime. Eg, if the 262streamtype lists a metadata name "region", it's then possible to 263define the endpoint as, eg, `${region}.mysite.com`, and before 264attempting the connection setting the stream's metadata item 265"region" to the desired value, eg, "uk". 266 267If the endpoint string begins with `+`, then it's understood to 268mean a connection to a Unix Domain Socket, for Linux `+@` means 269the following Unix Domain Socket is in the Linux Abstract 270Namespace and doesn't have a filesystem footprint. This is only 271supported on unix-type and windows platforms and when lws was 272configured with `-DLWS_UNIX_SOCK=1` 273 274**SERVER**: If given, the network interface name or IP address the listen socket 275should bind to. 276 277**SERVER**: If begins with '!', the rest of the endpoint name is the 278vhost name of an existing vhost to bind to, instead of creating a new 279one. This is useful when the vhost layout is already being managed by 280lejp-conf JSON and it's more convenient to put the details in there. 281 282### `port` 283 284**CLIENT**: The port number as an integer on the endpoint to connect to 285 286**SERVER**: The port number the server will listen on 287 288### `protocol` 289 290**CLIENT**: The wire protocol to connect to the endpoint with. Currently 291supported streamtypes are 292 293|Wire protocol|Description| 294|---|---| 295|h1|http/1| 296|h2|http/2| 297|ws|http/1 Websockets| 298|mqtt|mqtt 3.1.1| 299|raw|| 300 301Raw protocol is a bit different than the others in that there is no protocol framing, 302whatever is received on the connection is passed to the user rx callback and whatever 303the tx callback provides is issued on to the connection. Because tcp can be 304arbitrarily fragmented by any intermediary, such streams have to be regarded as an 305ordered bytestream that may be fragmented at any byte without any meaning in terms 306of message boundaries, for that reason SOM and EOM are ignored with raw. 307 308### `allow_redirects` 309 310By default redirects are not followed, if you wish a streamtype to observe them, eg, 311because that's how it responds to a POST, set `"allow_redirects": true` 312 313### `tls` 314 315Set to `true` to enforce the stream travelling in a tls tunnel 316 317### `client cert` 318 319Set if the stream needs to authenticate itself using a tls client certificate. 320Set to the certificate index counting from 0+. The certificates are managed 321using lws_sytstem blobs. 322 323### `opportunistic` 324 325Set to `true` if the connection may be left dropped except when in use 326 327### `nailed_up` 328 329Set to `true` to have lws retry if the connection carrying this stream should 330ever drop. 331 332### `retry` 333 334The name of the policy described in the `retry` section to apply to this 335connection for retry + backoff 336 337### `timeout_ms` 338 339Optional timeout associated with streams of this streamtype. 340 341If user code applies the `lws_ss_start_timeout()` api on a stream with a 342timeout of LWSSS_TIMEOUT_FROM_POLICY, the `timeout_ms` entry given in the 343policy is applied. 344 345### `perf` 346 347If set to true, and lws was built with `LWS_WITH_CONMON`, causes this streamtype 348to receive additional rx payload with the `LWSSS_FLAG_PERF_JSON` flag set on it, 349that is JSON representing the onward connection performance information. 350 351These are based on the information captured in the struct defined in 352libwebsockets/lws-conmon.h, represented in JSON 353 354``` 355 { 356 "peer": "46.105.127.147", 357 "dns_us": 1234, 358 "sockconn_us": 1234, 359 "tls_us": 1234, 360 "txn_resp_us": 1234, 361 "dns":["46.105.127.147", "2001:41d0:2:ee93::1"] 362 } 363``` 364 365Streamtypes without "perf": true will never see the special rx payloads. 366Notice that the `LWSSS_FLAG_PERF_JSON` payloads must be handled out of band 367for the normal payloads, as they can appear inside normal payload messages. 368 369### `tls_trust_store` 370 371The name of the trust store described in the `trust_stores` section to apply 372to validate the remote server cert. 373 374If missing and tls is enabled on the streamtype, then validation is 375attempted using the OS trust store, otherwise the connection fails. 376 377### `use_auth` 378 379Indicate that the streamtype should use the named auth type from the `auth` 380array in the policy 381 382### `aws_region` 383 384Indicate which metadata should be used to set aws region for certain streamtype 385 386### `aws_service` 387 388Indicate which metadata should be used to set aws service for certain streamtype 389 390### `direct_proto_str` 391 392If set to `true`, application can use `lws_ss_set_metadata()` to directly set protocol related string and use `lws_ss_get_metadata` to fetch certain protocol related string. Please note that currently HTTP header is the supported protocol string. The `name` parameter is the name of HTTP header name (**with ':'**, e.g. `"Content-Type:"`) and `value` is the header's value. `LWS_WITH_SS_DIRECT_PROTOCOL_STR` flag needs to be configured during compilation for this. Currently it's only work for non-proxy case. 393 394### `server_cert` 395 396**SERVER ONLY**: subject to change... the name of the x.509 cert that is the 397server's tls certificate 398 399### `server_key` 400 401**SERVER ONLY**: subject to change... the name of the x.509 cert that is the 402server's tls key 403 404### `swake_validity` 405 406Set to `true` if this streamtype is important enough for the functioning of the 407device that its locally-initiated periodic connection validity checks of the 408interval described in the associated retry / backoff selection, are important 409enough to wake the whole system from low power suspend so they happen on 410schedule. 411 412### `proxy_buflen` 413 414Only used when the streamtype is proxied... sets the maximum size of the 415payload buffering (in bytes) the proxy will hold for this type of stream. If 416the endpoint dumps a lot of data without any flow control, this may need to 417be correspondingly large. Default is 32KB. 418 419### `proxy_buflen_rxflow_on_above`, `proxy_buflen_rxflow_off_below` 420 421When `proxy_buflen` is set, you can also wire up the amount of buffered 422data intended for the client held at the proxy, to the onward ss wsi 423rx flow control state. If more than `proxy_buflen_rxflow_on_above` 424bytes are buffered, rx flow control is set stopping further rx. Once 425the dsh is drained below `proxy_buflen_rxflow_off_below`, the rx flow 426control is released and RX resumes. 427 428### `client_buflen` 429 430Only used when the streamtype is proxied... sets the maximum size of the 431payload buffering (in bytes) the client will hold for this type of stream. If 432the client sends a lot of data without any flow control, this may need to 433be correspondingly large. Default is 32KB. 434 435### `attr_priority` 436 437A number between 0 (normal priority) and 6 (very high priority). 7 is also 438possible, but requires CAP_NET_ADMIN on Linux and is reserved for network 439administration packets. Normally default priority is fine, but under some 440conditions when transporting over IP packets, you may want to control the 441IP packet ToS priority for the streamtype by using this. 442 443### `attr_low_latency` 444 445This is a flag indicating that the streamtype packets should be transported 446in a way that results in lower latency where there is a choice. For IP packets, 447this sets the ToS "low delay" flag on packets from this streamtype. 448 449### `attr_high_throughput` 450 451This is a flag indicating that this streamtype should be expected to produce 452bulk content that requires high throughput. For IP packets, 453this sets the ToS "high throughput" flag on packets from this streamtype. 454 455### `attr_high_reliability` 456 457This is a flag indicating that extra efforts should be made to deliver packets 458from this streamtype where possible. For IP packets, this sets the ToS "high 459reliability" flag on packets from this streamtype. 460 461### `attr_low_cost` 462 463This is a flag indicating that packets from this streamtype should be routed as 464inexpensively as possible by trading off latency and reliability where there is 465a choice. For IP packets, this sets the ToS "low cost" flag on packets from 466this streamtype. 467 468### `metadata` 469 470This allows declaring basically dynamic symbol names to be used by the streamtype, 471along with an optional mapping to a protocol-specific entity such as a given 472http header. Eg: 473 474``` 475 "metadata": [ { "myname": "" }, { "ctype": "content-type:" } ], 476``` 477 478In this example "ctype" is associated with the http header "content-type" while 479"myname" doesn't have any association to a header. 480 481Symbol names may be used in the other policy for the streamtype for string 482substitution using the syntax like `xxx${myname}yyy`, forward references are 483valid but the scope of the symbols is just the streamtype the metadata is 484defined for. 485 486Client code can set metadata by name, using the `lws_ss_set_metadata()` api, this 487should be done before a transaction. And for metadata associated with a 488protocol-specific entity, like http headers, if incoming responses contain the 489mentioned header, the metadata symbol is set to that value at the client before 490any rx proceeds. 491 492Metadata continues to work the same for the client in the case it is proxying its 493connectivity, metadata is passed in both directions serialized over the proxy link. 494 495## http transport 496 497### `http_method` 498 499HTTP method to use with http-related protocols, like GET or POST. 500Not required for ws. 501 502### `http_expect` 503 504Optionally indicates that success for HTTP transactions using this 505streamtype is different than the default 200 - 299. 506 507Eg, you may choose to set this to 204 for Captive Portal Detect usage 508if that's what you expect the server to reply with to indicate 509success. In that case, anything other than 204 will be treated as a 510connection failure. 511 512### `http_fail_redirect` 513 514Set to `true` if you want to fail the connection on meeting an 515http redirect. This is needed to, eg, detect Captive Portals 516correctly. Normally, if on https, you would want the default behaviour 517of following the redirect. 518 519### `http_url` 520 521Url path to use with http-related protocols 522 523The URL path can include metatadata like this 524 525"/mypath?whatever=${metadataname}" 526 527${metadataname} will be replaced by the current value of the 528same metadata name. The metadata names must be listed in the 529"metadata": [ ] section. 530 531### `http_resp_map` 532 533If your server overloads the meaning of the http transport response code with 534server-custom application codes, you can map these to discrete Secure Streams 535state callbacks using a JSON map, eg 536 537``` 538 "http_resp_map": [ { "530": 1530 }, { "531": 1531 } ], 539``` 540 541It's not recommended to abuse the transport layer http response code by 542mixing it with application state information like this, but if it's dealing 543with legacy serverside that takes this approach, it's possible to handle it 544in SS this way while removing the dependency on http. 545 546### `http_auth_header` 547 548The name of the header that takes the auth token, with a trailing ':', eg 549 550``` 551 "http_auth_header": "authorization:" 552``` 553 554### `http_dsn_header` 555 556The name of the header that takes the dsn token, with a trailing ':', eg 557 558``` 559 "http_dsn_header": "x-dsn:" 560``` 561 562### `http_fwv_header` 563 564The name of the header that takes the firmware version token, with a trailing ':', eg 565 566``` 567 "http_fwv_header": "x-fw-version:" 568``` 569 570### `http_devtype_header` 571 572The name of the header that takes the device type token, with a trailing ':', eg 573 574``` 575 "http_devtype_header": "x-device-type:" 576``` 577 578### `http_auth_preamble` 579 580An optional string that precedes the auth token, eg 581 582``` 583 "http_auth_preamble": "bearer " 584``` 585 586### `auth_hexify` 587 588Convert the auth token to hex ('A' -> "41") before transporting. Not necessary if the 589auth token is already in printable string format suitable for transport. Needed if the 590auth token is a chunk of 8-bit binary. 591 592### `nghttp2_quirk_end_stream` 593 594Set this to `true` if the peer server has the quirk it won't send a response until we have 595sent an `END_STREAM`, even though we have sent headers with `END_HEADERS`. 596 597### `h2q_oflow_txcr` 598 599Set this to `true` if the peer server has the quirk it sends an maximum initial tx credit 600of 0x7fffffff and then later increments it illegally. 601 602### `http_multipart_ss_in` 603 604Indicates that SS should parse any incoming multipart mime on this stream 605 606### `http_multipart_name` 607 608Indicates this stream goes out using multipart mime, and provides the name part of the 609multipart header 610 611### `http_multipart_filename` 612 613Indicates this stream goes out using multipart mime, and provides the filename part of the 614multipart header 615 616### `http_multipart_content_type` 617 618The `content-type` to mark up the multipart mime section with if present 619 620### `http_www_form_urlencoded` 621 622Indicate the data is sent in `x-www-form-urlencoded` form 623 624### `http_cookies` 625 626This streamtype should store and bring out http cookies from the peer. 627 628### `rideshare` 629 630For special cases where one logically separate stream travels with another when using this 631protocol. Eg, a single multipart mime transaction carries content from two or more streams. 632 633## ws transport 634 635### `ws_subprotocol` 636 637** CLIENT **: Name of the ws subprotocol to request from the server 638 639** SERVER **: Name of the subprotocol we will accept 640 641### `ws_binary` 642 643Use if the ws messages are binary 644 645### `ws_prioritize_reads` 646 647Set `true` if the event loop should prioritize keeping up with input at the 648potential expense of output latency. 649 650## MQTT transport 651 652### `mqtt_topic` 653 654Set the topic this streamtype uses for writes 655 656### `mqtt_subscribe` 657 658Set the topic this streamtype subscribes to 659 660### `mqtt qos` 661 662Set the QOS level for this streamtype 663 664### `mqtt_keep_alive` 665 66616-bit number representing MQTT keep alive for the stream. 667 668This is applied at connection time... where different streams may bind to the 669same underlying MQTT connection, all the streams should have an identical 670setting for this. 671 672### `mqtt_clean_start` 673 674Set to true if the connection should use MQTT's "clean start" feature. 675 676This is applied at connection time... where different streams may bind to the 677same underlying MQTT connection, all the streams should have an identical 678setting for this. 679 680### `mqtt_will_topic` 681 682Set the topic of the connection's will message, if any (there is none by default). 683 684This is applied at connection time... where different streams may bind to the 685same underlying MQTT connection, all the streams should have an identical 686setting for this. 687 688### `mqtt_will_message` 689 690Set the content of the connect's will message, if any (there is none by default). 691 692This is applied at connection time... where different streams may bind to the 693same underlying MQTT connection, all the streams should have an identical 694setting for this. 695 696### `mqtt_will_qos` 697 698Set the QoS of the will message, if any (there is none by default). 699 700This is applied at connection time... where different streams may bind to the 701same underlying MQTT connection, all the streams should have an identical 702setting for this. 703 704### `mqtt_will_retain` 705 706Set to true if the connection should use MQTT's "will retain" feature, if there 707is a will message (there is none by default). 708 709This is applied at connection time... where different streams may bind to the 710same underlying MQTT connection, all the streams should have an identical 711setting for this. 712 713## Loading and using updated remote policy 714 715If the default, hardcoded policy includes a streamtype `fetch_policy`, 716during startup when lws_system reaches the POLICY state, lws will use 717a Secure Stream of type `fetch_policy` to download, parse and update 718the policy to use it. 719 720The secure-streams-proxy minimal example shows how this is done and 721fetches its real policy from warmcat.com at startup using the built-in 722one. 723 724## Applying streamtype policy overlays 725 726This is intended for modifying policies at runtime for testing, eg, to 727force error paths to be taken. After the main policy is processed, you 728may parse additional, usually smaller policy fragments on top of it. 729 730Where streamtype names in the new fragment already exist in the current 731parsed policy, the settings in the fragment are applied over the parsed 732policy, overriding settings. There's a simple api to enable this by 733giving it the override JSON in one string 734 735``` 736int 737lws_ss_policy_overlay(struct lws_context *context, const char *overlay); 738``` 739 740but there are also other apis available that can statefully process 741larger overlay fragments if needed. 742 743An example overlay fragment looks like this 744 745``` 746 { "s": [{ "captive_portal_detect": { 747 "endpoint": "google.com", 748 "http_url": "/", 749 "port": 80 750 }}]} 751``` 752 753ie the overlay fragment completely follows the structure of the main policy, 754just misses out anything it doesn't override. 755 756Currently ONLY streamtypes may be overridden. 757 758You can see an example of this in use in `minimal-secure-streams` example 759where `--force-portal` and `--force-no-internet` options cause the captive 760portal detect streamtype to be overridden to force the requested kind of 761outcome. 762 763## Captive Portal Detection 764 765If the policy contains a streamtype `captive_portal_detect` then the 766type of transaction described there is automatically performed after 767acquiring a DHCP address to try to determine the captive portal 768situation. 769 770``` 771 "captive_portal_detect": { 772 "endpoint": "connectivitycheck.android.com", 773 "port": 80, 774 "protocol": "h1", 775 "http_method": "GET", 776 "http_url": "generate_204", 777 "opportunistic": true, 778 "http_expect": 204, 779 "http_fail_redirect": true 780 } 781``` 782 783## Stream serialization and proxying 784 785By default Secure Streams expects to make the outgoing connection described in 786the policy in the same process / thread, this suits the case where all the 787participating clients are in the same statically-linked image. 788 789In this case the `lws_ss_` apis are fulfilled locally by secure-streams.c and 790policy.c for policy lookups. 791 792However it also supports serialization, where the SS api can be streamed over 793another transport such as a Unix Domain Socket connection. This suits the case 794where the clients are actually in different processes in, eg, Linux or Android. 795 796In those cases, you run a proxy process (minimal-secure-streams-proxy) that 797listens on a Unix Domain Socket and is connected to by one or more other 798processes that pass their SS API activity to the proxy for fulfilment (or 799onward proxying). 800 801Each Secure Stream that is created then in turn creates a private Unix Domain 802Socket connection to the proxy for each stream. 803 804In this case the proxy uses secure-streams.c and policy.c as before to fulfil 805the inbound proxy streams, but uses secure-streams-serialize.c to serialize and 806deserialize the proxied SS API activity. The proxy clients define 807LWS_SS_USE_SSPC either very early in their sources before the includes, or on 808the compiler commandline... this causes the lws_ss_ apis to be replaced at 809preprocessor time with lws_sspc_ equivalents. These serialize the api action 810and pass it to the proxy over a Unix Domain Socket for fulfilment, the results 811and state changes etc are streamed over the Unix Domain Socket and presented to 812the application exactly the same as if it was being fulfilled locally. 813 814To demonstrate this, some minimal examples, eg, minimal-secure-streams and 815mimimal-secure-streams-avs build themselves both ways, once with direct SS API 816fulfilment and once with Unix Domain Socket proxying and -client appended on the 817executable name. To test the -client variants, run minimal-secure-streams-proxy 818on the same machine. 819 820## Complicated scenarios with secure streams proxy 821 822As mentioned above, Secure Streams has two modes, by default the application 823directly parses the policy and makes the outgoing connections itself. 824However when configured at cmake with 825 826``` 827-DLWS_WITH_SOCKS5=1 -DLWS_WITH_SECURE_STREAMS=1 -DLWS_WITH_SECURE_STREAMS_PROXY_API=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 828``` 829 830and define `LWS_SS_USE_SSPC` when building the application, applications forward 831their network requests to a local or remote SS proxy for fulfilment... and only 832the SS proxy has the system policy. By default, the SS proxy is on the local 833machine and is connected to via a Unix Domain Socket, but tcp links are also 834possible. (Note the proxied traffic is not encrypyed by default.) 835 836Using the configuration above, the example SS applications are built two ways, 837once for direct connection fulfilment (eg, `./bin/lws-minimal-secure-streams`), 838and once with `LWS_SS_USE_SSPC` also defined so it connects via an SS proxy, 839(eg, `./bin/lws-minimal-secure-streams-client`). 840 841## Testing an example scenario with SS Proxy and socks5 proxy 842 843``` 844 [ SS application ] --- tcp --- [ socks 5 proxy ] --- tcp --- [ SS proxy ] --- internet 845``` 846 847In this scenario, everything is on localhost, the socks5 proxy listens on :1337 and 848the SS proxy listens on :1234. The SS application connects to the socks5 849proxy to get to the SS proxy, which then goes out to the internet 850 851### 1 Start the SS proxy 852 853Tell it to listen on lo interface on port 1234 854 855``` 856$ ./bin/lws-minimal-secure-streams-proxy -p 1234 -i lo 857``` 858 859### 2 Start the SOCKS5 proxy 860 861``` 862$ ssh -D 1337 -N -v localhost 863``` 864 865The -v makes connections to the proxy visible in the terminal for testing 866 867### 3 Run the SS application 868 869The application is told to make all connections via the socks5 proxy at 870127.0.0.1:1337, and to fulfil its SS connections via an SS proxy, binding 871connections to 127.0.0.1 (ipv4 lo interface, -1), to 127.0.0.1:1234 (-a/-p). 872 873``` 874socks_proxy=127.0.0.1:1337 ./bin/lws-minimal-secure-streams-client -p 1234 -i 127.0.0.1 -a 127.0.0.1 875``` 876 877You can confirm this goes through the ssh socks5 proxy to get to the SS proxy 878and fulfil the connection. 879 880## Using static policies 881 882If one of your targets is too constrained to make use of dynamic JSON policies, but 883using SS and the policies is attractive for wider reasons, you can use a static policy 884built into the firmware for the constrained target. 885 886The secure-streams example "policy2c" (which runs on the build machine, not the device) 887 888https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/secure-streams/minimal-secure-streams-policy2c 889 890accepts a normal JSON policy on stdin, and emits a C code representation that can be 891included directly in the firmware. 892 893https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/secure-streams/minimal-secure-streams-staticpolicy/static-policy.h 894 895Using this technique it's possible to standardize on maintaining JSON policies across a 896range of devices with different contraints, and use the C conversion of the policy on devices 897that are too small. 898 899The Cmake option `LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY` should be enabled to use this 900mode, it will not build the JSON parser (and the option for LEJP can also be disabled if 901you're not otherwise using it, saving an additional couple of KB). 902 903Notice policy2c example tool must be built with `LWS_ROLE_H1`, `LWS_ROLE_H2`, `LWS_ROLE_WS` 904and `LWS_ROLE_MQTT` enabled so it can handle any kind of policy. 905 906## HTTP and ws serving 907 908All ws servers start out as http servers... for that reason ws serving is 909handled as part of http serving, if you give the `ws_subprotocol` entry to the 910streamtype additionally, the server will also accept upgrades to ws. 911 912To help the user code understand if the upgrade occurred, there's a special 913state `LWSSSCS_SERVER_UPGRADE`, so subsequent rx and tx can be understood to 914have come from the upgraded protocol. To allow separation of rx and tx 915handling between http and ws, there's a ss api `lws_ss_change_handlers()` 916which allows dynamically setting SS handlers. 917 918Since the http and ws upgrade identity is encapsulated in one streamtype, the 919user object for the server streamtype should contain related user data for both 920http and ws underlying protocol identity. 921