Add check for referrer in req.Referer

- typo as per standard
This commit is contained in:
Matija Obreza 2019-01-20 21:50:29 +01:00 committed by Matija Obreza
parent 50d8d71b08
commit 4b94b27a06
5 changed files with 77 additions and 2 deletions

View File

@ -35,6 +35,13 @@ URL_PREFIX=
# served using HTTP.
TLS_CERT=
TLS_KEY=
# List of accepted HTTP referrers. Return 403 if HTTP header `Referer` does not
# match prefixes provided in the list.
# Examples:
# 'REFERRERS=http://localhost,https://...,https://another.name'
# To accept missing referrer header, add a blank entry (start comma):
# 'REFERRERS=,http://localhost,https://another.name'
REFERRERS=
```
### YAML Configuration File
@ -53,6 +60,9 @@ folder: /web
url-prefix: ""
tls-cert: ""
tls-key: ""
referrers:
- http://localhost
- https://my.site
```
## Deployment

View File

@ -63,6 +63,10 @@ ENVIRONMENT VARIABLES
The prefix to use in the URL path. If supplied, then the prefix must
start with a forward-slash and NOT end with a forward-slash. If not
supplied then no prefix is used.
REFERRERS
A comma-separated list of valid HTTP Referer prefixes. If incoming header
value is not in this list, a 403 HTTP error is returned.
Examples: 'http://localhost,https://some.site,http://other.site:8080'
CONFIGURATION FILE
Configuration can also managed used a YAML configuration file. To select the
@ -81,6 +85,8 @@ CONFIGURATION FILE
tls-cert: ""
tls-key: ""
url-prefix: ""
referrers:
- http://localhost
----------------------------------------------------------------------------
USAGE
@ -99,7 +105,7 @@ USAGE
export PORT=80
static-file-server
Retrieve with: wget http://my.machine/sub/my.file
export FOLDER=/var/www
static-file-server -c config.yml
Result: Runs with values from config.yml, but with the folder being

View File

@ -34,11 +34,16 @@ func Run() error {
// configuration.
func handlerSelector() (handler http.HandlerFunc) {
var serveFileHandler handle.FileServerFunc
serveFileHandler = http.ServeFile
if config.Get.Debug {
serveFileHandler = handle.WithLogging(serveFileHandler)
}
if config.Get.Referrers != nil {
serveFileHandler = handle.WithReferrers(serveFileHandler, config.Get.Referrers)
}
// Choose and set the appropriate, optimized static file serving function.
if 0 == len(config.Get.URLPrefix) {
handler = handle.Basic(serveFileHandler, config.Get.Folder)

View File

@ -22,6 +22,7 @@ var (
TLSCert string `yaml:"tls-cert"`
TLSKey string `yaml:"tls-key"`
URLPrefix string `yaml:"url-prefix"`
Referrers []string `yaml:"referrers"`
}
)
@ -34,6 +35,7 @@ const (
tlsCertKey = "TLS_CERT"
tlsKeyKey = "TLS_KEY"
urlPrefixKey = "URL_PREFIX"
referrersKey = "REFERRERS"
)
const (
@ -61,6 +63,7 @@ func setDefaults() {
Get.TLSCert = defaultTLSCert
Get.TLSKey = defaultTLSKey
Get.URLPrefix = defaultURLPrefix
Get.Referrers = nil
}
// Load the configuration file.
@ -108,6 +111,7 @@ func overrideWithEnvVars() {
Get.TLSCert = envAsStr(tlsCertKey, Get.TLSCert)
Get.TLSKey = envAsStr(tlsKeyKey, Get.TLSKey)
Get.URLPrefix = envAsStr(urlPrefixKey, Get.URLPrefix)
Get.Referrers = strAsArray(envAsStr(referrersKey, ""))
}
// validate the configuration.
@ -211,3 +215,11 @@ func strAsBool(value string) (result bool, err error) {
}
return
}
func strAsArray(value string) (result []string) {
if (value == "") {
return nil
}
result = strings.Split(value, ",");
return
}

View File

@ -26,12 +26,54 @@ type ListenerFunc func(string, http.HandlerFunc) error
// requesting client.
type FileServerFunc func(http.ResponseWriter, *http.Request, string)
func validReferrer(s []string, e string) bool {
if (s == nil) {
// log.Printf("No referrers specified, all fine.")
return true
}
// log.Printf("Checking referrers " + strings.Join(s, ",") + " against " + e)
for _, a := range s {
// Handle blank HTTP Referer header, if configured
if (a == "") {
if (e == "") {
// log.Printf("No referrer in request. Allowing.");
return true;
}
// Continue loop (all strings start with "")
continue;
}
// Compare header with allowed prefixes
if strings.HasPrefix(e, a) {
// log.Printf(strings.Join([]string{ "Referrer match", e, a }, " "));
return true
}
}
return false
}
func WithReferrers(serveFile FileServerFunc, referrers []string) FileServerFunc {
return func(w http.ResponseWriter, r *http.Request, name string) {
if (validReferrer(referrers, r.Referer())) {
// log.Printf("Serving file.")
serveFile(w, r, name)
} else {
// log.Printf(strings.Join([]string{"Invalid referrer", r.Referer(), "Not in", strings.Join(referrers, ",")}, " "))
http.Error(w, strings.Join([]string{ "Invalid source", r.Referer() }, " "), 403)
return
}
}
}
// WithLogging returns a function that logs information about the request prior
// to serving the requested file.
func WithLogging(serveFile FileServerFunc) FileServerFunc {
return func(w http.ResponseWriter, r *http.Request, name string) {
log.Printf(
"REQ: %s %s %s%s -> %s\n",
"REQ from %s: %s %s %s%s -> %s\n",
r.Referer(),
r.Method,
r.Proto,
r.Host,