From b38b4959f62af16511c135bfcdf9fc83e40d2c2a Mon Sep 17 00:00:00 2001 From: Mark Dain Date: Sat, 16 Jun 2018 09:43:39 +0100 Subject: [PATCH] Initial commit of tls-redirector This is a tiny HTTP server that redirects all incoming, valid traffic to HTTPS. --- .gitignore | 5 +++ LICENSE | 21 +++++++++++ README.md | 23 ++++++++++++ main.go | 67 ++++++++++++++++++++++++++++++++++ systemd/tls-redirector.service | 9 +++++ systemd/tls-redirector.socket | 10 +++++ 6 files changed, 135 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 main.go create mode 100644 systemd/tls-redirector.service create mode 100644 systemd/tls-redirector.socket diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..80ddc36 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +#macOS +.DS_Store + +#tls-redirector +tls-redirector diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..be810dc --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Mark Dain + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c4be99c --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# ancarda/tls-redirector + +_A tiny service for port 80 that rewrites URLs to HTTPS_ + +[![License](https://img.shields.io/github/license/ancarda/tls-redirector.svg)](https://choosealicense.com/licenses/mit/) +[![Go Report Card](https://goreportcard.com/badge/github.com/ancarda/tls-redirector)](https://goreportcard.com/report/github.com/ancarda/tls-redirector) + +tls-redirector is a tiny HTTP server that is designed to run on +port 80 and redirect all incoming traffic to HTTPS. It does this +by emitting a 301 Permanent Redirect where the scheme is simply +replaced with "https". + +### Features + + * Can run as an unprivileged user by use of systemd activation sockets. + * Requires no disk access, making sandboxing trivial. + * IP address traffic (usually by crawlers) is dropped. + +### Possible Caveats + + * The `host` field is required to redirect (there's no way to configure a + default), and visitors without one will simply see an error message. + * Must be running on a Linux distribution with systemd for now. diff --git a/main.go b/main.go new file mode 100644 index 0000000..1dc3716 --- /dev/null +++ b/main.go @@ -0,0 +1,67 @@ +// Package main implements tls-redirector, a microservice that +// is designed to forward all HTTP traffic to HTTPS. +package main + +import ( + "log" + "net" + "net/http" + + "github.com/coreos/go-systemd/activation" +) + +func isIPAddress(host string) bool { + if net.ParseIP(host) != nil { + return true + } + + if host, _, err := net.SplitHostPort(host); err == nil { + if net.ParseIP(host) != nil { + return true + } + } + + return false +} + +func handle(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Server", "tls-redirector/1.0") + + // If we haven't been given a host, just abort. + if r.Host == "" { + http.Error(w, "tls-redirector cannot handle this request because no `host` header was sent by your browser.", http.StatusBadRequest) + return + } + + // If we've seen a direct request, such as an IP address, + // we'll discard it now. Not only is it uncommon to see + // X.509 certificates for IP addresses, it's very likely + // to be junk traffic (scanning bots). We can save the + // real web server some effort by dropping it now. + if isIPAddress(r.Host) { + http.Error(w, "tls-redirector cannot redirect IP addresses.", http.StatusBadRequest) + return + } + + // Overwrite the scheme to https:// and redirect. + // Change host as well as in r.URL, it's empty. + r.URL.Host = r.Host + r.URL.Scheme = "https" + http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently) +} + +func main() { + http.HandleFunc("/", handle) + + listeners, err := activation.Listeners() + log.Println(listeners) + if err != nil { + log.Panicf("cannot retrieve listeners: %s", err) + } + + if len(listeners) != 1 { + log.Panicf("unexpected number of socket activation (%d != 1)", len(listeners)) + } + + log.Fatal(http.Serve(listeners[0], nil)) +} diff --git a/systemd/tls-redirector.service b/systemd/tls-redirector.service new file mode 100644 index 0000000..4f8a011 --- /dev/null +++ b/systemd/tls-redirector.service @@ -0,0 +1,9 @@ +[Unit] +Description=TLS Redirector (http to https) +After=tls-redirector.socket + +[Service] +Type=simple +ExecStart=/usr/bin/tls-redirector +Restart=on-failure +User=nobody diff --git a/systemd/tls-redirector.socket b/systemd/tls-redirector.socket new file mode 100644 index 0000000..ffc8c67 --- /dev/null +++ b/systemd/tls-redirector.socket @@ -0,0 +1,10 @@ +[Unit] +Description=TLS Redirector Port 80 (socket) +After=network.target + +[Socket] +ListenStream=80 +BindIPv6Only=both + +[Install] +WantedBy=sockets.target