How do I Black Hole a standard Go Network Request

Viewed 179

I am experimenting with the Go's httpuitls.ReverseProxy and http.HandleFunc. I am trying to create a way to Black Hole certain routes in my simple proxy as shown below. How do I get the http library to completely throw out my request without responding or sending a disconnect?

This example hopefully clarifies what I mean. See the /toss route below.

package main

import (
    "log"
    "net/http"
    "net/http/httputil"
    "net/url"
)

func main() {
    origin, _ := url.Parse("https://www.example.com:443/")

    director := func(req *http.Request) {
        req.URL.Scheme = "https"
        req.URL.Host = origin.Host
        req.Host = origin.Host
    }

    proxy := &httputil.ReverseProxy{Director: director}

    http.HandleFunc("/toss", func(w http.ResponseWriter, r *http.Request) {
        // What goes here to Black Hole this request??
    })

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        proxy.ServeHTTP(w, r)
    })

    log.Fatal(http.ListenAndServe(":8080", nil))
}

Adding a little context to the question, the ultimate goal here is to use this proxy with a destructive testing tool. The idea being that the clients are never given a response to certain routes and it allows the user of the tool to see how their applications will handle this.

2 Answers

Hijack the connection from the server. Close the connection.

    if h, ok := w.(http.Hijacker); ok {
        c, _, err := h.Hijack()
        if err == nil {
            c.Close()
            return
        }
    }
    // Fallback to bad request.
    http.Error(w, "bad request", http.StatusBadRequest)

Run it on the Go Playground.

Hijack can fail because of middleware blocking access to the server's response writer, middleware wrote to the connection before then handler was called or because the the connection is using the http/2 protocol. The call to http.Error is a fallback for those scenarios.

There's no other option for abandoning the connection without doing something at the network layer.

Hijacking the connection without also closing the connection leaks file descriptors. The file descriptors may be eventually closed by low-level connection's finalizer, but the process may breach the file descriptor limit before that happens.

How do I get the http library to completely throw out my request without responding or sending a disconnect?

This requirement would essentially mean that the socket to the client stays alive, eating up resources at the server. Thus this kind of black-holing would be a bad idea. When interacting with the OS kernel or firewall it might be possible to close the socket locally only without the client noticing. But this will get very tricky and system depdend since for quickly cleaning up local resources it is usually required that the system got the reply from the client that the socket was closed on their end too etc.

An easier way would be to respond with a redirect to a different port on the same host and then simply drop (not reject) all traffic to this port at the firewall. Clients will usually blindly follow the redirect and than hang there until the connection attempt times out. This will thwart clients without eating up resources at the server.

Related