Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Golang reverse proxy blocked by Cloudflare while Nginx works alright?

For example, I have this simplest nginx.conf for the Nginx reverse proxy:

worker_processes  1;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       8081;

        location / {
          proxy_pass https://icanhazip.com;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

And this simple reverse proxy program implemented in Go:

package main

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

func main() {
    testUrl, err := url.Parse("https://icanhazip.com")
    if err != nil {
        log.Fatal(err)
    }

    proxy := httputil.NewSingleHostReverseProxy(testUrl)

    server := http.Server{
        Addr:    fmt.Sprintf(":%d", 8082),
        Handler: http.HandlerFunc(proxy.ServeHTTP),
    }

    if err := server.ListenAndServe(); err != http.ErrServerClosed {
        log.Fatal(err)
    }
}

After I got both services running on my local computer, access to the Nginx reverse proxy service is working without problem, returning my ip address correctly:

# curl http://127.0.0.1:8081
92.**7.1**.112

But access to the Go reverse proxy program result in a Cloudflare error:

# curl http://127.0.0.1:8082
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>cloudflare</center>
</body>
</html>

Since they are both running on the same computer and trying to access the same destination URL, it got to be something wrong with this Go reverse proxy program? Anyway I can make the Go reverse proxy program working the same way as Nginx?

So far I have tried the following:

  1. Overriding the Director function to set some headers, for example
    proxy := httputil.NewSingleHostReverseProxy(testUrl)
 
    originalDirector := proxy.Director
    proxy.Director = func(req *http.Request) {
        originalDirector(req)
        req.Header.Set("Host", req.Host)
    }
  1. Making a new ReverseProxy struct with custom Rewrite with SetXForward and things, for example
    proxy := &httputil.ReverseProxy{
                Rewrite: func(r *httputil.ProxyRequest) {
                    r.SetURL(testUrl)
                    r.Out.Host = r.In.Host
                    r.SetXForwarded()
                    r.Out.Header.Set("Host", r.In.Host)
                },
            }

So far nothing works, the Go reverse proxy program is still blocked by Cloudflare while Nginx works alright.

On another note this Go reverse proxy program does work with local URLs, for example if I change the URL to:

testUrl, err := url.Parse("http://127.0.0.1:8081")

Then it can chain with the Nginx reverse proxy and work as expected. So any idea how to make it work with remote URLs like Nginx does?

like image 721
hellopeach Avatar asked Oct 15 '25 19:10

hellopeach


1 Answers

After fumbling around, stumbled upon the solution myself, it seems many of the docs and tutorials out there are doing a lot more stuffs to the request object and headers that ends up a bit confusing, and setting all kinds of headers and stuff may actually make it more likely to get blocked by some CDN services.

In the end it seems just one modification of the request struct is sufficient to make the Go reverse proxy work with Cloudflare CDN

   proxy := httputil.NewSingleHostReverseProxy(testUrl)
 
    originalDirector := proxy.Director
    proxy.Director = func(req *http.Request) {
        originalDirector(req)
        req.Host = req.URL.Host
    }

Or using the new ReverseProxy struct method, it seems you don't need to modify anything at all (it's the modifications of the request structs I followed from the docs that made things worse)

    proxy := &httputil.ReverseProxy{
        Rewrite: func(r *httputil.ProxyRequest) {
            r.SetURL(testUrl)
        },
    }
like image 124
hellopeach Avatar answered Oct 18 '25 13:10

hellopeach



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!