78 lines
1.6 KiB
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
|
||
|
}
|