From 62fa5c31ba39ebf968f98a7ee46525f14c0ea97c Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Wed, 23 Mar 2016 16:05:38 +0100 Subject: Rewrite into config-les setup --- main.go | 126 ++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 59 insertions(+), 67 deletions(-) (limited to 'main.go') diff --git a/main.go b/main.go index 946603f..e54cd96 100644 --- a/main.go +++ b/main.go @@ -4,107 +4,99 @@ import ( "crypto/tls" "errors" "flag" - "io/ioutil" "log" "net/http" "net/http/httputil" + "net/rpc" "net/url" - "sync" - - "gopkg.in/yaml.v2" ) var ( config = flag.String("conf", "certs/goxy.yml", "configuration file") - listen = flag.String("listen", ":http", "HTTP") - listenTLS = flag.String("listentls", ":https", "TLS") + listen = flag.String("listen", ":http", "HTTP port") + listenTLS = flag.String("listentls", ":https", "TLS port") + listenRPC = flag.String("listenrpc", ":http-alt", "RPC port") + data = flag.String("data", "data/goxy.gob", "persistent storage file") + route = make(Route) + mux = http.NewServeMux() ) -type Config map[string]Route +type Route map[string]Entry -type Route struct { - CertFile string - KeyFile string - Upstream string - cert *tls.Certificate +type Entry struct { + ServerName 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 +func (r Route) SNI(h *tls.ClientHelloInfo) (*tls.Certificate, error) { + if e, ok := r[h.ServerName]; ok && e.Cert != nil { + return e.Cert, nil } return nil, errors.New("no cert for " + h.ServerName) } -func (r *Route) LoadCert() error { - if r.CertFile == "" && r.KeyFile == "" { - return nil +func (r Route) Restore() { + *mux = *http.NewServeMux() + for _, e := range route { + e.NewHandle() } - cert, err := tls.LoadX509KeyPair(r.CertFile, r.KeyFile) +} + +func (e Entry) NewHandle() error { + log.Println("New handle", e) + up, err := url.Parse(e.Upstream) if err != nil { return err } - r.cert = &cert + mux.Handle(e.ServerName+"/", httputil.NewSingleHostReverseProxy(up)) return nil } -func (r Route) String() string { - if r.cert != nil { - return r.Upstream + " with TLS" +func (e Entry) String() string { + if e.Cert != nil { + return e.ServerName + " -> " + e.Upstream + " with TLS" } else { - return r.Upstream + return e.ServerName + " -> " + e.Upstream } } -func LoadConfig(fname string) (Config, error) { - conf, err := ioutil.ReadFile(fname) - if err != nil { - return Config{}, err +func StartHTTP(listen string) { + log.Println("listen", listen, "(HTTP)") + s := http.Server{ + Addr: listen, + Handler: mux, + } + log.Fatal(s.ListenAndServe()) +} + +func StartTLS(listen string) { + log.Println("listen", listen, "(TLS)") + s := http.Server{ + Addr: listen, + Handler: mux, + TLSConfig: &tls.Config{GetCertificate: route.SNI}, } - var c Config - return c, yaml.Unmarshal(conf, &c) + log.Fatal(s.ListenAndServeTLS("", "")) +} + +func StartRPC(listen string) { + log.Println("listen", listen, "(RPC)") + rpc.HandleHTTP() + log.Fatal(http.ListenAndServe(listen, nil)) } 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)) + if err := route.Load(*data); err != nil { + log.Println(err) } + route.Restore() + + go StartHTTP(*listen) + go StartTLS(*listenTLS) + go StartRPC(*listenRPC) - 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() + select {} } -- cgit v1.2.3