diff --git a/Dockerfile b/Dockerfile index 7bcfe68..9522d51 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,13 @@ -FROM golang:1.15-alpine3.12 as builder +FROM golang:1.17-alpine3.15 as builder WORKDIR /build RUN apk add git -RUN go get github.com/GeertJohan/go.rice/rice COPY go.* ./ RUN go mod download COPY . . -RUN rice embed-go RUN cd cmd/boringproxy && CGO_ENABLED=0 go build -o boringproxy FROM scratch diff --git a/README.md b/README.md index f6a4917..ead9829 100644 --- a/README.md +++ b/README.md @@ -40,14 +40,6 @@ source $HOME/.bashrc go build ``` -To embed the web UI into the executable: - -```bash -go get github.com/GeertJohan/go.rice/rice -rice embed-go -go build -``` - # Running ## Server diff --git a/boringproxy.go b/boringproxy.go index ab4955c..0ac91cf 100644 --- a/boringproxy.go +++ b/boringproxy.go @@ -3,6 +3,8 @@ package boringproxy import ( "bufio" "crypto/tls" + "encoding/json" + "errors" "flag" "fmt" "io" @@ -18,8 +20,8 @@ import ( ) type Config struct { - WebUiDomain string `json:"webui_domain"` SshServerPort int `json:"ssh_server_port"` + PublicIp string `json:"public_ip"` } type SmtpConfig struct { @@ -36,9 +38,74 @@ type Server struct { httpListener *PassthroughListener } +type IpResponse struct { + Ip string `json:"ip"` +} + +func checkPublicAddress(host string, port int) error { + + ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + return err + } + defer ln.Close() + + code, err := genRandomCode(32) + if err != nil { + return err + } + + go func() { + for { + conn, err := ln.Accept() + if err != nil { + break + } + conn.Write([]byte(code)) + conn.Close() + } + }() + + conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", host, port)) + if err != nil { + return nil + } + defer conn.Close() + + data, err := io.ReadAll(conn) + if err != nil { + return nil + } + + retCode := string(data) + + if retCode != code { + return errors.New("Mismatched codes") + } + + return nil +} + +func getPublicIp() (string, error) { + resp, err := http.Get("https://api.ipify.org?format=json") + if err != nil { + return "", err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + + var ipRes *IpResponse + err = json.Unmarshal([]byte(body), &ipRes) + if err != nil { + return "", err + } + + return ipRes.Ip, nil +} + func Listen() { flagSet := flag.NewFlagSet(os.Args[0], flag.ExitOnError) - adminDomain := flagSet.String("admin-domain", "", "Admin Domain") + newAdminDomain := flagSet.String("admin-domain", "", "Admin Domain") sshServerPort := flagSet.Int("ssh-server-port", 22, "SSH Server Port") certDir := flagSet.String("cert-dir", "", "TLS cert directory") err := flagSet.Parse(os.Args[2:]) @@ -48,50 +115,70 @@ func Listen() { log.Println("Starting up") - webUiDomain := *adminDomain - - if *adminDomain == "" { - reader := bufio.NewReader(os.Stdin) - fmt.Print("Enter Admin Domain: ") - text, _ := reader.ReadString('\n') - webUiDomain = strings.TrimSpace(text) - } - - config := &Config{ - WebUiDomain: webUiDomain, - SshServerPort: *sshServerPort, - } - - certmagic.DefaultACME.DisableHTTPChallenge = true - if *certDir != "" { - certmagic.Default.Storage = &certmagic.FileStorage{*certDir} - } - //certmagic.DefaultACME.DisableTLSALPNChallenge = true - //certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA - certConfig := certmagic.NewDefault() - - err = certConfig.ManageSync([]string{config.WebUiDomain}) + ip, err := getPublicIp() if err != nil { log.Fatal(err) } - log.Print("Successfully acquired admin certificate") + err = checkPublicAddress(ip, 80) + if err != nil { + log.Fatal(err) + } + + err = checkPublicAddress(ip, 443) + if err != nil { + log.Fatal(err) + } db, err := NewDatabase() if err != nil { log.Fatal(err) } + if *certDir != "" { + certmagic.Default.Storage = &certmagic.FileStorage{*certDir} + } + //certmagic.DefaultACME.DisableHTTPChallenge = true + //certmagic.DefaultACME.DisableTLSALPNChallenge = true + //certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA + certConfig := certmagic.NewDefault() + + if *newAdminDomain != "" { + db.SetAdminDomain(*newAdminDomain) + } + + adminDomain := db.GetAdminDomain() + + if adminDomain == "" { + + err = setAdminDomain(ip, certConfig, db) + if err != nil { + log.Fatal(err) + } + } else { + err = certConfig.ManageSync([]string{adminDomain}) + if err != nil { + log.Fatal(err) + } + log.Print(fmt.Sprintf("Successfully acquired certificate for admin domain (%s)", adminDomain)) + } + users := db.GetUsers() if len(users) == 0 { db.AddUser("admin", true) - token, err := db.AddToken("admin") + //token, err := db.AddToken("admin") + _, err := db.AddToken("admin") if err != nil { log.Fatal("Failed to initialize admin user") } - log.Println("Admin token: " + token) - log.Println(fmt.Sprintf("Admin login link: https://%s/login?access_token=%s", webUiDomain, token)) + //log.Println("Admin token: " + token) + //log.Println(fmt.Sprintf("Admin login link: https://%s/login?access_token=%s", adminDomain, token)) + } + + config := &Config{ + SshServerPort: *sshServerPort, + PublicIp: ip, } tunMan := NewTunnelManager(config, db, certConfig) @@ -123,7 +210,60 @@ func Listen() { timestamp := time.Now().Format(time.RFC3339) srcIp := strings.Split(r.RemoteAddr, ":")[0] fmt.Println(fmt.Sprintf("%s %s %s %s %s", timestamp, srcIp, r.Method, r.Host, r.URL.Path)) - if r.Host == config.WebUiDomain { + if r.URL.Path == "/dnsapi/requests" { + r.ParseForm() + + requestId := r.Form.Get("request-id") + + dnsRequest, err := db.GetDNSRequest(requestId) + if err != nil { + w.WriteHeader(500) + io.WriteString(w, err.Error()) + return + } + + jsonBytes, err := json.Marshal(dnsRequest) + if err != nil { + w.WriteHeader(500) + io.WriteString(w, err.Error()) + return + } + + w.Write(jsonBytes) + + } else if r.URL.Path == "/dnsapi/callback" { + r.ParseForm() + + requestId := r.Form.Get("request-id") + + // Ensure the request exists + dnsRequest, err := db.GetDNSRequest(requestId) + if err != nil { + w.WriteHeader(500) + io.WriteString(w, err.Error()) + return + } + + db.DeleteDNSRequest(requestId) + + domain := r.Form.Get("domain") + + if dnsRequest.IsAdminDomain { + db.SetAdminDomain(domain) + + // TODO: Might want to get all certs here, not just the admin domain + err := certConfig.ManageSync([]string{domain}) + if err != nil { + log.Fatal(err) + } + + http.Redirect(w, r, fmt.Sprintf("https://%s", domain), 303) + } else { + adminDomain := db.GetAdminDomain() + http.Redirect(w, r, fmt.Sprintf("https://%s/edit-tunnel?domain=%s", adminDomain, domain), 303) + } + + } else if r.Host == db.GetAdminDomain() { if strings.HasPrefix(r.URL.Path, "/api/") { http.StripPrefix("/api", api).ServeHTTP(w, r) } else { @@ -143,9 +283,8 @@ func Listen() { } }) - // taken from: https://stackoverflow.com/a/37537134/943814 go func() { - if err := http.ListenAndServe(":80", http.HandlerFunc(redirectTLS)); err != nil { + if err := http.ListenAndServe(":80", nil); err != nil { log.Fatalf("ListenAndServe error: %v", err) } }() @@ -157,6 +296,8 @@ func Listen() { log.Fatal(err) } + log.Println("Ready") + for { conn, err := listener.Accept() if err != nil { @@ -215,7 +356,71 @@ func (p *Server) passthroughRequest(conn net.Conn, tunnel Tunnel) { wg.Wait() } -func redirectTLS(w http.ResponseWriter, r *http.Request) { - url := fmt.Sprintf("https://%s:443%s", r.Host, r.RequestURI) - http.Redirect(w, r, url, http.StatusMovedPermanently) +func setAdminDomain(ip string, certConfig *certmagic.Config, db *Database) error { + action := prompt("\nNo admin domain set. Enter '1' to input manually, or '2' to configure through TakingNames.io\n") + switch action { + case "1": + adminDomain := prompt("\nEnter admin domain:\n") + + err := certConfig.ManageSync([]string{adminDomain}) + if err != nil { + log.Fatal(err) + } + + db.SetAdminDomain(adminDomain) + case "2": + + log.Println("Get bootstrap domain") + + resp, err := http.Get("https://takingnames.io/dnsapi/bootstrap-domain") + if err != nil { + return err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + + bootstrapDomain := string(body) + + if resp.StatusCode != 200 { + fmt.Println(bootstrapDomain) + return errors.New("bootstrap domain request failed") + } + + log.Println("Get cert") + + err = certConfig.ManageSync([]string{bootstrapDomain}) + if err != nil { + log.Fatal(err) + } + + requestId, _ := genRandomCode(32) + + req := DNSRequest{ + IsAdminDomain: true, + Records: []*DNSRecord{ + &DNSRecord{ + Type: "A", + Value: ip, + TTL: 300, + }, + }, + } + + db.SetDNSRequest(requestId, req) + + tnLink := fmt.Sprintf("https://takingnames.io/dnsapi?requester=%s&request-id=%s", bootstrapDomain, requestId) + fmt.Println("Use the link below to select an admin domain:\n\n" + tnLink + "\n") + + default: + log.Fatal("Invalid option") + } + + return nil +} + +func prompt(promptText string) string { + reader := bufio.NewReader(os.Stdin) + fmt.Print(promptText) + text, _ := reader.ReadString('\n') + return strings.TrimSpace(text) } diff --git a/database.go b/database.go index 05b1d0d..70513cc 100644 --- a/database.go +++ b/database.go @@ -9,11 +9,13 @@ import ( ) type Database struct { - Tokens map[string]TokenData `json:"tokens"` - Tunnels map[string]Tunnel `json:"tunnels"` - Users map[string]User `json:"users"` - SshKeys map[string]SshKey `json:"ssh_keys"` - mutex *sync.Mutex + AdminDomain string `json:"admin_domain"` + Tokens map[string]TokenData `json:"tokens"` + Tunnels map[string]Tunnel `json:"tunnels"` + Users map[string]User `json:"users"` + SshKeys map[string]SshKey `json:"ssh_keys"` + dnsRequests map[string]DNSRequest `json:"dns_requests"` + mutex *sync.Mutex } type TokenData struct { @@ -33,6 +35,17 @@ type SshKey struct { type DbClient struct { } +type DNSRequest struct { + IsAdminDomain bool `json:"is_admin_domain"` + Records []*DNSRecord `json:"records"` +} + +type DNSRecord struct { + Type string `json:"type"` + Value string `json:"value"` + TTL int `json:"ttl"` +} + type Tunnel struct { Owner string `json:"owner"` Domain string `json:"domain"` @@ -85,6 +98,10 @@ func NewDatabase() (*Database, error) { db.SshKeys = make(map[string]SshKey) } + if db.dnsRequests == nil { + db.dnsRequests = make(map[string]DNSRequest) + } + db.mutex = &sync.Mutex{} db.mutex.Lock() @@ -94,6 +111,48 @@ func NewDatabase() (*Database, error) { return db, nil } +func (d *Database) SetAdminDomain(adminDomain string) { + d.mutex.Lock() + defer d.mutex.Unlock() + + d.AdminDomain = adminDomain + + d.persist() +} +func (d *Database) GetAdminDomain() string { + d.mutex.Lock() + defer d.mutex.Unlock() + + return d.AdminDomain +} + +func (d *Database) SetDNSRequest(requestId string, request DNSRequest) { + d.mutex.Lock() + defer d.mutex.Unlock() + + d.dnsRequests[requestId] = request + + // Not currently persisting because dnsRequests is only stored in + // memory. May change in the future. + //d.persist() +} +func (d *Database) GetDNSRequest(requestId string) (DNSRequest, error) { + d.mutex.Lock() + defer d.mutex.Unlock() + + if req, ok := d.dnsRequests[requestId]; ok { + return req, nil + } + + return DNSRequest{}, errors.New("No such DNS Request") +} +func (d *Database) DeleteDNSRequest(requestId string) { + d.mutex.Lock() + defer d.mutex.Unlock() + + delete(d.dnsRequests, requestId) +} + func (d *Database) AddToken(owner string) (string, error) { d.mutex.Lock() defer d.mutex.Unlock() diff --git a/go.mod b/go.mod index f693430..7b5f32a 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,22 @@ module github.com/boringproxy/boringproxy -go 1.15 +go 1.17 require ( - github.com/GeertJohan/go.rice v1.0.0 github.com/caddyserver/certmagic v0.12.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de ) + +require ( + github.com/klauspost/cpuid v1.2.5 // indirect + github.com/libdns/libdns v0.1.0 // indirect + github.com/mholt/acmez v0.1.1 // indirect + github.com/miekg/dns v1.1.30 // indirect + go.uber.org/atomic v1.6.0 // indirect + go.uber.org/multierr v1.5.0 // indirect + go.uber.org/zap v1.15.0 // indirect + golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect + golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect + golang.org/x/text v0.3.0 // indirect +) diff --git a/go.sum b/go.sum index 820b7be..2b41cd4 100644 --- a/go.sum +++ b/go.sum @@ -1,28 +1,16 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg= -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ= -github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= -github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/caddyserver/certmagic v0.12.0 h1:1f7kxykaJkOVVpXJ8ZrC6RAO5F6+kKm9U7dBFbLNeug= github.com/caddyserver/certmagic v0.12.0/go.mod h1:tr26xh+9fY5dN0J6IPAlMj07qpog22PJKa7Nw7j835U= -github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY= -github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/cpuid v1.2.5 h1:VBd9MyVIiJHzzgnrLQG5Bcv75H4YaWrlKqWHjurxCGo= github.com/klauspost/cpuid v1.2.5/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libdns/libdns v0.1.0 h1:0ctCOrVJsVzj53mop1angHp/pE3hmAhP7KiHvR0HD04= github.com/libdns/libdns v0.1.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= @@ -30,8 +18,6 @@ github.com/mholt/acmez v0.1.1 h1:KQODCqk+hBn3O7qfCRPj6L96uG65T5BSS95FKNEqtdA= github.com/mholt/acmez v0.1.1/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM= github.com/miekg/dns v1.1.30 h1:Qww6FseFn8PRfw07jueqIXqodm0JKiiKuK0DeXSqfyo= github.com/miekg/dns v1.1.30/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg= -github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -43,10 +29,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= @@ -89,7 +71,6 @@ golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapK golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= diff --git a/http_proxy.go b/http_proxy.go index fa87730..0b4566e 100644 --- a/http_proxy.go +++ b/http_proxy.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "net/http" + "strings" "time" ) @@ -49,6 +50,21 @@ func proxyRequest(w http.ResponseWriter, r *http.Request, tunnel Tunnel, httpCli upstreamReq.Header = downstreamReqHeaders upstreamReq.Header["X-Forwarded-Host"] = []string{r.Host} + + // TODO: Handle IPv6 addresses + addrParts := strings.Split(r.RemoteAddr, ":") + remoteIp := addrParts[0] + + xForwardedFor := downstreamReqHeaders.Get("X-Forwarded-For") + if xForwardedFor == "" { + xForwardedFor = remoteIp + } else { + xForwardedFor = xForwardedFor + ", " + remoteIp + } + upstreamReq.Header.Set("X-Forwarded-For", xForwardedFor) + + upstreamReq.Header.Set("Forwarded", fmt.Sprintf("for=%s", remoteIp)) + upstreamReq.Host = fmt.Sprintf("%s:%d", tunnel.ClientAddress, tunnel.ClientPort) upstreamRes, err := httpClient.Do(upstreamReq) diff --git a/release/Dockerfile b/release/Dockerfile index 6504fa9..1c3a649 100644 --- a/release/Dockerfile +++ b/release/Dockerfile @@ -11,4 +11,3 @@ WORKDIR boringproxy RUN ./scripts/install_go.sh ENV PATH="${PATH}:/usr/local/go/bin" ENV PATH="${PATH}:/root/go/bin" -RUN go get github.com/GeertJohan/go.rice/rice diff --git a/scripts/build_release.sh b/scripts/build_release.sh index f0779f0..a55a9b1 100755 --- a/scripts/build_release.sh +++ b/scripts/build_release.sh @@ -4,8 +4,6 @@ version=$(git describe --tags) ./scripts/generate_logo.sh -rice embed-go - cd ./cmd/boringproxy ../../scripts/build_x86_64.sh linux diff --git a/scripts/generate_logo.sh b/scripts/generate_logo.sh index 89b6c95..8691636 100755 --- a/scripts/generate_logo.sh +++ b/scripts/generate_logo.sh @@ -1,2 +1,6 @@ #!/bin/bash -inkscape -z -w 192 -h 192 logo.svg -e webui/logo.png + +# old inkscape +#inkscape -z -w 192 -h 192 logo.svg -e webui/logo.png + +inkscape -w 192 -h 192 logo.svg -o logo.png diff --git a/sni.go b/sni.go index 2cedc2f..fcf8334 100644 --- a/sni.go +++ b/sni.go @@ -74,8 +74,11 @@ func (f *PassthroughListener) PassConn(conn net.Conn) { } // This type creates a new net.Conn that's the same as an old one, except a new -// reader is provided. So it proxies every method except Read. I'm sure there's -// a cleaner way to do this... +// reader is provided. So it proxies every method except Read. This is +// necessary because by calling peekClientHello, part of the reader is read, +// so we need to create a new reader with the already read data inserted back +// in the front. +// I'm sure there's a cleaner way to do this... type ProxyConn struct { conn net.Conn reader io.Reader diff --git a/webui/alert.tmpl b/templates/alert.tmpl similarity index 92% rename from webui/alert.tmpl rename to templates/alert.tmpl index f025562..5eabaa7 100644 --- a/webui/alert.tmpl +++ b/templates/alert.tmpl @@ -1,9 +1,10 @@ - {{.Head}} - - diff --git a/templates/header.tmpl b/templates/header.tmpl new file mode 100644 index 0000000..67921d3 --- /dev/null +++ b/templates/header.tmpl @@ -0,0 +1,36 @@ + + + + + + + boringproxy + + + + + + + + + +
+ + + +
+ + +
+ diff --git a/webui/loading.tmpl b/templates/loading.tmpl similarity index 91% rename from webui/loading.tmpl rename to templates/loading.tmpl index 391caa8..af10115 100644 --- a/webui/loading.tmpl +++ b/templates/loading.tmpl @@ -2,9 +2,9 @@ - {{.Head}} - - - -
- - - -
- -
-
- {{range $domain, $tunnel:= .Tunnels}} - -
-
- {{$domain}}:{{$tunnel.TunnelPort}} -> {{$tunnel.ClientName}} -> {{$tunnel.ClientAddress}}:{{$tunnel.ClientPort}} -
- - Download Private Key - - -
- - -
- - -
-

- Are you sure you want to delete {{$domain}}? -

-
- -
-
-
- {{end}} -
- -
-

Add Tunnel

-
-
- - - -
-
- - -
- - - -
- - -
-
- - -
-
- - -
-
- - -
-
- - - -
- - - - -
-
-
- - -
- -
-
-
-
- -
- -
-
- {{range $token, $tokenData := .Tokens}} - -
- {{$token}} ({{$tokenData.Owner}}) - Login link - - - - -
- {{end}} -
- -
-
- - - -
-
-
-
- - - - {{if .IsAdmin}} -
- -
-
- {{range $username, $user := .Users}} -
- {{$username}} - - - -
- {{end}} -
-
-
- - - - - -
-
-
-
- {{end}} -
- -