websocket
12 TopicsF5 AWAF with HTTP/2, MRF and Websocket profiles
Good day all, I have F5 Big-IP AWAF's (version 16.1.4.3) and I am trying to configure HTTP/2 with MRF. My colleague and I discovered that Websocket profiles on the Virtual Server don't play well when enabling MRF. Is there a way to enable a "hybrid" configuration using websocket and HTTP/2 with MRF? I value and appreciate your time and energy and look forward to hearing from you. Thank you.99Views0likes5Commentsenable WebSocket profile.
We want to enable WebSocket profile. I set is "websocket" in the virtual server To enable it, HTTP profile needs to be enabled. I set it "http" in the same virtual server We have SSL communication through F5 LTM from the internet, if I enable HTTP profile -- the connection is not established with the server. Anything I need to configure? Thanks in advance.Solved4.3KViews0likes9CommentsiRule to decode WebSocket negotiation and frames
Problem this snippet solves: WebSocket establishes a socket via HTTP upgrade and once socket is established subsequent messages are non-HTTP, but WebSocket frame. There might be a situation where you want to dump WebSocket negotiation and frame into log for troubleshooting purpose. This iRule dumps negotiation and WebSocket frame header fields, and payload (only text data). WebSocket frame format looks as below. RFC 6455 - 5.2. Base Framing Protocol 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-------+-+-------------+-------------------------------+ |F|R|R|R| opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16/64) | |N|V|V|V| |S| | (if payload len==126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + | Extended payload length continued, if payload len == 127 | + - - - - - - - - - - - - - - - +-------------------------------+ | |Masking-key, if MASK set to 1 | +-------------------------------+-------------------------------+ | Masking-key (continued) | Payload Data | +-------------------------------- - - - - - - - - - - - - - - - + : Payload Data continued ... : + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Payload Data continued ... | +---------------------------------------------------------------+ WebSocket frame is quite simple. The first 2 bytes are necessary and always present. Extended payload length exists only when Payload length is set to 126 (in this case Ext len is 16 bits) or 127 (in this case Ext len is 64 bits). Masking-key exists only if MASK bit is set to 1. FIN : If the frame is the last frame, set to 1. If payload is fragmented, the last frame should have FIN = 1. Other fragmented ones should have FIN = 0. RSV : If extension is not used, it is set to 0 opcode : This tells you if it is data frame (can be text or binary) or control frame. %x0:continuation frame %x1:text frame %x2:binary frame %x3-7:reserved for further %x8:connection close %x9:ping %xA:pong %xB-F:reserved for further MASK : When browser sends a data, this bit MUST be set to 1, which means data is masked using the Masking-key. When server sends a data, this bit MUST NOT set to 1 Payload len : If 0 - 125, this field represents the payload length If it is 126, then the Extended payload length (16bit) are used to tell the actual payload length (maximum data size is 65535 bytes) If it is 127, then the Extended payload length (64bit : MSB must be 0) are used to tell the actual payload length (maximum data size is 9223372036854775807 bytes) Extended payload length Only when Payload len is set to 126 Extended payload length_continued Only when Payload len is set to 127 Masking-key Used to mask data. Masking is to avoid proxy poisoning. Non-compliant HTTP proxy caches WebSocket data. If MASK bit is 1, this field is present. If MASK bit is 0, this field is not present. Client sets this key and it must be unpredictable. Payload Payload from client to server is masked using Masking-key. How to use this snippet: Here I am sending text data "DEAD BEEF" in WebSocket frame via WebSocket_cURL.py (https://github.com/jussmen/WebSocket_cURL). HTTP request and response (negotiation) look like below. $ python WebSocket_cURL.py 10.10.148.101 80 -s "DEAD BEEF" GET /ws HTTP/1.1 Host: 10.10.148.101 Connection: Upgrade Upgrade: websocket Sec-WebSocket-Version: 13 Sec-WebSocket-Key: n5twxG/tNPf8h3po+pNrPA== User-Agent: IE HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: y9WDs+d4zDl+qvQ7H17KpnP0EhI= This is how iRule dumps the negotiation and subsequent WebSocket frames in /var/log/ltm <ws_request>: ============================================= <ws_request>: Client 10.10.1.2:47427 -> 10.10.148.101/ws (request) <ws_request>: Host: 10.10.148.101 <ws_request>: Connection: Upgrade <ws_request>: Upgrade: websocket <ws_request>: Sec-WebSocket-Version: 13 <ws_request>: Sec-WebSocket-Key: n5twxG/tNPf8h3po+pNrPA== <ws_request>: User-Agent: IE <ws_request>: ============================================= <ws_response>: ============================================= <ws_response>: Client 10.10.1.2:47427 -> 10.10.148.101/ws (response) <ws_response>: Upgrade: websocket <ws_response>: Connection: Upgrade <ws_response>: Sec-WebSocket-Accept: y9WDs+d4zDl+qvQ7H17KpnP0EhI= <ws_response>: ============================================= <ws_server_frame>: ============================================= <ws_server_frame>: FIN bit : 1 <ws_server_frame>: MASK bit : 1 <ws_server_frame>: MASK : 0 <ws_server_frame>: Type : Text - 1 <ws_server_frame>: ============================================= <ws_server_data>: ============================================= <ws_server_data>: The server says: 'Hello'. Connection was accepted. <ws_server_data>: ============================================= <ws_client_frame>: ============================================= <ws_client_frame>: FIN bit : 1 <ws_client_frame>: MASK bit : 1 <ws_client_frame>: MASK : 1178944834 <ws_client_frame>: Type : Text - 1 <ws_client_frame>: ============================================= <ws_client_data>: ============================================= <ws_client_data>: DEAD BEEF <ws_client_data>: ============================================= <ws_server_frame>: ============================================= <ws_server_frame>: FIN bit : 1 <ws_server_frame>: MASK bit : 1 <ws_server_frame>: MASK : 0 <ws_server_frame>: Type : Text - 1 <ws_server_frame>: ============================================= <ws_server_data>: ============================================= <ws_server_data>: The server says: DEAD BEEF back at you <ws_server_data>: ============================================= <ws_client_frame>: ============================================= <ws_client_frame>: FIN bit : 1 <ws_client_frame>: MASK bit : 1 <ws_client_frame>: MASK : 1178944834 <ws_client_frame>: Type : Connection close - 8 <ws_client_frame>: ============================================= <ws_server_frame>: ============================================= <ws_server_frame>: FIN bit : 1 <ws_server_frame>: MASK bit : 1 <ws_server_frame>: MASK : 0 <ws_server_frame>: Type : Connection close - 8 <ws_server_frame>: ============================================= Code : when WS_REQUEST { # Copied from : https://devcentral.f5.com/s/articles/log-http-headers set LogString "Client [IP::client_addr]:[TCP::client_port] -> [HTTP::host][HTTP::uri]" log local0. "=============================================" log local0. "$LogString (request)" foreach aHeader [HTTP::header names] { log local0. "$aHeader: [HTTP::header value $aHeader]" } log local0. "=============================================" } when WS_RESPONSE { # Copied from : https://devcentral.f5.com/s/articles/log-http-headers log local0. "=============================================" log local0. "$LogString (response)" foreach aHeader [HTTP::header names] { log local0. "$aHeader: [HTTP::header value $aHeader]" } log local0. "=============================================" } when WS_CLIENT_FRAME { log local0. "=============================================" log local0. "FIN bit : [WS::frame eom]" log local0. "MASK bit : [WS::frame orig_masked]" if { [WS::frame orig_masked] eq 0 } { log local0. "Not masked. Client frame MUST be masked." } if { [WS::frame orig_masked] eq 1 } { log local0. "MASK : [WS::frame mask]" } switch -glob [WS::frame type] { "0" { log local0. "Type : Continuatoin frame - 0" } "1" { log local0. "Type : Text - 1" WS::collect frame } "2" { log local0. "Type : Binary - 2" } "3" - "4" - "5" - "6" - "7" { log local0. "Type : Reserved type (3-7) - [WS::frame type]" } "8" { log local0. "Type : Connection close - 8" } "9" { log local0. "Type : ping - 9" } "10" { log local0. "Type : pong - 10" } "11" - "12" - "13" - "14" - "15" { log local0. "Type : Reserved type (11-15) - [WS::frame type]" } } log local0. "=============================================" } when WS_SERVER_FRAME { log local0. "=============================================" log local0. "FIN bit : [WS::frame eom]" log local0. "MASK bit : [WS::frame orig_masked]" if { [WS::frame orig_masked] eq 1 } { log local0. "MASK : [WS::frame mask]" } switch -glob [WS::frame type] { "0" { log local0. "Type : Continuatoin frame - 0" } "1" { log local0. "Type : Text - 1" WS::collect frame } "2" { log local0. "Type : Binary - 2" } "3" - "4" - "5" - "6" - "7" { log local0. "Type : Reserved type (3-7) - [WS::frame type]" } "8" { log local0. "Type : Connection close - 8" } "9" { log local0. "Type : ping - 9" } "10" { log local0. "Type : pong - 10" } "11" - "12" - "13" - "14" - "15" { log local0. "Type : Reserved type (11-15) - [WS::frame type]" } } log local0. "=============================================" } #when WS_CLIENT_FRAME_DONE { #log local0. "WS_CLIENT_FRAME_DONE" #} #when WS_SERVER_FRAME_DONE { #log local0. "WS_SERVER_FRAME_DONE" #} when WS_CLIENT_DATA { log local0. "=============================================" log local0. "[WS::payload]" log local0. "=============================================" WS::release } when WS_SERVER_DATA { log local0. "=============================================" log local0. "[WS::payload]" log local0. "=============================================" WS::release } Tested this on version: 12.0920Views0likes0CommentsIssues with reverse proxying the application using socket.io and Secure Websockets
Hello, I am trying to setup a reverse proxy for the application written with socket.io which tries to upgrade the connection to Secure Websockets. Looking at the docs WSS should be supported in BIG-IP 11.5.4, however I am getting some connection errors as per below (trace from the Firebug): The connection to wss://host.example.com/launchpad/socket.io/?EIO=3&transport=websocket&sid=GTQLD62vWeuwQwIzAAIp was interrupted while the page was loading. socket.io.js (line 3, col 1049) Are there any limitations known when using LTM and WSS ? In my existing lab configuration I am using both rewrite rules and stream profiles to rewrite URLs. Thanks a lot for any comments Regards282Views0likes0Commentsusing websocket via ASM
Hi all. I'm testing about ASM v11.4.1 and a website using websocket. I wonder ASM can support websocket. In my test, LTM can support websocket but ASM can't support it. When apply ASM policy to VirtualServer, I can't show websocket part. So I made a iRule, that is below: when CLIENT_ACCEPTED { HTTP::enable } when HTTP_REQUEST { if { ([string tolower [HTTP::header value Upgrade]] equals "websocket" ) && ([string tolower [HTTP::header value Connection]] equals "upgrade" ) } { log local0. "HTTP Disable" ASM::disable } } In this iRule, when websocket traffic is come, it disable ASM and pass to LTM. But it means, if some web attacks are come through websocket, ASM can't block attacks. In addition, if i change iRule from ASM::disable to HTTP::disable, page loading is slowed. Does any solution using with ASM and websocket?783Views0likes8CommentsWebsocket iRule
Hello everybody, hope you could help me with this , my thinking is this needs custom iRule . We are using Mango Automation system , and when we put it behind F5 LTM some parts (like gauges etc.) stop to function. I see these are websocket connections? Does anybody have experience with this ? They even have some documentation for Apache rev. proxy here in the link: https://docs-v4.mango-os.com/proxy thanks Damir1.3KViews0likes6CommentsWSS LTM not passing data correctly
Hi, i'm having some trouble about running an Virtual Server in front of a K3s ingress. I've setted up 4 virtual server, all point to the same destination address, but different port (different pool but final address is the same, only change the port) For Http/s, MQTT/s zero problem, but when i'm trying to redirect the http traffic using websocket i've several problem. Destination return several errors based on the Virtual Server tuning. Actually i've the virtual server configured in TCP with HTTP profile (Websocket enable both client and server) and in security profile i've created a wss security to allow * addresses (HTTP,HTTPS,WS,WSS) But when we try the application it return ERR_TRUNCATE_HEADERS. I've also create a new http profile based on the default, to increse the size of che Header Payload. Also no i'm not checking the payload, and ignore any possible malformed packet (just to let everything pass). On the application event log i can see all the request and i see the green thick so i suppose that everything is fine on the F5 side. How can i be sure of that? Is there a way to do extra check or am i missing something? Thank you guys. PaoloSolved1.7KViews0likes10CommentsClarification about WebSocket and ASM
As indicated in https://support.f5.com/csp/article/K14754, if an application uses websockets and an ASM policy has been activated on the related virtual server, a websocket profile is expected to be associated with that virtual server; if the websocket profile is missing, traffic interruptions occur despite the WAF policy being in transparent mode. Is it possible to disable checks on the ASM policy relating to websockets instead of associating a websocket profile to the virtual server?Solved998Views0likes1CommentHTML5 WebSocket rewriting
I am having an issue with rewriting my WebSocket connection. Let me explain my scenario, and then I will explain the issue I am experiencing. On my Internal network (192.168.252.x) I have a HTML5 gateway device(252.100), that is used to establish an HTML5 RDP session. This component is setup correctly, from the internal network I am able to log into the web based interface and successfully establish an HTML5 based RDP connection from my HTML5 gateway device (252.100) to my target machine 252.101. What I am trying to accomplish is to do this HTML5 RDP connection going through the F5. From the webtop, my user will click on a portal access link. This portal access link takes the user to the web based front-end of my HTML5 gateway device via and https webpage. My user is able to successfully go through the webtop, and log into my web front end. The issue occurs when starting the HTML5 RDP session from the webtop. My HTML5 proxy machine is throwing an error saying Websocket closed. Tracing the network traffic between all components, there is no traffic flow from the HTML gateway and the Target machine, and no traffic flows into the HTML gateway. This is due to the fact that the Websocket is not being rewritten by the F5. I will try to attach an image with the Chrome dev console that shows this websocket address: In short: when a new websocket is created I get the following: WebSocket connection to 'wss://192.168.252.100/myservice?mypage.hsl_mode=DIRECT&servicename_name=encodedlinkname failed: Error in connection establishment net::ERR_CONNECTION_TIMED_OUT. What I would expect to see is not the direct Internal IP address of the HTML5 gateway but some External IP from the F5 since the websocket should be rewritten by F5. My External net address is 192.168.210.x. I am testing from 192.168.210.100 and my F5 External self IP is 192.168.210.22. So I would expect to see that the websocket address would the External SelfIP. I have attempted playing around with the HTTP profile, Redirect Rewrite settings (None, All, Matching, and Nodes). But this didn't seem to help. I have also tried creating a WebSocket profile and tested all the Masking settings, (Preserve, Unmask, Selective, and Remmask) Also no dice. I have tested quite a few settings on the other profiles as well without any luck. Any suggestions would be helpful. As a side note: I was able to get this successfully running on Big-ip 11.4. With the same configuration, I am not able to get this working on our newer 12.1 implementation. I am also currently unable to observe the 11.4 websocket creation behavior as this VE install has eaten itself while trying to do a version update.. But that is another story.1.6KViews0likes9Comments