iconia/agent/agent.go

78 lines
1.6 KiB
Go

package agent
import (
"context"
"crypto/tls"
"fmt"
"log"
"net/http"
"net/url"
"os"
"time"
"github.com/hashicorp/yamux"
)
func Handle(ctx context.Context, agentURL, agentToken string, h http.Handler) error {
u, err := url.Parse(agentURL)
if err != nil {
return fmt.Errorf("error parsing URL: %w", err)
}
if u.Scheme != "iconia" {
return fmt.Errorf("wanted scheme %s, got: %s", "iconia", u.Scheme)
}
if u.Path == "" {
return fmt.Errorf("put the domain you want to forward in the path")
}
tc := &tls.Config{
ServerName: u.Path[1:],
InsecureSkipVerify: true, // TODO(Cadey): FIX THIS OMG
NextProtos: []string{agentToken},
}
log.Println("dialing", u.Host)
conn, err := tls.Dial("tcp", u.Host, tc)
if err != nil {
return fmt.Errorf("error dialing remote host %s: %w", u.Host, err)
}
defer conn.Close()
log.Println("connection established")
sesh, err := yamux.Client(conn, &yamux.Config{
AcceptBacklog: 1,
EnableKeepAlive: true,
KeepAliveInterval: time.Minute,
ConnectionWriteTimeout: 100 * time.Millisecond,
MaxStreamWindowSize: 262144 * 16,
Logger: log.New(os.Stderr, u.Path+"(yamux): ", log.LstdFlags),
})
if err != nil {
return fmt.Errorf("error connecting to iconia: %w", err)
}
defer sesh.Close()
s := &http.Server{
Handler: h,
}
log.Println("listening for traffic from iconia")
err = s.Serve(sesh)
if err != nil {
return fmt.Errorf("error serving http: %w", err)
}
go func() {
<-ctx.Done()
s.Shutdown(context.Background())
sesh.GoAway()
}()
return nil
}