@@ -4,29 +4,37 @@ import (
4
4
"bytes"
5
5
"context"
6
6
"crypto/ed25519"
7
+ "crypto/tls"
7
8
"encoding/base64"
8
9
"encoding/hex"
9
10
"encoding/json"
10
11
"flag"
11
12
"fmt"
12
13
"github.com/mdp/qrterminal/v3"
14
+ "github.com/rs/zerolog"
15
+ "github.com/rs/zerolog/log"
13
16
"github.com/sigurn/crc16"
17
+ tunnelConfig "github.com/ton-blockchain/adnl-tunnel/config"
18
+ "github.com/ton-blockchain/adnl-tunnel/tunnel"
14
19
"github.com/ton-utils/reverse-proxy/config"
20
+ "github.com/ton-utils/reverse-proxy/rldphttp"
15
21
"github.com/xssnick/tonutils-go/adnl"
22
+ "github.com/xssnick/tonutils-go/adnl/address"
16
23
"github.com/xssnick/tonutils-go/adnl/dht"
17
24
"github.com/xssnick/tonutils-go/adnl/rldp"
18
- rldphttp "github.com/xssnick/tonutils-go/adnl/rldp/http"
19
25
"github.com/xssnick/tonutils-go/liteclient"
20
26
"github.com/xssnick/tonutils-go/tlb"
21
27
"github.com/xssnick/tonutils-go/ton"
22
28
"github.com/xssnick/tonutils-go/ton/dns"
23
29
"io"
24
- "log"
30
+ regularLog "log"
25
31
"net"
26
32
"net/http"
27
33
"net/http/httputil"
28
34
"net/url"
29
35
"os"
36
+ "strconv"
37
+ "strings"
30
38
"time"
31
39
)
32
40
@@ -41,10 +49,41 @@ type Config struct {
41
49
42
50
var FlagDomain = flag .String ("domain" , "" , "domain to configure" )
43
51
var FlagDebug = flag .Bool ("debug" , false , "more logs" )
52
+ var FlagAllowInsecureHttps = flag .Bool ("allow-insecure-https" , false , "allow insecure https" )
44
53
var FlagTxURL = flag .Bool ("tx-url" , false , "show set domain record url instead of qr" )
54
+ var TunnelConfig = flag .String ("tunnel-config" , "" , "tunnel config path" )
45
55
46
56
var GitCommit = "custom"
47
- var Version = "v0.3.3"
57
+ var Version = "v0.4.0"
58
+
59
+ func envOrVal (env string , arg any ) any {
60
+ var res = arg
61
+
62
+ val , exists := os .LookupEnv (env )
63
+ if exists && val != "" {
64
+ switch arg .(type ) {
65
+ case []byte :
66
+ v , err := base64 .StdEncoding .DecodeString (val )
67
+ if err != nil {
68
+ panic (err .Error ())
69
+ }
70
+ return v
71
+ case uint16 :
72
+ v , err := strconv .ParseUint (val , 10 , 16 )
73
+ if err != nil {
74
+ panic (err .Error ())
75
+ }
76
+ return uint16 (v )
77
+ case string :
78
+ return val
79
+ case bool :
80
+ ok := strings .ToLower (val ) != "0" && strings .ToLower (val ) != "false"
81
+ return ok
82
+ }
83
+ }
84
+
85
+ return res
86
+ }
48
87
49
88
type Handler struct {
50
89
h http.Handler
@@ -56,7 +95,9 @@ func (h Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
56
95
if err != nil {
57
96
return
58
97
}
59
- fmt .Println ("REQUEST:" , string (reqDump ))
98
+ log .Debug ().
99
+ Str ("request_dump" , string (reqDump )).
100
+ Msg ("Dumping HTTP request" )
60
101
}
61
102
62
103
hdr := http.Header {}
@@ -68,7 +109,11 @@ func (h Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
68
109
}
69
110
request .Header = hdr
70
111
71
- log .Println ("request:" , request .Method , request .Host , request .RequestURI )
112
+ log .Debug ().
113
+ Str ("method" , request .Method ).
114
+ Str ("host" , request .Host ).
115
+ Str ("uri" , request .RequestURI ).
116
+ Msg ("Received HTTP request" )
72
117
73
118
writer .Header ().Set ("Ton-Reverse-Proxy" , "Tonutils Reverse Proxy " + Version )
74
119
h .h .ServeHTTP (writer , request )
@@ -77,20 +122,24 @@ func (h Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
77
122
func main () {
78
123
flag .Parse ()
79
124
80
- log .Println ("Tonutils Reverse Proxy" , Version + ", build: " + GitCommit )
125
+ log .Logger = log .Output (zerolog.ConsoleWriter {Out : os .Stdout }).Level (zerolog .InfoLevel )
126
+ if * FlagDebug {
127
+ log .Logger = log .Logger .Level (zerolog .DebugLevel )
128
+ }
129
+
130
+ log .Info ().Str ("version" , Version ).Str ("build" , GitCommit ).Msg ("Starting Tonutils Reverse Proxy" )
81
131
82
132
cfg , err := loadConfig ()
83
133
if err != nil {
84
- panic ( "failed to load config: " + err . Error () )
134
+ log . Fatal (). Err ( err ). Msg ( "Failed to load config" )
85
135
}
86
136
87
137
netCfg , err := liteclient .GetConfigFromUrl (context .Background (), cfg .NetworkConfigURL )
88
138
if err != nil {
89
- log .Println ( "failed to download ton config:" , err . Error (), "; we will take it from static cache" )
139
+ log .Warn (). Err ( err ). Msg ( "Failed to download TON config, using static cache" )
90
140
netCfg = & liteclient.GlobalConfig {}
91
141
if err = json .NewDecoder (bytes .NewBufferString (config .FallbackNetworkConfig )).Decode (netCfg ); err != nil {
92
- log .Println ("failed to parse fallback ton config:" , err .Error ())
93
- os .Exit (1 )
142
+ log .Fatal ().Err (err ).Msg ("Failed to parse fallback TON config" )
94
143
}
95
144
}
96
145
@@ -101,56 +150,111 @@ func main() {
101
150
102
151
err = client .AddConnectionsFromConfig (ctx , netCfg )
103
152
if err != nil {
104
- panic ( err )
153
+ log . Fatal (). Err ( err ). Msg ( "Failed to add connections from config" )
105
154
}
106
155
107
156
_ , dhtAdnlKey , err := ed25519 .GenerateKey (nil )
108
157
if err != nil {
109
- panic ( "failed to generate ed25519 key for dht: " + err . Error () )
158
+ log . Fatal (). Err ( err ). Msg ( "Failed to generate key for DHT" )
110
159
}
111
160
112
- gateway := adnl .NewGateway (dhtAdnlKey )
113
- err = gateway .StartClient ()
161
+ dhtGateway := adnl .NewGateway (dhtAdnlKey )
162
+ err = dhtGateway .StartClient ()
114
163
if err != nil {
115
- panic ( "failed to load network config: " + err . Error () )
164
+ log . Fatal (). Err ( err ). Msg ( "Failed to start ADNL gateway client" )
116
165
}
117
166
118
- dhtClient , err := dht .NewClientFromConfig (gateway , netCfg )
167
+ dhtClient , err := dht .NewClientFromConfig (dhtGateway , netCfg )
119
168
if err != nil {
120
- panic (err )
169
+ log .Fatal ().Err (err ).Msg ("Failed to create DHT client from config" )
170
+ }
171
+
172
+ var gate * adnl.Gateway
173
+ if * TunnelConfig != "" {
174
+ data , err := os .ReadFile (* TunnelConfig )
175
+ if err != nil {
176
+ if os .IsNotExist (err ) {
177
+ if _ , err = tunnelConfig .GenerateClientConfig (* TunnelConfig ); err != nil {
178
+ log .Error ().Err (err ).Msg ("Failed to generate tunnel config" )
179
+ os .Exit (1 )
180
+ }
181
+ log .Info ().Msg ("Generated tunnel config; fill it with the desired route and restart" )
182
+ os .Exit (0 )
183
+ }
184
+ log .Fatal ().Err (err ).Msg ("Failed to load tunnel config" )
185
+ }
186
+
187
+ var tunCfg tunnelConfig.ClientConfig
188
+ if err = json .Unmarshal (data , & tunCfg ); err != nil {
189
+ log .Fatal ().Err (err ).Msg ("Failed to parse tunnel config" )
190
+ }
191
+
192
+ tun , port , ip , err := tunnel .PrepareTunnel (& tunCfg , netCfg )
193
+ if err != nil {
194
+ log .Fatal ().Err (err ).Msg ("Failed to prepare tunnel" )
195
+ }
196
+
197
+ gate = adnl .NewGatewayWithListener (ed25519 .NewKeyFromSeed (cfg .PrivateKey ), func (addr string ) (net.PacketConn , error ) {
198
+ return tun , nil
199
+ })
200
+ gate .SetAddressList ([]* address.UDP {
201
+ {
202
+ IP : ip ,
203
+ Port : int32 (port ),
204
+ },
205
+ })
206
+
207
+ tun .SetOutAddressChangedHandler (func (addr * net.UDPAddr ) {
208
+ gate .SetAddressList ([]* address.UDP {
209
+ {
210
+ IP : addr .IP ,
211
+ Port : int32 (addr .Port ),
212
+ },
213
+ })
214
+ })
215
+ } else {
216
+ gate = adnl .NewGateway (ed25519 .NewKeyFromSeed (cfg .PrivateKey ))
217
+ gate .SetAddressList ([]* address.UDP {
218
+ {
219
+ IP : net .ParseIP (cfg .ExternalIP ).To4 (),
220
+ Port : int32 (cfg .Port ),
221
+ },
222
+ })
121
223
}
122
224
123
225
u , err := url .Parse (cfg .ProxyPass )
124
226
if err != nil {
125
- panic ( err )
227
+ log . Fatal (). Err ( err ). Msg ( "Failed to parse proxy pass URL" )
126
228
}
127
229
128
230
if * FlagDebug == false {
129
231
adnl .Logger = func (v ... any ) {}
130
232
rldphttp .Logger = func (v ... any ) {}
131
233
} else {
132
- rldp .Logger = log .Println
133
- rldphttp .Logger = log .Println
134
- adnl .Logger = log .Println
234
+ rldp .Logger = regularLog .Println
235
+ rldphttp .Logger = regularLog .Println
236
+ // adnl.Logger = regularLog .Println
135
237
}
136
238
137
239
proxy := httputil .NewSingleHostReverseProxy (u )
138
- s := rldphttp .NewServer (ed25519 .NewKeyFromSeed (cfg .PrivateKey ), dhtClient , Handler {proxy })
139
- s .SetExternalIP (net .ParseIP (cfg .ExternalIP ).To4 ())
240
+ if * FlagAllowInsecureHttps {
241
+ proxy .Transport = & http.Transport {TLSClientConfig : & tls.Config {InsecureSkipVerify : true }}
242
+ }
243
+ s := rldphttp .NewServer (ed25519 .NewKeyFromSeed (cfg .PrivateKey ), gate , dhtClient , Handler {proxy })
140
244
141
245
addr , err := rldphttp .SerializeADNLAddress (s .Address ())
142
246
if err != nil {
143
- panic ( err )
247
+ log . Fatal (). Err ( err ). Msg ( "Failed to serialize ADNL address" )
144
248
}
145
- log .Println ( "Server's ADNL address is " , addr + ".adnl (" + hex .EncodeToString (s .Address ())+ ") " )
249
+ log .Info (). Str ( "ADNL_address " , addr ). Str ( "hex_address" , hex .EncodeToString (s .Address ())). Msg ( "Server's ADNL address " )
146
250
147
251
if * FlagDomain != "" {
148
252
setupDomain (client , * FlagDomain , s .Address ())
149
253
}
150
254
151
- log .Println ( "Starting server on " , addr + ".adnl" )
255
+ log .Info (). Str ( "address " , addr + ".adnl" ). Msg ( "Starting server " )
152
256
if err = s .ListenAndServe (fmt .Sprintf ("%s:%d" , cfg .ListenIP , cfg .Port )); err != nil {
153
- panic ( err )
257
+ log . Fatal (). Err ( err ). Msg ( "Failed to listen and serve" )
154
258
}
155
259
}
156
260
@@ -225,6 +329,13 @@ func loadConfig() (*Config, error) {
225
329
cfg .NetworkConfigURL = "https://ton.org/global.config.json"
226
330
}
227
331
332
+ cfg .ExternalIP = envOrVal ("EXTERNAL_IP" , cfg .ExternalIP ).(string )
333
+ cfg .ListenIP = envOrVal ("LISTEN_IP" , cfg .ListenIP ).(string )
334
+ cfg .Port = envOrVal ("LISTEN_PORT" , cfg .Port ).(uint16 )
335
+ cfg .ProxyPass = envOrVal ("PROXY_PASS" , cfg .ProxyPass ).(string )
336
+ cfg .PrivateKey = envOrVal ("PRIVATE_KEY" , cfg .PrivateKey ).([]byte )
337
+ cfg .NetworkConfigURL = envOrVal ("NETWORK_CONFIG_URL" , cfg .NetworkConfigURL ).(string )
338
+
228
339
return & cfg , nil
229
340
}
230
341
@@ -236,14 +347,14 @@ func setupDomain(client *liteclient.ConnectionPool, domain string, adnlAddr []by
236
347
// get root dns address from network config
237
348
root , err := dns .GetRootContractAddr (ctx , api )
238
349
if err != nil {
239
- log .Println ( "Failed to resolve root dns contract:" , err )
350
+ log .Error (). Err ( err ). Msg ( "Failed to resolve root dns contract" )
240
351
return
241
352
}
242
353
243
354
resolver := dns .NewDNSClient (api , root )
244
355
domainInfo , err := resolver .Resolve (ctx , domain )
245
356
if err != nil {
246
- log .Println ( " Failed to configure domain", domain , ":" , err )
357
+ log .Error (). Err ( err ). Str ( "domain" , domain ). Msg ( " Failed to configure domain" )
247
358
return
248
359
}
249
360
@@ -254,7 +365,7 @@ func setupDomain(client *liteclient.ConnectionPool, domain string, adnlAddr []by
254
365
255
366
nftData , err := domainInfo .GetNFTData (ctx )
256
367
if err != nil {
257
- log .Println ( " Failed to get domain data", domain , ":" , err )
368
+ log .Error (). Err ( err ). Str ( "domain" , domain ). Msg ( " Failed to get domain data" )
258
369
return
259
370
}
260
371
@@ -271,19 +382,19 @@ func setupDomain(client *liteclient.ConnectionPool, domain string, adnlAddr []by
271
382
time .Sleep (2 * time .Second )
272
383
updated , err := resolve (ctx , resolver , domain , adnlAddr )
273
384
if err != nil {
385
+ log .Warn ().Err (err ).Str ("domain" , domain ).Msg ("Retrying domain resolution" )
274
386
continue
275
387
}
276
388
277
389
if updated {
278
390
break
279
391
}
280
392
}
281
- fmt .Println ("Domain" , domain , "was successfully configured to use for your TON Site!" )
282
- fmt .Println ()
393
+ log .Info ().Str ("domain" , domain ).Msg ("Domain successfully configured to use for your TON Site" )
283
394
return
284
395
}
285
396
286
- fmt . Println ( "Domain " , domain , " is already configured to use with current ADNL address. Everything is OK!" )
397
+ log . Info (). Str ( "domain " , domain ). Msg ( "Domain is already configured to use with current ADNL address. Everything is OK!" )
287
398
}
288
399
289
400
func resolve (ctx context.Context , client * dns.Client , domain string , adnlAddr []byte ) (bool , error ) {
@@ -292,6 +403,7 @@ func resolve(ctx context.Context, client *dns.Client, domain string, adnlAddr []
292
403
293
404
domainInfo , err := client .Resolve (ctx , domain )
294
405
if err != nil {
406
+ log .Error ().Err (err ).Str ("domain" , domain ).Msg ("Failed to resolve domain" )
295
407
return false , err
296
408
}
297
409
0 commit comments