@@ -26,24 +26,24 @@ var (
2626 backoffFactor = 2.
2727 backoffMin = 5 * time .Second
2828 backoffMax = time .Minute
29- streamTimeout = time .Minute
29+ streamTimeout = 5 * time .Minute
3030)
3131
3232type Tunnel struct {
33- promAddr string
34- address string
35- projectToken string
36- serverName string
37- cancelFn context.CancelFunc
38- gwConn net.Conn
33+ address string
34+ serverName string
35+ token string
36+ config [] byte
37+ cancelFn context.CancelFunc
38+ gwConn net.Conn
3939}
4040
41- func NewTunnel (address , serverName , promAddr , projectToken string ) * Tunnel {
41+ func NewTunnel (address , serverName string , token string , config [] byte ) * Tunnel {
4242 t := & Tunnel {
43- address : address ,
44- promAddr : promAddr ,
45- projectToken : projectToken ,
46- serverName : serverName ,
43+ address : address ,
44+ serverName : serverName ,
45+ token : token ,
46+ config : config ,
4747 }
4848 var ctx context.Context
4949 ctx , t .cancelFn = context .WithCancel (context .Background ())
@@ -59,15 +59,15 @@ func (t *Tunnel) keepConnected(ctx context.Context) {
5959 case <- ctx .Done ():
6060 return
6161 default :
62- t .gwConn , err = connect (t .address , t .serverName , t .projectToken )
62+ t .gwConn , err = connect (t .address , t .serverName , t .token , t . config )
6363 if err != nil {
6464 d := b .Duration ()
6565 klog .Errorf ("%s, reconnecting to %s in %.0fs" , err , t .address , d .Seconds ())
6666 time .Sleep (d )
6767 continue
6868 }
6969 b .Reset ()
70- proxy (ctx , t .gwConn , t . promAddr )
70+ proxy (ctx , t .gwConn )
7171 _ = t .gwConn .Close ()
7272 }
7373 }
@@ -81,30 +81,40 @@ func (t *Tunnel) Close() {
8181}
8282
8383func main () {
84- klog .Infof ("version: %s" , version )
8584 resolverUrl := os .Getenv ("RESOLVER_URL" )
8685 if resolverUrl == "" {
8786 resolverUrl = "https://gw.coroot.com/promtun/resolve"
8887 }
89- promAddr := mustEnv ("PROMETHEUS_ADDRESS" )
90- projectToken := mustEnv ("PROJECT_TOKEN" )
88+ token := mustEnv ("PROJECT_TOKEN" )
89+ if len (token ) != 36 {
90+ klog .Exitln ("invalid project token" )
91+ }
92+ configPath := mustEnv ("CONFIG_PATH" )
9193
92- u , err := url . Parse ( resolverUrl )
94+ data , err := os . ReadFile ( configPath )
9395 if err != nil {
94- klog .Exitf ( "invalid RESOLVER_URL %s: %s" , resolverUrl , err )
96+ klog .Exitln ( "failed to read config:" , err )
9597 }
96- serverName := u . Hostname ( )
98+ config := [] byte ( os . ExpandEnv ( string ( data )) )
9799
98- if err := pingProm (promAddr ); err != nil {
99- klog .Exitf ("failed to ping prometheus: %s" , err )
100+ klog .Infof ("version: %s" , version )
101+
102+ loop (token , resolverUrl , config )
103+ }
104+
105+ func loop (token , resolverUrl string , config []byte ) {
106+ u , err := url .Parse (resolverUrl )
107+ if err != nil {
108+ klog .Exitf ("invalid resolver URL %s: %s" , resolverUrl , err )
100109 }
110+ tlsServerName := u .Hostname ()
101111
102112 tunnels := map [string ]* Tunnel {}
103113
104114 b := backoff.Backoff {Factor : backoffFactor , Min : backoffMin , Max : backoffMax }
105115 for {
106116 klog .Infof ("updating gateways endpoints from %s" , resolverUrl )
107- endpoints , err := getEndpoints (resolverUrl , projectToken )
117+ endpoints , err := getEndpoints (resolverUrl , token )
108118 if err != nil {
109119 d := b .Duration ()
110120 klog .Errorf ("failed to get gateway endpoints: %s, retry in %.0fs" , err , d .Seconds ())
@@ -117,13 +127,13 @@ func main() {
117127 for _ , e := range endpoints {
118128 fresh [e ] = true
119129 if _ , ok := tunnels [e ]; ! ok {
120- klog .Infof ("starting tunnel to %s" , e )
121- tunnels [e ] = NewTunnel (e , serverName , promAddr , projectToken )
130+ klog .Infof ("starting a tunnel to %s" , e )
131+ tunnels [e ] = NewTunnel (e , tlsServerName , token , config )
122132 }
123133 }
124134 for e , t := range tunnels {
125135 if ! fresh [e ] {
126- klog .Infof ("closing tunnel to %s" , e )
136+ klog .Infof ("closing tunnel with %s" , e )
127137 t .Close ()
128138 delete (tunnels , e )
129139 }
@@ -132,9 +142,9 @@ func main() {
132142 }
133143}
134144
135- func getEndpoints (resolverUrl , projectToken string ) ([]string , error ) {
145+ func getEndpoints (resolverUrl , token string ) ([]string , error ) {
136146 req , _ := http .NewRequest ("GET" , resolverUrl , nil )
137- req .Header .Set ("X-Token" , projectToken )
147+ req .Header .Set ("X-Token" , token )
138148 resp , err := http .DefaultClient .Do (req )
139149 if err != nil {
140150 return nil , err
@@ -150,29 +160,44 @@ func getEndpoints(resolverUrl, projectToken string) ([]string, error) {
150160 return strings .Split (strings .TrimSpace (string (payload )), ";" ), nil
151161}
152162
153- func connect (gwAddr , serverName , projectToken string ) (net.Conn , error ) {
163+ type Header struct {
164+ Token [36 ]byte
165+ Version [16 ]byte
166+ ConfigSize uint32
167+ }
168+
169+ func connect (gwAddr , serverName , token string , config []byte ) (net.Conn , error ) {
170+ h := Header {}
171+ copy (h .Token [:], token )
172+ copy (h .Version [:], version )
173+ h .ConfigSize = uint32 (len (config ))
174+
154175 klog .Infof ("connecting to %s (%s)" , gwAddr , serverName )
155176 deadline := time .Now ().Add (timeout )
156177 dialer := & net.Dialer {Deadline : deadline }
157- tlsCfg := & tls.Config {InsecureSkipVerify : tlsSkipVerify , ServerName : serverName }
178+ tlsCfg := & tls.Config {ServerName : serverName , InsecureSkipVerify : tlsSkipVerify }
158179 gwConn , err := tls .DialWithDialer (dialer , "tcp" , gwAddr , tlsCfg )
159180 if err != nil {
160- return nil , fmt .Errorf ("failed to establish connection to %s: %s" , gwAddr , err )
181+ return nil , fmt .Errorf ("failed to establish a connection to %s: %s" , gwAddr , err )
161182 }
162183 klog .Infof ("connected to gateway %s" , gwAddr )
163184
164185 _ = gwConn .SetDeadline (deadline )
165- if _ , err := gwConn .Write ([]byte (projectToken )); err != nil {
186+ if err = binary .Write (gwConn , binary .LittleEndian , h ); err != nil {
187+ _ = gwConn .Close ()
188+ return nil , fmt .Errorf ("failed to send config to %s: %s" , gwAddr , err )
189+ }
190+ if _ , err = gwConn .Write (config ); err != nil {
166191 _ = gwConn .Close ()
167- return nil , fmt .Errorf ("failed to send project token to %s: %s" , gwAddr , err )
192+ return nil , fmt .Errorf ("failed to send config to %s: %s" , gwAddr , err )
168193 }
169194 var resp uint16
170195 if err := binary .Read (gwConn , binary .LittleEndian , & resp ); err != nil {
171196 _ = gwConn .Close ()
172- return nil , fmt .Errorf ("failed to read gateway response from %s: %s" , gwAddr , err )
197+ return nil , fmt .Errorf ("failed to read the response from %s: %s" , gwAddr , err )
173198 }
174199 _ = gwConn .SetDeadline (time.Time {})
175- klog .Infof (" got from gateway %s: %d" , gwAddr , resp )
200+ klog .Infof (` got "%d" from the gateway %s` , resp , gwAddr )
176201
177202 if resp != 200 {
178203 _ = gwConn .Close ()
@@ -182,7 +207,7 @@ func connect(gwAddr, serverName, projectToken string) (net.Conn, error) {
182207 return gwConn , nil
183208}
184209
185- func proxy (ctx context.Context , gwConn net.Conn , promAddr string ) {
210+ func proxy (ctx context.Context , gwConn net.Conn ) {
186211 cfg := yamux .DefaultConfig ()
187212 cfg .KeepAliveInterval = time .Second
188213 cfg .LogOutput = ioutil .Discard
@@ -199,30 +224,41 @@ func proxy(ctx context.Context, gwConn net.Conn, promAddr string) {
199224 default :
200225 gwStream , err := session .Accept ()
201226 if err != nil {
202- klog .Errorf ("failed to accept stream: %s" , err )
227+ klog .Errorf ("failed to accept a stream: %s" , err )
203228 return
204229 }
205230 go func (c net.Conn ) {
206231 defer c .Close ()
207232 deadline := time .Now ().Add (streamTimeout )
208233 if err := c .SetDeadline (deadline ); err != nil {
209- klog .Errorf ("failed to set deadline to stream: %s" , err )
234+ klog .Errorf ("failed to set a deadline for the stream: %s" , err )
210235 return
211236 }
212- promConn , err := net .DialTimeout ("tcp" , promAddr , timeout )
237+ var dstLen uint16
238+ if err := binary .Read (c , binary .LittleEndian , & dstLen ); err != nil {
239+ klog .Errorf ("failed to read the destination size: %s" , err )
240+ return
241+ }
242+ dest := make ([]byte , int (dstLen ))
243+ if _ , err := io .ReadFull (c , dest ); err != nil {
244+ klog .Errorf ("failed to read the destination address: %s" , err )
245+ return
246+ }
247+ destAddress := string (dest )
248+ destConn , err := net .DialTimeout ("tcp" , destAddress , timeout )
213249 if err != nil {
214- klog .Errorf ("failed to establish prometheus connection: %s" , err )
250+ klog .Errorf ("failed to establish a connection to %s : %s" , destAddress , err )
215251 return
216252 }
217- defer promConn .Close ()
218- if err = promConn .SetDeadline (deadline ); err != nil {
219- klog .Errorf ("failed to set deadline to prometheus connection: %s" , err )
253+ defer destConn .Close ()
254+ if err = destConn .SetDeadline (deadline ); err != nil {
255+ klog .Errorf ("failed to set a deadline for the dest connection: %s" , err )
220256 return
221257 }
222258 go func () {
223- io .Copy (c , promConn )
259+ io .Copy (c , destConn )
224260 }()
225- io .Copy (promConn , c )
261+ io .Copy (destConn , c )
226262 }(gwStream )
227263 }
228264 }
@@ -235,12 +271,3 @@ func mustEnv(key string) string {
235271 }
236272 return value
237273}
238-
239- func pingProm (addr string ) error {
240- c , err := net .DialTimeout ("tcp" , addr , timeout )
241- if err != nil {
242- return err
243- }
244- _ = c .Close ()
245- return nil
246- }
0 commit comments