summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Anderson <[email protected]>2017-01-01 15:53:01 -0800
committerDavid Anderson <[email protected]>2017-01-01 15:53:01 -0800
commite0a01587f5d3c412231f18012f3f55743c5aa885 (patch)
tree09558564d57ad19872b087f526fd0bda7f397599
parent09cc4bb6199e7c8ef49d4c3f5e4077b49f892407 (diff)
Add slowloris protection, in the form of a ClientHello timeout.
-rw-r--r--main.go26
1 files changed, 24 insertions, 2 deletions
diff --git a/main.go b/main.go
index 9acefef..c1ac324 100644
--- a/main.go
+++ b/main.go
@@ -25,8 +25,11 @@ import (
"time"
)
-var cfgFile = flag.String("conf", "", "configuration file")
-var listen = flag.String("listen", ":443", "listening port")
+var (
+ cfgFile = flag.String("conf", "", "configuration file")
+ listen = flag.String("listen", ":443", "listening port")
+ helloTimeout = flag.Duration("hello-timeout", 3*time.Second, "how long to wait for the TLS ClientHello")
+)
var config Config
@@ -71,6 +74,15 @@ func (c *Conn) logf(msg string, args ...interface{}) {
func (c *Conn) abort(alert byte, msg string, args ...interface{}) {
c.logf(msg, args...)
alertMsg := []byte{21, 3, byte(c.tlsMinor), 0, 2, 2, alert}
+
+ if err := c.SetWriteDeadline(time.Now().Add(*helloTimeout)); err != nil {
+ c.logf("error while setting write deadline during abort: %s", err)
+ // Do NOT send the alert if we can't set a write deadline,
+ // that could result in leaking a connection for an extended
+ // period.
+ return
+ }
+
if _, err := c.Write(alertMsg); err != nil {
c.logf("error while sending alert: %s", err)
}
@@ -82,6 +94,11 @@ func (c *Conn) sniFailed(msg string, args ...interface{}) { c.abort(112, msg
func (c *Conn) proxy() {
defer c.Close()
+ if err := c.SetReadDeadline(time.Now().Add(*helloTimeout)); err != nil {
+ c.internalError("Setting read deadline for ClientHello: %s", err)
+ return
+ }
+
var (
err error
handshakeBuf bytes.Buffer
@@ -92,6 +109,11 @@ func (c *Conn) proxy() {
return
}
+ if err = c.SetReadDeadline(time.Time{}); err != nil {
+ c.internalError("Clearing read deadline for ClientHello: %s", err)
+ return
+ }
+
c.backend = config.Match(c.hostname)
if c.backend == "" {
c.sniFailed("no backend found for %q", c.hostname)