Slide 1

Slide 1 text

HTTP Tunneling in Go Kazuki Higashiguchi April 23, 2022 @ Go Conference 2022 Spring

Slide 2

Slide 2 text

Agenda HTTP(S) Client WebSocket server WebSocket client HTTP(S) Server 1. HTTP Tunneling 2. Establish bidirectional connection using WebSocket 3. HTTP Tunneling over WebSocket

Slide 3

Slide 3 text

About Me Kazuki Higashiguchi Backend Engineer at Autify. ID: @hgsgtk

Slide 4

Slide 4 text

Autify Solution No-code AI-powered software testing automation services for Web/Mobile applications AI automatically maintenance test scripts No code unlocks automation at scale

Slide 5

Slide 5 text

Agenda HTTP(S) Client WebSocket server WebSocket client HTTP(S) Server 1. HTTP Tunneling 2. Establish bidirectional connection using WebSocket 3. HTTP Tunneling over WebSocket

Slide 6

Slide 6 text

HTTP tunneling ● Create a network link between two computers in conditions of restricted network connectivity. e.g. firewalls, NATs, ACLs ● Use a protocol of higher level (HTTP) to transport a lower level protocol (TCP)

Slide 7

Slide 7 text

HTTP CONNECT method ● Start bidirectional communications with the requested resource e.g. access HTTPS websites, HTTP proxy server HTTP(S) Client HTTP(S) Server Proxy (Gateway)

Slide 8

Slide 8 text

HTTP tunneling with CONNECT Quoted from HTTP: The Definitive Guide / 8.5 Tunnels 1. Client sends CONNECT request 2. Gateway opens TCP connection to the server 3. Gateway returns HTTP ready message to the client 4. Start bidirectional communication of raw packets of data

Slide 9

Slide 9 text

A case study: elazarl/goproxy elazarl/goproxy: An HTTP proxy library for Go $ curl -I -x http://localhost:8080 https://example.com HTTP/1.0 200 OK A basic sample code:

Slide 10

Slide 10 text

Tunneling implementation in elazarl/goproxy https://github.com/elazarl/goproxy/blob/0bfa7c564b 5ffbece2f0832eb4e714fb971f70f3/https.go#L95

Slide 11

Slide 11 text

Tunneling implementation in elazarl/goproxy 1 2 3

Slide 12

Slide 12 text

Step 1: Take over the proxy connection http.Hijacker interface allows an HTTP handler to take over the connection.

Slide 13

Slide 13 text

Step 2: Open TCP connections Opens TCP connection using net.Dial Returns HTTP ready message: 200 Connection established

Slide 14

Slide 14 text

Step 3: Streaming with io.Copy

Slide 15

Slide 15 text

Streaming: TLS handshake over TCP connection ● TLS handshake is done using the streaming ● Application data is sent and receive after TLS handshake

Slide 16

Slide 16 text

Key takeaways ● HTTP Tunneling uses a protocol of higher level (HTTP) to transport a lower level protocol (TCP) ● The basic flow of HTTP tunneling using the HTTP Connect method ● http.Hijack and io.Copy are key functions to implement HTTP tunneling in Go

Slide 17

Slide 17 text

Agenda HTTP(S) Client WebSocket server WebSocket client HTTP(S) Server 1. HTTP Tunneling 2. Establish bidirectional connection using WebSocket 3. HTTP Tunneling over WebSocket

Slide 18

Slide 18 text

Establish bidirectional connections WebSocket server WebSocket client Handshake WebSocket Conn WebSocket Conn HTTP(S) Client WebSocket server WebSocket client HTTP(S) Server

Slide 19

Slide 19 text

Bidirectional connections ● Long/short polling ● WebSockets ● Server-Sent Events ● HTTP/2 Push ● etc

Slide 20

Slide 20 text

WebSockets ● A mechanism for low-cost, full-duplex communication on Web ● Designed to work over HTTP (compatible with the HTTP protocol) ● Handshake -> Messages -> Close

Slide 21

Slide 21 text

WebSocket client and server using gorilla/websocket Client: gorilla/websocket: an WebSocket implementation in Go Server:

Slide 22

Slide 22 text

websocket.Conn implementation websocket.Conn has net.Conn in the unexported field. The return value of http.Hijack will be set to the field conn. https://github.com/gorilla/websocket/blob/eeb877e8a1fd26c449b7af3cb1d71879287d724c/server.go#L125

Slide 23

Slide 23 text

Agenda HTTP(S) Client WebSocket server WebSocket client HTTP(S) Server 1. HTTP Tunneling 2. Establish bidirectional connection using WebSocket 3. HTTP Tunneling over WebSocket

Slide 24

Slide 24 text

