Translation Go Httpserver Best Practices

Source: Internet
Author: User
Tags response write cloudflare cipher suite

This is an article by Cloudflare Filippo Valsorda, published in Gopher Academy in 2016, although it has been in the past two years, but it still has meaning.

Previously crypto/tls too slow and net/http very young, so for Go Web server, it is usually wise of us to put it behind the reverse proxy, such as Nginx, and now do not need.

In CloudFlare we recently experimented with direct burst of pure go service as a host. Go 1.8 net/http and crypto/tls provides stable, high-performance and flexible functionality.

Then, some tuning work needs to be done, and this article will show you how to tune and make the Web server more stable.

Crypto/tls

2016 years, you will no longer run an unencrypted HTTP Server, so you need to crypto/tls . The good news is that the library is already very fast (our test), and now his security attack tracking is excellent.

The default configuration is to use the intermediate recommended configuration in the Mozilla reference, but you should still set up PreferServerCipherSuites to ensure a faster and more secure password vault, CurvePreferences avoiding the curves that are not optimized. The client if using the CurveP384 algorithm back causes our machine to consume up to 1 seconds of CPU.

12345678910
&tls. config{//causes servers to use Go ' s default ciphersuite preferences,//which is tuned to avoid attacks. Does nothing on clients. true,//only if use curves which has assembly implementations//Go 1.8only},}

If you want to configure compatibility, you can set MinVersion and CipherSuites .

1234567891011121314
Minversion:tls. Versiontls12,ciphersuites: []uint16//Go 1.8only TLS. tls_ecdhe_rsa_with_chacha20_poly1305,   //Go 1.8only TLS. Tls_ecdhe_ecdsa_with_aes_128_gcm_sha256,tls. tls_ecdhe_rsa_with_aes_128_gcm_sha256,//best disabled, as they don ' t provide Forward secrecy,//but might b E necessary for some clients//TLS. tls_rsa_with_aes_256_gcm_sha384,//TLS. tls_rsa_with_aes_128_gcm_sha256,   },

Note that the implementation of the CBC cipher Suite for Go (which we disabled above) is easy to receive LUCKY13 attacks, even though go 1.8 implements some of the processing.

Finally, it is important to note that all of these recommendations apply only to the AMD64 architecture because it enables fast, constant-level cryptographic primitives (AES-GCM, chacha20-poly1305, P256), and other architectures may not be suitable for product-level applications.

Since it is a service to be burst with the Internet, it requires a publicly trusted certificate. By Let’s Encrypt easily applying, you can use golang.org/x/crypto/acme/autocert the GetCertificate function.

Do not forget to redirect http to HTTPS, if your client is a browser, you can consider HSTS.

12345678910
5 * time. Second,writetimeout: 5 * time. Second,handler:http. Handlerfunc (func(w http. Responsewriter, req *http. Request) {W.header (). Set ("Connection""Close" "https://" + req. Host + req. Url. String () http. Redirect (w, req, URL, http. statusmovedpermanently)}),}gofunc() {log. Fatal (SRV. Listenandserve ())} ()

You can use SSL Labs test to check that the configuration is correct.

Net/http

net/httpContains HTTP/1.1 and HTTP/2 . You must already be familiar with the development of handler, so this article does not discuss it. We discuss some of the scenarios behind the server side.

Timeout

Timeouts can be the most easily overlooked dangerous scenario. Your service may be spared in the controlled network, but it will not be so fortunate on the Internet, especially (not just) being attacked by malicious means.

There are a number of resources that require timeout control. Although Goroutine consumes little, file descriptors are always limited. Stuck connections, non-working connections, or even malicious disconnected connections should not consume them.

A server that exceeds the maximum file symbol is always unable to accept a new connection and will report the following failure:

1
http: Accept error:accept TCP [::]:openfilesin1s

A default http.Server , like the example in the pack documentation file http.ListenAndServe http.ListenAndServeTLS , without setting any timeout control, you're definitely not what you want.

http.ServerThere are three parameters to control the timeout: ReadTimeout , WriteTimeout and IdleTimeout , you can set them in the display:

12345678
SRV: = &http. server{     5 * time. Second,    writetimeout: Ten * time. Second,      * time. Second,    tlsconfig:    tlsconfig,    Handler:      servemux,}log. Println (SRV. Listenandservetls ("" "))

ReadTimeoutThe time range is self-connected, and ends with the requested body being fully read out. In net/http the implementation it is Accept set after the connection SetReadDeadline .

ReadTimeoutThe biggest problem is that it does not allow the server to give the client more time to request the body stream. Go 1.8 introduces a new parameter ReadHeaderTimeout that ends with reading the request header. Then there have been some unclear ways to set the read timeout, the relevant design discussion can refer to #16100.

WriteTimeoutTime-out normally starting from reading the request header, ending at the end of the response write (that ServeHTTP is, the life cycle), through readRequest the SetWriteDeadline settings.

Then, when connected over HTTPS, SetWriteDeadline Accept It is set immediately after, so it also contains the TLS handshake for the packet write. What's annoying is that this means WriteTimeout containing the HTTP header's read as well as the first byte of the wait.

ReadTimeoutAnd WriteTimeout is absolute, it cannot be changed in handler (#16100).

Go 1.8 also introduces new IdleTimeout parameters to limit the number of idle server Keep-Alive connections before reuse.

The previous version of Go 1.8, when the ReadTimeout request was completed and immediately began ticking (tick), this Keep-Alive is not appropriate for the connection: idle time consumes the client to allow the request to be sent, causing some fast clients to have unexpected timeouts.

For untrusted clients and networks, you should set Read , Write and Idle timeout, so that a client that reads or writes slowly does not consume a connection for a long time.

For the background of the http/1.1 timeout before go 1.8, you can refer to CloudFlare's blog.

Http/2

HTTP/2 is automatically enabled back in Go 1.6+ as long as it meets the following conditions:

    • Request throughTLS/HTTPS
    • Server.TLSNextProtoNil (if an empty map is set, HTTP/2 is disabled)
    • Server.TLSConfighas been set, ListenAndServeTLS called, or the next
    • Serveis called and tls.Config.NextProtos contains h2 (for example []string{"H2", "http/1.1")

HTTP/2 and http/1.1 are somewhat different because the same connection serves multiple requests at the same time, but go abstracts the Unified Timeout control interface.

Unfortunately, go 1.7 ReadTimeout interrupts the HTTP/2 connection, which does not reset for each connection, but instead resets it when the connection is first established, and disconnects the HTTP/2 connection when it expires. Go 1.8 fixes this issue.

Based on this and ReadTimeout the idle time issue, I strongly recommend that you upgrade to 1.8 as soon as possible.

TCP keep-alives

If you use ListenAndServe (unlike incoming net.Listener Serve , this method uses the default value to provide 0 protection), the 3-minute TCP keep-alive will be set automatically, it will let the completely disappearing client have the opportunity to abandon the connection, my experience is not to fully believe it, Set the timeout anyway.

First of all, 3 minutes is too long and you can use your own to tcpKeepAliveListener adjust it. 、

More importantly, Keep-Alive just make sure the client is still alive, but will not set a limit on the connection survival. A malicious client will open a very large number of connections, causing your server to open many file descriptors that will cause your service to be denied service through outstanding requests.

Finally, my experience is that connections often lead to leaks, knowing that timeouts work.

Servemux

The package level http.Handle[Func] (and your web framework) is registered handler to the global http.DefaultServeMux , and if Server.Handler it is nil, you should avoid doing so.

Any package you enter, whether direct or indirect, can be accessed http.DefaultServeMux and may register the route you do not expect.

For example, if any of the libraries in the package dependency are imported net/http/pprof , the client can get the profile of your application's CPU. You can use net/http/pprof manual registration.

The right thing to do is initialize your own http.ServeMux , register the handler on top of it, set it to Server.Handler , or set your own web framework for Server.Handler .

Logging

Net/http does a lot of work before calling your handler, such as accepting connections https://github.com/golang/go/blob/1106512db54fc2736c7a9a67dd553fc9e1fca742 /src/net/http/server.go#l2631-l2653, TLS handshake, etc...

When any one step goes wrong, it writes a line of logs to Server.ErrorLog . Some of these errors, such as timeouts and connection resets, are normal on the Internet. You can connect most of the errors and add them to the metric, thanks to this guarantee:

Each logging operation makes a single call to the Writer ' s Write method.

If you do not want to output the stack log in handler, you can use panic(nil) or use go 1.8 panic(http.ErrAbortHandler) .

Metrics

Metric can help you monitor open file descriptors. Prometheus uses proc the file system to help you do this.

If you need to investigate leaks, you can use Server.ConnState hooks to get more details of the connection metric. Note that there is no way to maintain the correct number of state without maintaining the state StateActive , so you need to maintain one map[net.Conn]ConnState .

Conclusion

Using Nginx to do the front end of the Go service log is gone, but in the face of the internet you still need to do some additional protection, you may need to upgrade to the new go 1.8 version.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.