0

I'm doing a simple reverse proxy operation, while the server running in the background normally works on cloudflare, I start getting an endless number of "connect: connection refused" errors when I get behind the reverse proxy.

I use standard go libraries, no extras optimization of performance improvement.

There is no sample code that I can share here, because I did a very simple process..

The website I'm dealing with receives 4-5 million requests per day, and there is an incredible number of requests live. I had no problems with standard websites, but a website of this scale hard me. Is there a trick you can recommend me?

Jun 19 03:44:33 ubuntu main[492935]: 2021/06/19 03:44:33 http: proxy error: dial tcp xx.xxx.x.xx:80: connect: connection refused
Jun 19 03:44:33 ubuntu main[492935]: 2021/06/19 03:44:33 http: proxy error: dial tcp xx.xxx.x.xx:80: connect: connection refused
... repeated many many times ...

Edit post; After the comments, I wanted to share my code as well.

package main

import (
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httputil"
    "net/url"
    "time"
)

type server struct {
    proxy *httputil.ReverseProxy
}

func handler(handler http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        s := &server{}
        ob := &resp{ResponseWriter: w}
        s.ServeHTTP(ob, r)
        log.Printf("%s %s \"%s %s %s\" %d %d \"%s\" \"%s\"", r.RemoteAddr, r.Host, r.Method, r.URL.Path, r.Proto, ob.status, ob.written, r.Referer(), r.UserAgent())
    })
}

type resp struct {
    http.ResponseWriter
    status      int
    written     uint64
    wroteHeader bool
}

func (o *resp) Write(p []byte) (bytes int, err error) {
    if !o.wroteHeader {
        o.WriteHeader(http.StatusOK)
    }
    bytes, err = o.ResponseWriter.Write(p)
    o.written += uint64(bytes)
    return
}

func (o *resp) WriteHeader(code int) {
    o.ResponseWriter.WriteHeader(code)
    if o.wroteHeader {
        return
    }
    o.wroteHeader = true
    o.status = code
}

func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    backend, _ := url.Parse("http://10.0.0.10")
    s.proxy = httputil.NewSingleHostReverseProxy(backend)
    s.proxy.ServeHTTP(w, r)
}

func main() {
    base := &server{}
    http.Handle("/", base)
    s := &http.Server{
        Addr:         ":80",
        Handler:      handler(http.DefaultServeMux),
        ReadTimeout:  30 * time.Second,
        WriteTimeout: 60 * time.Second,
        IdleTimeout:  120 * time.Second,
        ErrorLog:     log.New(ioutil.Discard, "", 0),
    }
    log.Panicln(s.ListenAndServe())
}
  • 1
    Looks like the upstream server is not able to handle the load. Cloudflare is not a simple reverse proxy but is a CDN, which means it will also cache content and serve the cached content, thus reducing the load on the server. And it might also create a more efficient connection to the upstream than your code, like making sure that multiple requests are sent over a single connection. *"There is no sample code that I can share here, because I did a very simple process.."* - how is "simple process" an excuse? I don't think we can actually help here w/o understanding what your code actually does. – Steffen Ullrich Jun 19 '21 at 04:55
  • "Connection refused" means the server isn't running on the specified host:port, or is firewalled off, or an intermediate host prevents the connection. There's nothing else we can do to help you here, especially without any code to look at. We can't debug your network for you. – Peter Jun 19 '21 at 07:15
  • @SteffenUllrich Of course, I do not compare my work with CloudFlare, I just did not explain it correctly. The website is completely running on cloudflare, the backend server and the backend server hardware features that I wrote with go are the same. When I direct it to the server running nginx php-fpm, it's fine, but I'm having a problem with my go reverse proxy server. I know the problem is not resource usage and there is no firewall blocking either. – Osman Makal Jun 19 '21 at 08:19
  • @Peter I understood, there is no problem in my network, not about this, I wanted to ask if there is anything I don't know about golang reverse proxy, I missed it. I'm using the standard go libraries. – Osman Makal Jun 19 '21 at 08:21
  • @OsmanMakal: I'm still not sure about your setup. Let's see if I understand your setup correctly: the setup working is `cloudflare -> nginx`. The setup causing trouble is `cloudflare -> your reverse proxy -> nginx`. And the trouble is that most requests actually succeed but some fail due do connection refused. Is this correct? – Steffen Ullrich Jun 19 '21 at 10:43
  • @SteffenUllrich Yes, exactly as you write. – Osman Makal Jun 19 '21 at 11:56

1 Answers1

0

... the setup working is cloudflare -> nginx. The setup causing trouble is cloudflare -> your reverse proxy -> nginx. And the trouble is that most requests actually succeed but some fail due do connection refused.

These error messages mean that nginx behind the reverse proxy simply cannot keep up with the load. In this case the TCP listen queue fills up to the limit and new connections will be rejected. So it is not a problem of your proxy, but a problem of the nginx behind the proxy.

It might actually be that the same happens when the site is accessed directly by Cloudflare, but you simply have no access to similar logs files from Cloudflare.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Thanks for your answer, but while the website is working properly behind cloudflare, it keeps giving 502 error when using cloudflare -> go proxy > nginx – Osman Makal Jun 19 '21 at 14:30
  • @OsmanMakal: What do you mean with *"keeps giving 502 error"*? From my understanding of your question (based on the comments) the website is mostly working and only a few request fail? – Steffen Ullrich Jun 19 '21 at 14:33