Skip to content

Commit 018e339

Browse files
authored
Merge pull request #43 from tonutils/dev04
ENV override for config, tunnel support, insecure https flag
2 parents 673df6c + a559e41 commit 018e339

File tree

9 files changed

+1006
-50
lines changed

9 files changed

+1006
-50
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
.idea
2-
build
2+
build
3+
*.json
4+
payments-db/

cmd/proxy/main.go

+145-33
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,37 @@ import (
44
"bytes"
55
"context"
66
"crypto/ed25519"
7+
"crypto/tls"
78
"encoding/base64"
89
"encoding/hex"
910
"encoding/json"
1011
"flag"
1112
"fmt"
1213
"github.com/mdp/qrterminal/v3"
14+
"github.com/rs/zerolog"
15+
"github.com/rs/zerolog/log"
1316
"github.com/sigurn/crc16"
17+
tunnelConfig "github.com/ton-blockchain/adnl-tunnel/config"
18+
"github.com/ton-blockchain/adnl-tunnel/tunnel"
1419
"github.com/ton-utils/reverse-proxy/config"
20+
"github.com/ton-utils/reverse-proxy/rldphttp"
1521
"github.com/xssnick/tonutils-go/adnl"
22+
"github.com/xssnick/tonutils-go/adnl/address"
1623
"github.com/xssnick/tonutils-go/adnl/dht"
1724
"github.com/xssnick/tonutils-go/adnl/rldp"
18-
rldphttp "github.com/xssnick/tonutils-go/adnl/rldp/http"
1925
"github.com/xssnick/tonutils-go/liteclient"
2026
"github.com/xssnick/tonutils-go/tlb"
2127
"github.com/xssnick/tonutils-go/ton"
2228
"github.com/xssnick/tonutils-go/ton/dns"
2329
"io"
24-
"log"
30+
regularLog "log"
2531
"net"
2632
"net/http"
2733
"net/http/httputil"
2834
"net/url"
2935
"os"
36+
"strconv"
37+
"strings"
3038
"time"
3139
)
3240

@@ -41,10 +49,41 @@ type Config struct {
4149

4250
var FlagDomain = flag.String("domain", "", "domain to configure")
4351
var FlagDebug = flag.Bool("debug", false, "more logs")
52+
var FlagAllowInsecureHttps = flag.Bool("allow-insecure-https", false, "allow insecure https")
4453
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")
4555

4656
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+
}
4887

4988
type Handler struct {
5089
h http.Handler
@@ -56,7 +95,9 @@ func (h Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
5695
if err != nil {
5796
return
5897
}
59-
fmt.Println("REQUEST:", string(reqDump))
98+
log.Debug().
99+
Str("request_dump", string(reqDump)).
100+
Msg("Dumping HTTP request")
60101
}
61102

62103
hdr := http.Header{}
@@ -68,7 +109,11 @@ func (h Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
68109
}
69110
request.Header = hdr
70111

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")
72117

73118
writer.Header().Set("Ton-Reverse-Proxy", "Tonutils Reverse Proxy "+Version)
74119
h.h.ServeHTTP(writer, request)
@@ -77,20 +122,24 @@ func (h Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
77122
func main() {
78123
flag.Parse()
79124

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")
81131

82132
cfg, err := loadConfig()
83133
if err != nil {
84-
panic("failed to load config: " + err.Error())
134+
log.Fatal().Err(err).Msg("Failed to load config")
85135
}
86136

87137
netCfg, err := liteclient.GetConfigFromUrl(context.Background(), cfg.NetworkConfigURL)
88138
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")
90140
netCfg = &liteclient.GlobalConfig{}
91141
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")
94143
}
95144
}
96145

@@ -101,56 +150,111 @@ func main() {
101150

102151
err = client.AddConnectionsFromConfig(ctx, netCfg)
103152
if err != nil {
104-
panic(err)
153+
log.Fatal().Err(err).Msg("Failed to add connections from config")
105154
}
106155

107156
_, dhtAdnlKey, err := ed25519.GenerateKey(nil)
108157
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")
110159
}
111160

112-
gateway := adnl.NewGateway(dhtAdnlKey)
113-
err = gateway.StartClient()
161+
dhtGateway := adnl.NewGateway(dhtAdnlKey)
162+
err = dhtGateway.StartClient()
114163
if err != nil {
115-
panic("failed to load network config: " + err.Error())
164+
log.Fatal().Err(err).Msg("Failed to start ADNL gateway client")
116165
}
117166

118-
dhtClient, err := dht.NewClientFromConfig(gateway, netCfg)
167+
dhtClient, err := dht.NewClientFromConfig(dhtGateway, netCfg)
119168
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+
})
121223
}
122224

