-
Notifications
You must be signed in to change notification settings - Fork 6
/
config.go
144 lines (120 loc) · 3 KB
/
config.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package torproxy
import (
"bytes"
"context"
"fmt"
"io"
"os"
"os/exec"
"strconv"
"time"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"github.com/cretz/bine/tor"
"gopkg.in/natefinch/lumberjack.v2"
)
// TorProxy config
type Config struct {
To map[string]string
Client *Tor
}
// Tor instance config struct
type Tor struct {
// Socks5 proxy port
Host string
Port int
DataDir string
Torrc string
DebugMode bool
LogFile string
debugger io.Writer
instance *tor.Tor
contextCanceler context.CancelFunc
onion *tor.OnionService
}
// DefaultOnionServicePort is the port used to serve the onion service on
const DefaultOnionServicePort = 4242
// TODO: Discuss these values
const (
torProxyKeepalive = 30000000
torFallbackDelay = 30000000 * time.Millisecond
torProxyTimeout = 30000000 * time.Second
)
// ParseTor parses advanced config for Tor client
func (t *Tor) ParseTor(d *caddyfile.Dispenser) error {
switch d.Val() {
case "host":
t.Host = d.RemainingArgs()[0]
case "port":
value, err := strconv.Atoi(d.RemainingArgs()[0])
if err != nil {
return fmt.Errorf("The given value for port field is not standard. It should be an integer")
}
t.Port = value
case "datadir":
t.DataDir = d.RemainingArgs()[0]
case "torrc":
t.Torrc = d.RemainingArgs()[0]
case "debug_mode":
value, err := strconv.ParseBool(d.RemainingArgs()[0])
if err != nil {
return fmt.Errorf("The given value for debug_mode field is not standard. It should be a boolean")
}
t.DebugMode = value
case "logfile":
t.LogFile = d.RemainingArgs()[0]
default:
return d.ArgErr() // unhandled option for tor
}
return nil
}
// SetDefaults sets the default values for prometheus config
// if the fields are empty
func (t *Tor) SetDefaults() {
if t.DebugMode {
if t.LogFile != "" {
t.debugger = &lumberjack.Logger{
Filename: t.LogFile,
MaxSize: 100,
MaxAge: 14,
MaxBackups: 10,
}
}
t.debugger = os.Stdout
}
if t.Host == "" {
t.Host = "127.0.0.1"
}
if t.Port == 0 {
t.Port = DefaultOnionServicePort
}
}
// TorConstructor return a new instance of Tor client struct.
// Used to manage the Tor client's life cycle
func TorConstructor() (caddy.Destructor, error) {
return &Tor{}, nil
}
// Destruct stops the Tor client
func (t *Tor) Destruct() error {
return t.Stop()
}
// IsInstalled checks the Tor client using the `tor --version` command
func (t *Tor) IsInstalled() error {
// Setup and run the "tor --version" command
cmd := exec.Command("tor", "--version")
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}
if err := cmd.Start(); err != nil {
return err
}
// Read the output into buffer
buf := new(bytes.Buffer)
buf.ReadFrom(stdout)
// Check if the output contains Tor's version
if buf.String()[0:3] != "Tor" {
return fmt.Errorf("Tor is not installed on you machine.Please follow these instructions to install Tor: https://www.torproject.org/download/")
}
return nil
}