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:
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)
}
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?
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)
},
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With