Skip to content
File

Blob: tun/client/keyless_proxy.go

go89 lines
1package client
2 
3import (
4 "context"
5 "crypto/tls"
6 "net"
7 
8 "go.miragespace.co/specter/gateway"
9 "go.miragespace.co/specter/spec/cipher"
10 "go.miragespace.co/specter/spec/protocol"
11 "go.miragespace.co/specter/spec/tun"
12 "go.miragespace.co/specter/util/bufconn"
13 
14 "go.uber.org/zap"
15)
16 
17type emulatedTunnelServer struct {
18 cli *Client
19}
20 
21func (e *emulatedTunnelServer) DialClient(ctx context.Context, link *protocol.Link) (net.Conn, error) {
22 // the pipe net.Conn must be buffered to preserved real-world network behavior
23 c1, c2 := bufconn.BufferedPipe(8192)
24 err := e.cli.handleIncomingDelegation(ctx, link, c1)
25 if err != nil {
26 return nil, err
27 }
28 return c2, nil
29}
30 
31func (e *emulatedTunnelServer) DialInternal(context.Context, *protocol.Node) (net.Conn, error) {
32 return nil, tun.ErrLookupFailed
33}
34 
35func (e *emulatedTunnelServer) Identity() *protocol.Node {
36 return &protocol.Node{
37 Id: e.cli.ServerTransport.Identity().GetId(),
38 Address: e.cli.KeylessProxy.HTTPSListner.Addr().String(),
39 }
40}
41 
42var _ tun.Server = (*emulatedTunnelServer)(nil)
43 
44func (c *Client) startKeylessProxy() {
45 if c.KeylessProxy.ALPNMux == nil || c.KeylessProxy.HTTPSListner == nil {
46 return
47 }
48 
49 address := c.KeylessProxy.HTTPSListner.Addr()
50 tcpAddress, ok := address.(*net.TCPAddr)
51 if !ok {
52 return
53 }
54 
55 gwTLSConf := cipher.GetGatewayTLSConfig(c.getCertificate, []string{
56 tun.ALPN(protocol.Link_HTTP2),
57 tun.ALPN(protocol.Link_HTTP),
58 tun.ALPN(protocol.Link_TCP),
59 tun.ALPN(protocol.Link_UNKNOWN),
60 })
61 
62 gwH2Listener := tls.NewListener(c.KeylessProxy.HTTPSListner, gwTLSConf)
63 defer gwH2Listener.Close()
64 
65 // handles h3, h3-29, and specter-tcp/1
66 gwH3Listener := c.KeylessProxy.ALPNMux.With(gwTLSConf, append([]string{tun.ALPN(protocol.Link_TCP)}, cipher.H3Protos...)...)
67 defer gwH3Listener.Close()
68 
69 gwCfg := gateway.GatewayConfig{
70 TunnelServer: &emulatedTunnelServer{c},
71 Logger: c.Logger.With(zap.String("component", "keyless_proxy")),
72 HTTPListener: c.KeylessProxy.HTTPListner,
73 H2Listener: gwH2Listener,
74 H3Listener: gwH3Listener,
75 GatewayPort: tcpAddress.Port,
76 Options: gateway.Options{
77 TransportBufferSize: 1 << 16,
78 ProxyBufferSize: 1 << 16,
79 },
80 }
81 
82 gw := gateway.New(gwCfg)
83 defer gw.Close()
84 
85 gw.MustStart(c.parentCtx)
86 
87 <-c.closeCh
88}