aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-03-22 19:41:46 +0100
committerDimitri Sokolyuk <demon@dim13.org>2016-03-22 19:41:46 +0100
commit96350677c89d46dbaabf8d1813ca494b56efb02d (patch)
tree085c1322567aba637b76b77f87dfacbf9c739c89 /main.go
Inital import
Diffstat (limited to 'main.go')
-rw-r--r--main.go110
1 files changed, 110 insertions, 0 deletions
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()
+}