cloudflared/socks/connection_handler_test.go
Lee Valentine 206523344f TUN-4017: Add support for using cloudflared as a full socks proxy.
To use cloudflared as a socks proxy, add an ingress on the server
side with your desired rules. Rules are matched in the order they
are added.  If there are no rules, it is an implicit allow.  If
there are rules, but no rule matches match, the connection is denied.

ingress:
  - hostname: socks.example.com
    service: socks-proxy
    originRequest:
      ipRules:
        - prefix: 1.1.1.1/24
          ports: [80, 443]
          allow: true
        - prefix: 0.0.0.0/0
          allow: false

On the client, run using tcp mode:
cloudflared access tcp --hostname socks.example.com --url 127.0.0.1:8080

Set your socks proxy as 127.0.0.1:8080 and you will now be proxying
all connections to the remote machine.
2021-03-10 21:26:12 +00:00

90 lines
2.0 KiB
Go

package socks
import (
"encoding/json"
"io/ioutil"
"net"
"net/http"
"testing"
"time"
"github.com/stretchr/testify/assert"
"golang.org/x/net/proxy"
)
type successResponse struct {
Status string `json:"status"`
}
func sendSocksRequest(t *testing.T) []byte {
dialer, err := proxy.SOCKS5("tcp", "127.0.0.1:8086", nil, proxy.Direct)
assert.NoError(t, err)
httpTransport := &http.Transport{}
httpClient := &http.Client{Transport: httpTransport}
// set our socks5 as the dialer
httpTransport.Dial = dialer.Dial
req, err := http.NewRequest("GET", "http://127.0.0.1:8085", nil)
assert.NoError(t, err)
resp, err := httpClient.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
assert.NoError(t, err)
return b
}
func startTestServer(t *testing.T, httpHandler func(w http.ResponseWriter, r *http.Request)) {
// create a socks server
requestHandler := NewRequestHandler(NewNetDialer(), nil)
socksServer := NewConnectionHandler(requestHandler)
listener, err := net.Listen("tcp", "localhost:8086")
assert.NoError(t, err)
go func() {
defer listener.Close()
for {
conn, _ := listener.Accept()
go socksServer.Serve(conn)
}
}()
// create an http server
mux := http.NewServeMux()
mux.HandleFunc("/", httpHandler)
// start the servers
go http.ListenAndServe("localhost:8085", mux)
}
func respondWithJSON(w http.ResponseWriter, v interface{}, status int) {
data, _ := json.Marshal(v)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
w.Write(data)
}
func OkJSONResponseHandler(w http.ResponseWriter, r *http.Request) {
resp := successResponse{
Status: "ok",
}
respondWithJSON(w, resp, http.StatusOK)
}
func TestSocksConnection(t *testing.T) {
startTestServer(t, OkJSONResponseHandler)
time.Sleep(100 * time.Millisecond)
b := sendSocksRequest(t)
assert.True(t, len(b) > 0, "no data returned!")
var resp successResponse
json.Unmarshal(b, &resp)
assert.True(t, resp.Status == "ok", "response didn't return ok")
}