2016-02-04 04:36:11 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httputil"
|
|
|
|
"os"
|
2016-06-04 21:55:10 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
2016-05-09 15:30:16 +00:00
|
|
|
|
|
|
|
"github.com/VividCortex/godaemon"
|
|
|
|
"gopkg.in/alecthomas/kingpin.v2"
|
2016-02-04 04:36:11 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
routedHostnames map[string]int
|
2016-06-04 21:55:10 +00:00
|
|
|
// Sites are the enabled sites
|
|
|
|
Sites []Site
|
|
|
|
// HTTPClient is the http client
|
|
|
|
HTTPClient http.Client
|
2016-02-04 04:36:11 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
logFileLoc = kingpin.Flag("log", "Location of the log file").Default("stdout").String()
|
2016-05-09 15:30:16 +00:00
|
|
|
daemonize = kingpin.Flag("daemon", "If daemonized, the program will run in the background.").Default("false").Bool()
|
2016-02-04 04:36:11 +00:00
|
|
|
sitesLoc = kingpin.Flag("sites_dir", "Location of site files").Short('h').Default("/etc/hostsplitter/").String()
|
|
|
|
bindAddr = kingpin.Flag("bind", "Bind address").Short('b').Default(":80").String()
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
HTTPClient = http.Client{}
|
|
|
|
|
|
|
|
kingpin.Parse()
|
|
|
|
|
2016-06-04 21:55:10 +00:00
|
|
|
fmt.Println("Starting hostsplitter")
|
2016-02-04 04:36:11 +00:00
|
|
|
|
|
|
|
if *logFileLoc != "stdout" {
|
|
|
|
logFile, err := os.OpenFile(*logFileLoc, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0640)
|
|
|
|
defer logFile.Close()
|
|
|
|
if err != nil {
|
2016-06-04 21:55:10 +00:00
|
|
|
fmt.Println("error opening file: %v", err)
|
2016-02-04 04:36:11 +00:00
|
|
|
}
|
2016-06-04 21:55:10 +00:00
|
|
|
fmt.Println("Using ", *logFileLoc, " for logging")
|
|
|
|
//log.SetOutput(logFile)
|
2016-02-04 04:36:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if *daemonize {
|
2016-06-04 21:55:10 +00:00
|
|
|
fmt.Println("Daemonizing... Bye Bye")
|
2016-02-04 04:36:11 +00:00
|
|
|
godaemon.MakeDaemon(&godaemon.DaemonAttr{})
|
|
|
|
}
|
|
|
|
|
|
|
|
LoadConfig()
|
|
|
|
|
|
|
|
go SignalHandler()
|
|
|
|
|
2016-06-04 21:55:10 +00:00
|
|
|
fmt.Println(http.ListenAndServe(*bindAddr, &httputil.ReverseProxy{
|
2016-02-04 04:36:11 +00:00
|
|
|
Director: func(r *http.Request) {
|
|
|
|
if i, ok := routedHostnames[string(r.Host)]; ok {
|
2016-02-05 17:23:13 +00:00
|
|
|
r.Header.Set("X-Hostsplitter-Secret", Sites[i].Secret)
|
2016-02-04 04:36:11 +00:00
|
|
|
r.Header.Set("Host", r.Host)
|
|
|
|
r.URL.Scheme = "http"
|
|
|
|
r.URL.Host = Sites[i].GetBackend()
|
|
|
|
r.RequestURI = ""
|
2016-06-04 21:55:10 +00:00
|
|
|
HTTPLogger(r, http.StatusOK)
|
2016-02-04 04:36:11 +00:00
|
|
|
} else {
|
2016-06-04 21:55:10 +00:00
|
|
|
r.URL.Host = ""
|
|
|
|
r.URL.Scheme = ""
|
|
|
|
HTTPLogger(r, http.StatusBadRequest)
|
2016-02-04 04:36:11 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2016-06-04 21:55:10 +00:00
|
|
|
const apacheFormatPattern = "%s - - [%s] \"%s %s %s\" %d %d \"%s\" \"%s\" %.4f\n"
|
|
|
|
|
|
|
|
// HTTPLogger logs an http request
|
|
|
|
func HTTPLogger(r *http.Request, status int) {
|
|
|
|
if *logFileLoc != "stdout" {
|
|
|
|
logFile, err := os.OpenFile(*logFileLoc, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0640)
|
|
|
|
defer logFile.Close()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("error opening file: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
timeFormatted := time.Now().Format("02/Jan/2006 03:04:05")
|
|
|
|
clientIP := r.RemoteAddr
|
|
|
|
if colon := strings.LastIndex(clientIP, ":"); colon != -1 {
|
|
|
|
clientIP = clientIP[:colon]
|
|
|
|
}
|
|
|
|
|
|
|
|
referer := r.Referer()
|
|
|
|
if referer == "" {
|
|
|
|
referer = "-"
|
|
|
|
}
|
|
|
|
|
|
|
|
userAgent := r.UserAgent()
|
|
|
|
if userAgent == "" {
|
|
|
|
userAgent = "-"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprint(logFile, fmt.Sprintf(
|
|
|
|
apacheFormatPattern,
|
|
|
|
clientIP,
|
|
|
|
timeFormatted,
|
|
|
|
r.Method,
|
|
|
|
r.RequestURI,
|
|
|
|
r.Proto,
|
|
|
|
status,
|
|
|
|
0,
|
|
|
|
referer,
|
|
|
|
userAgent,
|
|
|
|
0.00,
|
|
|
|
))
|
|
|
|
}
|
2016-02-04 04:36:11 +00:00
|
|
|
}
|
2016-06-04 21:55:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
record := &ApacheLogRecord{
|
|
|
|
ResponseWriter: rw,
|
|
|
|
ip: clientIP,
|
|
|
|
time: time.Time{},
|
|
|
|
method: r.Method,
|
|
|
|
uri: r.RequestURI,
|
|
|
|
protocol: r.Proto,
|
|
|
|
status: http.StatusOK,
|
|
|
|
referer: referer,
|
|
|
|
userAgent: userAgent,
|
|
|
|
elapsedTime: time.Duration(0),
|
|
|
|
}
|
|
|
|
*/
|