Add check for referrer in req.Referer

- typo as per standard
pull/19/head
Matija Obreza 5 years ago committed by Matija Obreza
parent 50d8d71b08
commit 4b94b27a06
  1. 10
      README.md
  2. 8
      cli/help/help.go
  3. 5
      cli/server/server.go
  4. 12
      config/config.go
  5. 44
      handle/handle.go

@ -35,6 +35,13 @@ URL_PREFIX=
# served using HTTP. # served using HTTP.
TLS_CERT= TLS_CERT=
TLS_KEY= 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 ### YAML Configuration File
@ -53,6 +60,9 @@ folder: /web
url-prefix: "" url-prefix: ""
tls-cert: "" tls-cert: ""
tls-key: "" tls-key: ""
referrers:
- http://localhost
- https://my.site
``` ```
## Deployment ## Deployment

@ -63,6 +63,10 @@ ENVIRONMENT VARIABLES
The prefix to use in the URL path. If supplied, then the prefix must 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 start with a forward-slash and NOT end with a forward-slash. If not
supplied then no prefix is used. 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 FILE
Configuration can also managed used a YAML configuration file. To select the Configuration can also managed used a YAML configuration file. To select the
@ -81,6 +85,8 @@ CONFIGURATION FILE
tls-cert: "" tls-cert: ""
tls-key: "" tls-key: ""
url-prefix: "" url-prefix: ""
referrers:
- http://localhost
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
USAGE USAGE
@ -99,7 +105,7 @@ USAGE
export PORT=80 export PORT=80
static-file-server static-file-server
Retrieve with: wget http://my.machine/sub/my.file Retrieve with: wget http://my.machine/sub/my.file
export FOLDER=/var/www export FOLDER=/var/www
static-file-server -c config.yml static-file-server -c config.yml
Result: Runs with values from config.yml, but with the folder being Result: Runs with values from config.yml, but with the folder being

@ -34,11 +34,16 @@ func Run() error {
// configuration. // configuration.
func handlerSelector() (handler http.HandlerFunc) { func handlerSelector() (handler http.HandlerFunc) {
var serveFileHandler handle.FileServerFunc var serveFileHandler handle.FileServerFunc
serveFileHandler = http.ServeFile serveFileHandler = http.ServeFile
if config.Get.Debug { if config.Get.Debug {
serveFileHandler = handle.WithLogging(serveFileHandler) 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. // Choose and set the appropriate, optimized static file serving function.
if 0 == len(config.Get.URLPrefix) { if 0 == len(config.Get.URLPrefix) {
handler = handle.Basic(serveFileHandler, config.Get.Folder) handler = handle.Basic(serveFileHandler, config.Get.Folder)

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

@ -26,12 +26,54 @@ type ListenerFunc func(string, http.HandlerFunc) error
// requesting client. // requesting client.
type FileServerFunc func(http.ResponseWriter, *http.Request, string) 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 // WithLogging returns a function that logs information about the request prior
// to serving the requested file. // to serving the requested file.
func WithLogging(serveFile FileServerFunc) FileServerFunc { func WithLogging(serveFile FileServerFunc) FileServerFunc {
return func(w http.ResponseWriter, r *http.Request, name string) { return func(w http.ResponseWriter, r *http.Request, name string) {
log.Printf( log.Printf(
"REQ: %s %s %s%s -> %s\n", "REQ from %s: %s %s %s%s -> %s\n",
r.Referer(),
r.Method, r.Method,
r.Proto, r.Proto,
r.Host, r.Host,

Loading…
Cancel
Save