mirror of
https://github.com/boringproxy/boringproxy.git
synced 2025-02-25 18:55:29 -06:00
Merge remote-tracking branch 'upstream/master' into load-balancer
This commit is contained in:
commit
7410c8bd23
@ -17,7 +17,6 @@ RUN if [[ "ORIGIN" == 'remote' ]] ; then git clone --depth 1 --branch "${BRANCH}
|
||||
COPY go.* ./
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
RUN export VERSION='2'
|
||||
|
||||
RUN cd cmd/boringproxy && CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} \
|
||||
go build -ldflags "-X main.Version=${VERSION}" \
|
||||
@ -25,6 +24,7 @@ RUN cd cmd/boringproxy && CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} \
|
||||
|
||||
FROM scratch
|
||||
EXPOSE 80 443
|
||||
WORKDIR /storage
|
||||
|
||||
COPY --from=builder /build/cmd/boringproxy/boringproxy /
|
||||
|
||||
|
20
api.go
20
api.go
@ -379,10 +379,26 @@ func (a *Api) CreateTunnel(tokenData TokenData, params url.Values) (*Tunnel, err
|
||||
}
|
||||
|
||||
tlsTerm := params.Get("tls-termination")
|
||||
if tlsTerm != "server" && tlsTerm != "client" && tlsTerm != "passthrough" && tlsTerm != "client-tls" {
|
||||
if tlsTerm != "server" && tlsTerm != "client" && tlsTerm != "passthrough" && tlsTerm != "client-tls" && tlsTerm != "server-tls" {
|
||||
return nil, errors.New("Invalid tls-termination parameter")
|
||||
}
|
||||
|
||||
sshServerAddr := a.db.GetAdminDomain()
|
||||
sshServerAddrParam := params.Get("ssh-server-addr")
|
||||
if sshServerAddrParam != "" {
|
||||
sshServerAddr = sshServerAddrParam
|
||||
}
|
||||
|
||||
sshServerPort := a.config.SshServerPort
|
||||
sshServerPortParam := params.Get("ssh-server-port")
|
||||
if sshServerPortParam != "" {
|
||||
var err error
|
||||
sshServerPort, err = strconv.Atoi(sshServerPortParam)
|
||||
if err != nil {
|
||||
return nil, errors.New("Invalid ssh-server-port parameter")
|
||||
}
|
||||
}
|
||||
|
||||
request := Tunnel{
|
||||
Domain: domain,
|
||||
Owner: owner,
|
||||
@ -394,6 +410,8 @@ func (a *Api) CreateTunnel(tokenData TokenData, params url.Values) (*Tunnel, err
|
||||
AuthUsername: username,
|
||||
AuthPassword: password,
|
||||
TlsTermination: tlsTerm,
|
||||
ServerAddress: sshServerAddr,
|
||||
ServerPort: sshServerPort,
|
||||
Used: false,
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ func Listen() {
|
||||
flagSet := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
|
||||
newAdminDomain := flagSet.String("admin-domain", "", "Admin Domain")
|
||||
sshServerPort := flagSet.Int("ssh-server-port", 22, "SSH Server Port")
|
||||
dbDir := flagSet.String("db-dir", "", "Database file directory")
|
||||
certDir := flagSet.String("cert-dir", "", "TLS cert directory")
|
||||
printLogin := flagSet.Bool("print-login", false, "Prints admin login information")
|
||||
httpPort := flagSet.Int("http-port", 80, "HTTP (insecure) port")
|
||||
@ -53,7 +54,9 @@ func Listen() {
|
||||
allowHttp := flagSet.Bool("allow-http", false, "Allow unencrypted (HTTP) requests")
|
||||
publicIp := flagSet.String("public-ip", "", "Public IP")
|
||||
behindProxy := flagSet.Bool("behind-proxy", false, "Whether we're running behind another reverse proxy")
|
||||
acmeEmail := flagSet.String("acme-email", "", "Email for ACME (ie Let's Encrypt)")
|
||||
acmeUseStaging := flagSet.Bool("acme-use-staging", false, "Use ACME (ie Let's Encrypt) staging servers")
|
||||
acceptCATerms := flagSet.Bool("accept-ca-terms", false, "Automatically accept CA terms")
|
||||
err := flagSet.Parse(os.Args[2:])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s: parsing flags: %s\n", os.Args[0], err)
|
||||
@ -61,7 +64,7 @@ func Listen() {
|
||||
|
||||
log.Println("Starting up")
|
||||
|
||||
db, err := NewDatabase()
|
||||
db, err := NewDatabase(*dbDir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -101,6 +104,15 @@ func Listen() {
|
||||
//certmagic.DefaultACME.DisableHTTPChallenge = true
|
||||
//certmagic.DefaultACME.DisableTLSALPNChallenge = true
|
||||
|
||||
if *acmeEmail != "" {
|
||||
certmagic.DefaultACME.Email = *acmeEmail
|
||||
}
|
||||
|
||||
if *acceptCATerms {
|
||||
certmagic.DefaultACME.Agreed = true
|
||||
log.Print(fmt.Sprintf("Automatic agreement to CA terms with email (%s)", *acmeEmail))
|
||||
}
|
||||
|
||||
if *acmeUseStaging {
|
||||
certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA
|
||||
}
|
||||
@ -328,11 +340,11 @@ func Listen() {
|
||||
continue
|
||||
}
|
||||
|
||||
go p.handleConnection(conn)
|
||||
go p.handleConnection(conn, certConfig)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Server) handleConnection(clientConn net.Conn) {
|
||||
func (p *Server) handleConnection(clientConn net.Conn, certConfig *certmagic.Config) {
|
||||
|
||||
clientHello, clientReader, err := peekClientHello(clientConn)
|
||||
if err != nil {
|
||||
@ -348,21 +360,31 @@ func (p *Server) handleConnection(clientConn net.Conn) {
|
||||
log.Println("Retrying...")
|
||||
}
|
||||
|
||||
tunnel, exists := p.db.SelectLoadBalancedTunnel(clientHello.ServerName)
|
||||
if exists && (tunnel.TlsTermination == "client" || tunnel.TlsTermination == "passthrough") || tunnel.TlsTermination == "client-tls" {
|
||||
err = p.passthroughRequest(passConn, tunnel)
|
||||
tunnel, exists := p.db.SelectLoadBalancedTunnel(clientHello.ServerName)
|
||||
if exists && (tunnel.TlsTermination == "client" || tunnel.TlsTermination == "passthrough") || tunnel.TlsTermination == "client-tls" {
|
||||
err = p.passthroughRequest(passConn, tunnel)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Tunnel %s|%s connection failed\n", tunnel.Domain, tunnel.ClientName)
|
||||
retry++
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("Tunnel %s|%s connection failed\n", tunnel.Domain, tunnel.ClientName)
|
||||
retry++
|
||||
continue
|
||||
} else {
|
||||
p.httpListener.PassConn(passConn)
|
||||
break
|
||||
}
|
||||
} else if exists && tunnel.TlsTermination == "server-tls" {
|
||||
useTls := true
|
||||
err := ProxyTcp(passConn, "127.0.0.1", tunnel.TunnelPort, useTls, certConfig)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
log.Printf("Tunnel %s|%s connection failed\n", tunnel.Domain, tunnel.ClientName)
|
||||
retry++
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
p.httpListener.PassConn(passConn)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
107
client.go
107
client.go
@ -6,12 +6,10 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -321,18 +319,6 @@ func (c *Client) BoreTunnel(ctx context.Context, tunnel Tunnel) error {
|
||||
|
||||
} else {
|
||||
|
||||
if tunnel.TlsTermination == "client-tls" {
|
||||
tlsConfig := &tls.Config{
|
||||
GetCertificate: c.certConfig.GetCertificate,
|
||||
}
|
||||
|
||||
tlsConfig.NextProtos = append([]string{"http/1.1", "h2", "acme-tls/1"}, tlsConfig.NextProtos...)
|
||||
|
||||
tlsListener := tls.NewListener(listener, tlsConfig)
|
||||
|
||||
listener = tlsListener
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
@ -345,17 +331,27 @@ func (c *Client) BoreTunnel(ctx context.Context, tunnel Tunnel) error {
|
||||
break
|
||||
//continue
|
||||
}
|
||||
go c.handleConnection(conn, tunnel.ClientAddress, tunnel.ClientPort)
|
||||
|
||||
var useTls bool
|
||||
if tunnel.TlsTermination == "client-tls" {
|
||||
useTls = true
|
||||
} else {
|
||||
useTls = false
|
||||
}
|
||||
|
||||
go ProxyTcp(conn, tunnel.ClientAddress, tunnel.ClientPort, useTls, c.certConfig)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// TODO: There's still quite a bit of duplication with what the server does. Could we
|
||||
// encapsulate it into a type?
|
||||
err = c.certConfig.ManageSync(ctx, []string{tunnel.Domain})
|
||||
if err != nil {
|
||||
log.Println("CertMagic error at startup")
|
||||
log.Println(err)
|
||||
if tunnel.TlsTermination != "passthrough" {
|
||||
// TODO: There's still quite a bit of duplication with what the server does. Could we
|
||||
// encapsulate it into a type?
|
||||
err = c.certConfig.ManageSync(ctx, []string{tunnel.Domain})
|
||||
if err != nil {
|
||||
log.Println("CertMagic error at startup")
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
<-ctx.Done()
|
||||
@ -363,75 +359,6 @@ func (c *Client) BoreTunnel(ctx context.Context, tunnel Tunnel) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) handleConnection(conn net.Conn, upstreamAddr string, port int) {
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
useTls := false
|
||||
addr := upstreamAddr
|
||||
|
||||
if strings.HasPrefix(upstreamAddr, "https://") {
|
||||
addr = upstreamAddr[len("https://"):]
|
||||
useTls = true
|
||||
}
|
||||
|
||||
var upstreamConn net.Conn
|
||||
var err error
|
||||
|
||||
if useTls {
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
upstreamConn, err = tls.Dial("tcp", fmt.Sprintf("%s:%d", addr, port), tlsConfig)
|
||||
} else {
|
||||
upstreamConn, err = net.Dial("tcp", fmt.Sprintf("%s:%d", addr, port))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
|
||||
defer upstreamConn.Close()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
|
||||
// Copy request to upstream
|
||||
go func() {
|
||||
_, err := io.Copy(upstreamConn, conn)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
|
||||
if c, ok := upstreamConn.(*net.TCPConn); ok {
|
||||
c.CloseWrite()
|
||||
} else if c, ok := upstreamConn.(*tls.Conn); ok {
|
||||
c.CloseWrite()
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
// Copy response to downstream
|
||||
go func() {
|
||||
_, err := io.Copy(conn, upstreamConn)
|
||||
//conn.(*net.TCPConn).CloseWrite()
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
// TODO: I added this to fix a bug where the copy to
|
||||
// upstreamConn was never closing, even though the copy to
|
||||
// conn was. It seems related to persistent connections going
|
||||
// idle and upstream closing the connection. I'm a bit worried
|
||||
// this might not be thread safe.
|
||||
conn.Close()
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func printJson(data interface{}) {
|
||||
d, _ := json.MarshalIndent(data, "", " ")
|
||||
fmt.Println(string(d))
|
||||
|
@ -2,9 +2,13 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/boringproxy/boringproxy"
|
||||
)
|
||||
@ -15,6 +19,7 @@ Commands:
|
||||
version Prints version information.
|
||||
server Start a new server.
|
||||
client Connect to a server.
|
||||
tuntls Tunnel a raw TLS connection.
|
||||
|
||||
Use "%[1]s command -h" for a list of flags for the command.
|
||||
`
|
||||
@ -25,7 +30,6 @@ func fail(msg string) {
|
||||
fmt.Fprintln(os.Stderr, msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Fprintln(os.Stderr, os.Args[0]+": Need a command")
|
||||
@ -40,6 +44,44 @@ func main() {
|
||||
fmt.Println(Version)
|
||||
case "help", "-h", "--help", "-help":
|
||||
fmt.Printf(usage, os.Args[0])
|
||||
case "tuntls":
|
||||
// This command is a direct port of https://github.com/anderspitman/tuntls
|
||||
flagSet := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
|
||||
server := flagSet.String("server", "", "boringproxy server")
|
||||
port := flagSet.Int("port", 0, "Local port to bind to")
|
||||
err := flagSet.Parse(os.Args[2:])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s: parsing flags: %s\n", os.Args[0], err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if *server == "" {
|
||||
fmt.Fprintf(os.Stderr, "server argument is required\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if *port == 0 {
|
||||
// one-time tunnel over stdin/stdout
|
||||
doTlsTunnel(*server, os.Stdin, os.Stdout)
|
||||
} else {
|
||||
// listen on a port and create tunnels for each connection
|
||||
fmt.Fprintf(os.Stderr, "Listening on port %d\n", *port)
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
go doTlsTunnel(*server, conn, conn)
|
||||
}
|
||||
}
|
||||
case "server":
|
||||
boringproxy.Listen()
|
||||
case "client":
|
||||
@ -97,3 +139,32 @@ func main() {
|
||||
fail(os.Args[0] + ": Invalid command " + command)
|
||||
}
|
||||
}
|
||||
|
||||
func doTlsTunnel(server string, in io.Reader, out io.Writer) {
|
||||
fmt.Fprintf(os.Stderr, "tuntls connecting to server: %s\n", server)
|
||||
|
||||
conn, err := tls.Dial("tcp", fmt.Sprintf("%s:443", server), &tls.Config{
|
||||
//RootCAs: roots,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to connect: "+err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
|
||||
go func() {
|
||||
io.Copy(conn, in)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
io.Copy(out, conn)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
conn.Close()
|
||||
}
|
||||
|
12
database.go
12
database.go
@ -11,6 +11,8 @@ import (
|
||||
"github.com/takingnames/namedrop-go"
|
||||
)
|
||||
|
||||
var DBFolderPath string
|
||||
|
||||
type Database struct {
|
||||
AdminDomain string `json:"admin_domain"`
|
||||
Tokens map[string]TokenData `json:"tokens"`
|
||||
@ -62,11 +64,13 @@ type Tunnel struct {
|
||||
Used bool
|
||||
}
|
||||
|
||||
func NewDatabase() (*Database, error) {
|
||||
func NewDatabase(path string) (*Database, error) {
|
||||
|
||||
dbJson, err := ioutil.ReadFile("boringproxy_db.json")
|
||||
DBFolderPath = path
|
||||
|
||||
dbJson, err := ioutil.ReadFile(DBFolderPath + "boringproxy_db.json")
|
||||
if err != nil {
|
||||
log.Println("failed reading boringproxy_db.json")
|
||||
log.Printf("failed reading %sboringproxy_db.json\n", DBFolderPath)
|
||||
dbJson = []byte("{}")
|
||||
}
|
||||
|
||||
@ -359,5 +363,5 @@ func (d *Database) DeleteUser(username string) {
|
||||
}
|
||||
|
||||
func (d *Database) persist() {
|
||||
saveJson(d, "boringproxy_db.json")
|
||||
saveJson(d, DBFolderPath+"boringproxy_db.json")
|
||||
}
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
Edit docker-compose.yml and change the following under **commands** for service **boringproxy**
|
||||
- bp.example.com: your admin domain
|
||||
- your-email-address: the email address to register with Let's Encrypt
|
||||
|
||||
***Since the -accept-ca-terms flag is set in the compose file, this will automatically accept terms and conditions of Let's Encrypt.***
|
||||
|
||||
## Build image from source and run server in docker
|
||||
You can build the image from source. This requires that you clone the GitHub repo and start docker using the compose command below:
|
||||
|
@ -7,11 +7,13 @@ services:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- data:/opt/boringproxy/
|
||||
command: ["server", "-admin-domain", "bp.example.com", "-cert-dir", "/certmagic"]
|
||||
- storage:/storage/
|
||||
- ssh://.ssh
|
||||
- /etc/ssl/certs/:/etc/ssl/certs/:ro
|
||||
command: ["server", "-admin-domain", "bp.example.com", "-acme-email", "your-email-address", "-accept-ca-terms", "-cert-dir", "/storage/certmagic", "-print-login"]
|
||||
environment:
|
||||
USER: "root"
|
||||
|
||||
volumes:
|
||||
data:
|
||||
certmagic:
|
||||
storage:
|
||||
ssh:
|
@ -39,6 +39,7 @@
|
||||
<option value="client">Client HTTPS</option>
|
||||
<option value="server">Server HTTPS</option>
|
||||
<option value="client-tls">Client raw TLS</option>
|
||||
<option value="server-tls">Server raw TLS</option>
|
||||
<option value="passthrough">Passthrough</option>
|
||||
</select>
|
||||
</div>
|
||||
@ -58,6 +59,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='input'>
|
||||
<label for="ssh-server-addr">Override SSH Server Address:</label>
|
||||
<input type="text" id="ssh-server-addr" name="ssh-server-addr">
|
||||
</div>
|
||||
<div class='input'>
|
||||
<label for="ssh-server-port">Override SSH Server Port:</label>
|
||||
<input type="text" id="ssh-server-port" name="ssh-server-port">
|
||||
</div>
|
||||
|
||||
<button class='button' type="submit">Submit</button>
|
||||
|
||||
</form>
|
||||
|
108
tls_proxy.go
Normal file
108
tls_proxy.go
Normal file
@ -0,0 +1,108 @@
|
||||
package boringproxy
|
||||
|
||||
import (
|
||||
//"errors"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/caddyserver/certmagic"
|
||||
)
|
||||
|
||||
func ProxyTcp(conn net.Conn, addr string, port int, useTls bool, certConfig *certmagic.Config) error {
|
||||
|
||||
if useTls {
|
||||
tlsConfig := &tls.Config{
|
||||
GetCertificate: certConfig.GetCertificate,
|
||||
}
|
||||
|
||||
tlsConfig.NextProtos = append([]string{"http/1.1", "h2", "acme-tls/1"}, tlsConfig.NextProtos...)
|
||||
|
||||
tlsConn := tls.Server(conn, tlsConfig)
|
||||
|
||||
tlsConn.Handshake()
|
||||
if tlsConn.ConnectionState().NegotiatedProtocol == "acme-tls/1" {
|
||||
tlsConn.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
go handleConnection(tlsConn, addr, port)
|
||||
} else {
|
||||
go handleConnection(conn, addr, port)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleConnection(conn net.Conn, upstreamAddr string, port int) {
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
useTls := false
|
||||
addr := upstreamAddr
|
||||
|
||||
if strings.HasPrefix(upstreamAddr, "https://") {
|
||||
addr = upstreamAddr[len("https://"):]
|
||||
useTls = true
|
||||
}
|
||||
|
||||
var upstreamConn net.Conn
|
||||
var err error
|
||||
|
||||
if useTls {
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
upstreamConn, err = tls.Dial("tcp", fmt.Sprintf("%s:%d", addr, port), tlsConfig)
|
||||
} else {
|
||||
upstreamConn, err = net.Dial("tcp", fmt.Sprintf("%s:%d", addr, port))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
|
||||
defer upstreamConn.Close()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
|
||||
// Copy request to upstream
|
||||
go func() {
|
||||
_, err := io.Copy(upstreamConn, conn)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
|
||||
if c, ok := upstreamConn.(*net.TCPConn); ok {
|
||||
c.CloseWrite()
|
||||
} else if c, ok := upstreamConn.(*tls.Conn); ok {
|
||||
c.CloseWrite()
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
// Copy response to downstream
|
||||
go func() {
|
||||
_, err := io.Copy(conn, upstreamConn)
|
||||
//conn.(*net.TCPConn).CloseWrite()
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
// TODO: I added this to fix a bug where the copy to
|
||||
// upstreamConn was never closing, even though the copy to
|
||||
// conn was. It seems related to persistent connections going
|
||||
// idle and upstream closing the connection. I'm a bit worried
|
||||
// this might not be thread safe.
|
||||
conn.Close()
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
@ -36,7 +36,7 @@ func NewTunnelManager(config *Config, db *Database, certConfig *certmagic.Config
|
||||
|
||||
if config.autoCerts {
|
||||
for _, tun := range db.GetTunnels() {
|
||||
if tun.TlsTermination == "server" {
|
||||
if tun.TlsTermination == "server" || tun.TlsTermination == "server-tls" {
|
||||
err = certConfig.ManageSync(context.Background(), []string{tun.Domain})
|
||||
if err != nil {
|
||||
log.Println("CertMagic error at startup")
|
||||
@ -64,7 +64,7 @@ func (m *TunnelManager) RequestCreateTunnel(tunReq Tunnel) (Tunnel, error) {
|
||||
return Tunnel{}, errors.New("Owner required")
|
||||
}
|
||||
|
||||
if tunReq.TlsTermination == "server" {
|
||||
if tunReq.TlsTermination == "server" || tunReq.TlsTermination == "server-tls" {
|
||||
if m.config.autoCerts {
|
||||
err := m.certConfig.ManageSync(context.Background(), []string{tunReq.Domain})
|
||||
if err != nil {
|
||||
@ -99,8 +99,6 @@ func (m *TunnelManager) RequestCreateTunnel(tunReq Tunnel) (Tunnel, error) {
|
||||
return Tunnel{}, err
|
||||
}
|
||||
|
||||
tunReq.ServerAddress = m.db.GetAdminDomain()
|
||||
tunReq.ServerPort = m.config.SshServerPort
|
||||
tunReq.ServerPublicKey = ""
|
||||
tunReq.Username = m.user.Username
|
||||
tunReq.TunnelPrivateKey = privKey
|
||||
|
Loading…
Reference in New Issue
Block a user