From 96350677c89d46dbaabf8d1813ca494b56efb02d Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Tue, 22 Mar 2016 19:41:46 +0100 Subject: Inital import --- main.go | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 main.go (limited to 'main.go') diff --git a/main.go b/main.go new file mode 100644 index 0000000..46180fd --- /dev/null +++ b/main.go @@ -0,0 +1,110 @@ +package main + +import ( + "crypto/tls" + "errors" + "flag" + "io/ioutil" + "log" + "net/http" + "net/http/httputil" + "net/url" + "sync" + + "gopkg.in/yaml.v2" +) + +var ( + config = flag.String("conf", "goxy.yml", "configuration file") + listen = flag.String("listen", ":http", "HTTP") + listenTLS = flag.String("listentls", ":https", "TLS") +) + +type Config map[string]Route + +type Route struct { + CertFile string + KeyFile string + Upstream string + cert *tls.Certificate +} + +func (c Config) SNI(h *tls.ClientHelloInfo) (*tls.Certificate, error) { + if r, ok := c[h.ServerName]; ok && r.cert != nil { + return r.cert, nil + } + return nil, errors.New("no cert for " + h.ServerName) +} + +func (r *Route) LoadCert() error { + if r.CertFile == "" && r.KeyFile == "" { + return nil + } + cert, err := tls.LoadX509KeyPair(r.CertFile, r.KeyFile) + if err != nil { + return err + } + r.cert = &cert + return nil +} + +func (r Route) String() string { + if r.cert != nil { + return r.Upstream + " with TLS" + } else { + return r.Upstream + } +} + +func LoadConfig(fname string) (Config, error) { + conf, err := ioutil.ReadFile(fname) + if err != nil { + return Config{}, err + } + var c Config + return c, yaml.Unmarshal(conf, &c) +} + +func main() { + flag.Parse() + c, err := LoadConfig(*config) + if err != nil { + log.Fatal(err) + } + + for k, v := range c { + if err := v.LoadCert(); err != nil { + log.Println("load", err) + continue + } + c[k] = v + up, err := url.Parse(v.Upstream) + if err != nil { + log.Println("upstream", err) + continue + } + log.Println("map", k, "to", v) + http.Handle(k+"/", httputil.NewSingleHostReverseProxy(up)) + } + + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + log.Println("listen", *listenTLS) + s := http.Server{ + Addr: *listenTLS, + TLSConfig: &tls.Config{GetCertificate: c.SNI}, + } + log.Fatal(s.ListenAndServeTLS("", "")) + }() + go func() { + defer wg.Done() + log.Println("listen", *listen) + s := http.Server{ + Addr: *listen, + } + log.Fatal(s.ListenAndServe()) + }() + wg.Wait() +} -- cgit v1.2.3