HTTP Tunneling over WebSocket HTTP(S) Client HTTP(S) Server WebSocket server WebSocket client WebSocket Conn WebSocket Conn TCP Conn TCP Conn $ curl -Lv -x http://websocket-server https://target.local WebSocket server and WebSocket client jointly act as a proxy(gateway). https://target.local http://websocket-server streaming streaming

Slide 25

Slide 25 text

How HTTP Tunneling over WebSocket

Slide 26

Slide 26 text

How HTTP Tunneling with WebSocket WebSocket server tells the address of destination to WebSocket client. WebSocket client open a TCP connection to the destination server.

Slide 27

Slide 27 text

How HTTP Tunneling with WebSocket Bidirectional message over an established WebSocket connection.

Slide 28

Slide 28 text

WebSocket server implementation A sample code available on github.com/hgsgtk/go-snippets

Slide 29

Slide 29 text

WebSocket server implementation 1 2 3

Slide 30

Slide 30 text

Step 1: Write messages to WebSocket connection Send a TCP handshake request with the destination address.

Slide 31

Slide 31 text

Distinguish several types of messages This design transfers several kinds of message over a single WebSocket connection ● Request to open TCP connections ● Notify to establish TCP connections ● Streaming raw packets of data ● etc

Slide 32

Slide 32 text

A case study: Chrome Devtools Protocol CDP defines the JSON protocol, which is used to communicate in the WebSocket connection. Request Members: id, method, params Response Members: id, result, (error)

Slide 33

Slide 33 text

Define own protocol for WebSocket communication A small example of methods ● Handshake: Request to open TCP connections ● Completed: Notify to establish TCP connections ● Communication: Streaming raw packets of data

Slide 34

Slide 34 text

Step 2: Take over the proxy connection 2 Take over the connection using http.Hijacker.

Slide 35

Slide 35 text

Step 3: Streaming 3 Use io.Copy to combine WebSocket connection and TCP connection.

Slide 36

Slide 36 text

Notes on net.Conn returned from http.Hijack ● http.Hijacker returns net.Conn and bufio.ReadWriter. [Code comment on http.Hijack] The returned bufio.Reader may contain unprocessed buffered data from the client. ● Reading net.Conn alone may cause data to be dropped. ● Read buffers from bufio.Reader.

Slide 37

Slide 37 text

Wrap websocket.Conn to use in io.Copy: io.Writer Pack incoming packets to defined JSON format ンu��(gT��!"�. ��ҠF��0�Q��Yl/��L�E8/���c<��>���C� ��m$�X�Ax�Y%^��J�v�[�o�U�a���U�t �u��5��k��m��&|Ǜq����)�z7����?�… { "method": 3, "data": "ンu��(gT��!"�. ��ҠF��0�Q��Yl/��L�E8/���c<��>� ��C���m$�X�Ax�Y%^��J�v� [�o�U�a���U�t �u��5��k��m��&|Ǜq����) �z7����?�… " }

Slide 38

Slide 38 text

Wrap websocket.Conn to use in io.Copy: io.Reader Read packets from a decoded JSON message ンu��(gT��!"�. ��ҠF��0�Q��Yl/��L�E8/���c<��>���C� ��m$�X�Ax�Y%^��J�v�[�o�U�a���U�t �u��5��k��m��&|Ǜq����)�z7����?�… { "method": 3, "data": "ンu��(gT��!"�. ��ҠF��0�Q��Yl/��L�E8/���c<��>� ��C���m$�X�Ax�Y%^��J�v� [�o�U�a���U�t �u��5��k��m��&|Ǜq����) �z7����?�… " }

Slide 39

Slide 39 text

WebSocket client implementation

Slide 40

Slide 40 text

Open a TCP connection to the given destination Dial to the destination address conn, err := net.Dial("tcp", “autify.com:443”)

Slide 41

Slide 41 text

Key takeaways ● HTTP Tunneling over WebSocket ● Define own protocol for WebSocket communication and create a wrap struct for streaming with io.Copy ● Should read both net.Conn and bufio.ReadWriter returned from http.Hijacker

Slide 42

Slide 42 text

Resources ● RFC 6455 The WebSocket Protocol ● IETF: Tunneling TCP based protocols through Web proxy servers ● Mmdn web doc: Proxy servers and tunneling ● Mmdn web doc: CONNECT ● Wikipedia: HTTP Tunnel ● Wikipedia: WebSocket ● HTTP: The Definitive Guide / 8.5 Tunnels ● Cloudflare: What happens in a TLS handshake? | SSL handshake ● Chrome DevTools Protocol

Slide 43

Slide 43 text

Resources ● elazarl/goproxy ● gorilla/websocket ● github.com/hgsgtk/go-snippets/gocon2022spring/tcpws

Slide 44

Slide 44 text

Thank you for your watching We are taking demo requests https://autify.com/ Autify for Web Autify for Mobile