-
Notifications
You must be signed in to change notification settings - Fork 4
/
nanoproxy.go
116 lines (95 loc) · 2.83 KB
/
nanoproxy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package main
import (
"github.com/caarlos0/env/v10"
"github.com/rs/zerolog"
"github.com/ryanbekhen/nanoproxy/pkg/config"
"github.com/ryanbekhen/nanoproxy/pkg/credential"
"github.com/ryanbekhen/nanoproxy/pkg/httpproxy"
"github.com/ryanbekhen/nanoproxy/pkg/resolver"
"github.com/ryanbekhen/nanoproxy/pkg/socks5"
"github.com/ryanbekhen/nanoproxy/pkg/tor"
"net"
"net/http"
"os"
"strings"
"time"
_ "time/tzdata"
)
func main() {
cfg := &config.Config{}
logger := zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}).With().Timestamp().Logger()
if err := env.Parse(cfg); err != nil {
logger.Fatal().Msg(err.Error())
}
loc, _ := time.LoadLocation(cfg.Timezone)
if loc != nil {
time.Local = loc
}
var credentials credential.Store
if len(cfg.Credentials) > 0 {
credentials = credential.NewStaticCredentialStore()
for _, cred := range cfg.Credentials {
credArr := strings.Split(cred, ":")
if len(credArr) != 2 {
logger.Fatal().Msgf("Invalid credential: %s", cred)
}
credentials.Add(credArr[0], credArr[1])
}
}
dnsResolver := &resolver.DNSResolver{}
httpConfig := httpproxy.Config{
Credentials: credentials,
Logger: &logger,
DestConnTimeout: cfg.DestTimeout,
ClientConnTimeout: cfg.ClientTimeout,
Dial: net.Dial,
Resolver: dnsResolver,
}
httpServer := httpproxy.New(&httpConfig)
socks5Config := socks5.Config{
Logger: &logger,
DestConnTimeout: cfg.DestTimeout,
ClientConnTimeout: cfg.ClientTimeout,
Resolver: dnsResolver,
}
if cfg.TorEnabled {
torDialer := &tor.DefaultDialer{}
socks5Config.Dial = torDialer.Dial
httpConfig.Dial = torDialer.Dial
logger.Info().Msg("Tor mode enabled")
torController := tor.NewTorController(torDialer)
ch := make(chan bool)
go tor.SwitcherIdentity(&logger, torController, cfg.TorIdentityInterval, ch)
go func() {
<-ch
logger.Fatal().Msg("Tor identity switcher stopped")
}()
}
if len(cfg.Credentials) > 0 {
authenticator := &socks5.UserPassAuthenticator{
Credentials: credentials,
}
socks5Config.Authentication = append(socks5Config.Authentication, authenticator)
}
sock5Server := socks5.New(&socks5Config)
go func() {
logger.Info().Msgf("Starting HTTP proxy server on %s://%s", cfg.Network, cfg.ADDRHttp)
server := &http.Server{
Addr: cfg.ADDRHttp,
Handler: httpServer,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logger.Fatal().Msg(err.Error())
}
}()
go func() {
logger.Info().Msgf("Starting SOCKS5 server on %s://%s", cfg.Network, cfg.ADDR)
if err := sock5Server.ListenAndServe(cfg.Network, cfg.ADDR); err != nil {
logger.Fatal().Msg(err.Error())
}
}()
select {}
}