123225
u, err := url.Parse(cfg.ProxyPass)
124226
if err != nil {
125-
panic(err)
227+
log.Fatal().Err(err).Msg("Failed to parse proxy pass URL")
126228
}
127229

128230
if *FlagDebug == false {
129231
adnl.Logger = func(v ...any) {}
130232
rldphttp.Logger = func(v ...any) {}
131233
} 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
135237
}
136238

137239
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})
140244

141245
addr, err := rldphttp.SerializeADNLAddress(s.Address())
142246
if err != nil {
143-
panic(err)
247+
log.Fatal().Err(err).Msg("Failed to serialize ADNL address")
144248
}
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")
146250

147251
if *FlagDomain != "" {
148252
setupDomain(client, *FlagDomain, s.Address())
149253
}
150254

151-
log.Println("Starting server on", addr+".adnl")
255+
log.Info().Str("address", addr+".adnl").Msg("Starting server")
152256
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")
154258
}
155259
}
156260

@@ -225,6 +329,13 @@ func loadConfig() (*Config, error) {
225329
cfg.NetworkConfigURL = "https://ton.org/global.config.json"
226330
}
227331

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+
228339
return &cfg, nil
229340
}
230341

@@ -236,14 +347,14 @@ func setupDomain(client *liteclient.ConnectionPool, domain string, adnlAddr []by
236347
// get root dns address from network config
237348
root, err := dns.GetRootContractAddr(ctx, api)
238349
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")
240351
return
241352
}
242353

243354
resolver := dns.NewDNSClient(api, root)
244355
domainInfo, err := resolver.Resolve(ctx, domain)
245356
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")
247358
return
248359
}
249360

@@ -254,7 +365,7 @@ func setupDomain(client *liteclient.ConnectionPool, domain string, adnlAddr []by
254365

255366
nftData, err := domainInfo.GetNFTData(ctx)
256367
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")
258369
return
259370
}
260371

@@ -271,19 +382,19 @@ func setupDomain(client *liteclient.ConnectionPool, domain string, adnlAddr []by
271382
time.Sleep(2 * time.Second)
272383
updated, err := resolve(ctx, resolver, domain, adnlAddr)
273384
if err != nil {
385+
log.Warn().Err(err).Str("domain", domain).Msg("Retrying domain resolution")
274386
continue
275387
}
276388

277389
if updated {
278390
break
279391
}
280392
}
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")
283394
return
284395
}
285396

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!")
287398
}
288399

289400
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 []
292403

293404
domainInfo, err := client.Resolve(ctx, domain)
294405
if err != nil {
406+
log.Error().Err(err).Str("domain", domain).Msg("Failed to resolve domain")
295407
return false, err
296408
}
297409

go.mod

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
11
module github.com/ton-utils/reverse-proxy
22

3-
go 1.19
3+
go 1.23.3
44

55
require (
66
github.com/mdp/qrterminal/v3 v3.0.0
7-
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
8-
github.com/xssnick/tonutils-go v1.9.9-0.20240729172752-0ce0d252a288
7+
github.com/rs/zerolog v1.33.0
8+
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1
9+
github.com/ton-blockchain/adnl-tunnel v0.0.0-20250227065935-bdeeba972e50
10+
github.com/xssnick/tonutils-go v1.11.1-0.20250226184842-e0277c2b08f8
911
)
1012

1113
require (
12-
github.com/oasisprotocol/curve25519-voi v0.0.0-20220328075252-7dd334e3daae // indirect
13-
golang.org/x/crypto v0.17.0 // indirect
14-
golang.org/x/sys v0.15.0 // indirect
14+
github.com/golang/snappy v0.0.4 // indirect
15+
github.com/kevinms/leakybucket-go v0.0.0-20200115003610-082473db97ca // indirect
16+
github.com/mattn/go-colorable v0.1.14 // indirect
17+
github.com/mattn/go-isatty v0.0.20 // indirect
18+
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect
19+
github.com/syndtr/goleveldb v1.0.0 // indirect
20+
github.com/xssnick/raptorq v1.0.0 // indirect
21+
github.com/xssnick/ton-payment-network v0.0.0-20250211055352-ed9cef403ce1 // indirect
22+
golang.org/x/crypto v0.35.0 // indirect
23+
golang.org/x/net v0.35.0 // indirect
24+
golang.org/x/sys v0.30.0 // indirect
1525
rsc.io/qr v0.2.0 // indirect
1626
)

0 commit comments

Comments
 (0)