1
1
package main
2
2
3
3
import (
4
- "bytes"
5
- "context"
6
- "encoding/base64"
7
- "encoding/json"
8
- "fmt"
9
- "github.com/mdp/qrterminal/v3"
10
- box "github.com/sagernet/sing-box"
11
- "github.com/sagernet/sing-box/include"
4
+ "github.com/getlantern/lantern-server-manager/common"
12
5
"io"
13
- "math/rand/v2"
14
6
"net/http"
15
- "net/netip"
16
- "os"
17
7
"strings"
18
8
19
9
"github.com/charmbracelet/log"
20
- "github.com/golang-jwt/jwt/v5"
21
- "github.com/sagernet/sing-box/option"
22
- "github.com/sagernet/sing/common"
23
- singJson "github.com/sagernet/sing/common/json"
24
- "github.com/sagernet/sing/common/json/badjson"
25
- "github.com/sagernet/sing/common/json/badoption"
26
10
)
27
11
28
12
type InitCmd struct {
29
13
}
30
14
31
- func GenerateAccessToken (hmacSecret []byte ) (string , error ) {
32
- token := jwt .NewWithClaims (jwt .SigningMethodHS256 , jwt.MapClaims {
33
- "sub" : "admin" ,
34
- // no expiration
35
- })
36
-
37
- // Sign and get the complete encoded token as a string using the secret
38
- return token .SignedString (hmacSecret )
39
- }
40
-
41
- func PasswordGenerator (passwordLength int ) string {
42
- lowerCase := "abcdefghijklmnopqrstuvwxyz" // lowercase
43
- upperCase := "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // uppercase
44
- Numbers := "0123456789" // numbers
45
- specialChar := "!@#$%^&*()_-+={}[/?]" // specialchar
46
-
47
- // variable for storing password
48
- password := ""
49
-
50
- for n := 0 ; n < passwordLength ; n ++ {
51
- // NOW RANDOM CHARACTER
52
- randNum := rand .N (4 )
53
-
54
- switch randNum {
55
- case 0 :
56
- randCharNum := rand .N (len (lowerCase ))
57
- password += string (lowerCase [randCharNum ])
58
- case 1 :
59
- randCharNum := rand .N (len (upperCase ))
60
- password += string (upperCase [randCharNum ])
61
- case 2 :
62
- randCharNum := rand .N (len (Numbers ))
63
- password += string (Numbers [randCharNum ])
64
- case 3 :
65
- randCharNum := rand .N (len (specialChar ))
66
- password += string (specialChar [randCharNum ])
67
- }
68
- }
69
-
70
- return password
71
- }
72
-
73
- type ServerConfig struct {
74
- Port int `json:"port"`
75
- AccessToken string `json:"access_token"`
76
- HMACSecret string `json:"hmac_secret"`
77
- }
78
-
79
- func (c * ServerConfig ) GetNewServerURL (publicIP string ) string {
80
- return fmt .Sprintf ("lantern://new-private-server?ip=%s&port=%d&token=%s" , publicIP , c .Port , c .AccessToken )
81
- }
82
- func (c * ServerConfig ) GetQR (publicIP string ) string {
83
- qrCode := bytes .NewBufferString ("" )
84
- qrterminal .Generate (c .GetNewServerURL (publicIP ), qrterminal .L , qrCode )
85
-
86
- return qrCode .String ()
87
- }
88
- func readServerConfig () (* ServerConfig , error ) {
89
- data , err := os .ReadFile ("server.json" )
90
- if err != nil {
91
- return nil , err
92
- }
93
- var config ServerConfig
94
- if err := json .Unmarshal (data , & config ); err != nil {
95
- return nil , err
96
- }
97
- if config .Port == 0 {
98
- return nil , fmt .Errorf ("port not set" )
99
- }
100
- if config .AccessToken == "" {
101
- return nil , fmt .Errorf ("access token not set" )
102
- }
103
- if config .HMACSecret == "" {
104
- return nil , fmt .Errorf ("hmac secret not set" )
105
- }
106
- return & config , nil
107
- }
108
-
109
- func generateServerConfig () (* ServerConfig , error ) {
110
- // generate a number that is a valid non-privileged port
111
- port := rand .N (65535 - 1024 ) + 1024
112
- // generate hmac secret
113
- hmacSecret := PasswordGenerator (32 )
114
- // generate an access token
115
- accessToken , err := GenerateAccessToken ([]byte (hmacSecret ))
116
- if err != nil {
117
- return nil , err
118
- }
119
- conf := & ServerConfig {
120
- Port : port ,
121
- AccessToken : accessToken ,
122
- HMACSecret : hmacSecret ,
123
- }
124
- // write the config to a file
125
- data , err := json .Marshal (conf )
126
- if err != nil {
127
- return nil , err
128
- }
129
- log .Infof ("Writing intial config to server.json" )
130
- return conf , os .WriteFile ("server.json" , data , 0600 )
131
- }
132
-
133
- func readSingBoxServerConfig () (* option.Options , error ) {
134
- data , err := os .ReadFile ("sing-box-config.json" )
135
- if err != nil {
136
- return nil , err
137
- }
138
- globalCtx := box .Context (context .Background (), include .InboundRegistry (), include .OutboundRegistry (), include .EndpointRegistry (), include .DNSTransportRegistry ())
139
-
140
- opt , err := singJson .UnmarshalExtendedContext [option.Options ](globalCtx , data )
141
- if err != nil {
142
- return nil , err
143
- }
144
- return & opt , nil
145
- }
146
-
147
- func generateSingboxConnectConfig (publicIP , username string ) ([]byte , error ) {
148
- singBoxServerConfig , err := readSingBoxServerConfig ()
149
- if err != nil {
150
- return nil , err
151
- }
152
- if len (singBoxServerConfig .Inbounds ) == 0 {
153
- return nil , fmt .Errorf ("no inbounds found, invalid config" )
154
- }
155
- inboundOptions , ok := singBoxServerConfig .Inbounds [0 ].Options .(* option.ShadowsocksInboundOptions )
156
- if ! ok {
157
- return nil , fmt .Errorf ("inbound is not shadowsocks" )
158
- }
159
- var password string
160
- if username == "admin" {
161
- password = inboundOptions .Password
162
- } else {
163
- for _ , u := range inboundOptions .Users {
164
- if u .Name == username {
165
- password = u .Password
166
- break
167
- }
168
- }
169
- }
170
- if password == "" {
171
- return nil , fmt .Errorf ("user not found" )
172
- }
173
- opt := option.Options {
174
- Log : & option.LogOptions {
175
- Level : "debug" ,
176
- Output : "stdout" ,
177
- },
178
- Outbounds : []option.Outbound {
179
- {
180
- Type : "shadowsocks" ,
181
- Tag : "ss-outbound" ,
182
- Options : & option.ShadowsocksOutboundOptions {
183
- DialerOptions : option.DialerOptions {},
184
- ServerOptions : option.ServerOptions {
185
- Server : publicIP ,
186
- ServerPort : inboundOptions .ListenPort ,
187
- },
188
- Method : "2022-blake3-aes-128-gcm" ,
189
- Password : password ,
190
- },
191
- },
192
- },
193
- }
194
- return badjson .MarshallObjects (opt )
195
- }
196
-
197
- func generateBasicSingboxServerConfig () error {
198
- // generate a number that is a valid non-privileged port
199
- port := rand .N (65535 - 1024 ) + 1024
200
- // generate a password. we are using 2022-blake3-aes-128-gcm so length must be 16
201
- password := base64 .StdEncoding .EncodeToString ([]byte (PasswordGenerator (16 )))
202
- // generate basic shadowsocks config
203
- opt := option.Options {
204
- Log : & option.LogOptions {
205
- Level : "debug" ,
206
- Output : "stdout" ,
207
- },
208
- Inbounds : []option.Inbound {
209
- {
210
- Type : "shadowsocks" ,
211
- Tag : "ss-inbound" ,
212
-
213
- Options : & option.ShadowsocksInboundOptions {
214
- Method : "2022-blake3-aes-128-gcm" ,
215
- ListenOptions : option.ListenOptions {
216
- ListenPort : uint16 (port ),
217
- Listen : common .Ptr (badoption .Addr (netip .AddrFrom4 ([4 ]byte {0 , 0 , 0 , 0 }))),
218
- },
219
- Password : password ,
220
- },
221
- },
222
- },
223
- }
224
- data , err := badjson .MarshallObjects (opt )
225
- if err != nil {
226
- return err
227
- }
228
- log .Infof ("Writing intial vpn config to sing-box-config.json" )
229
- return os .WriteFile ("sing-box-config.json" , data , 0644 )
230
- }
231
-
232
15
func getPublicIP () (string , error ) {
233
16
resp , err := http .Get ("https://ifconfig.io" )
234
17
if err != nil {
@@ -244,22 +27,28 @@ func getPublicIP() (string, error) {
244
27
return strings .TrimSpace (string (body )), nil
245
28
}
246
29
247
- func (c InitCmd ) Run () error {
248
- var err error
249
- var config * ServerConfig
250
- if config , err = generateServerConfig (); err != nil {
251
- return err
30
+ func InitializeConfigs () (* common.ServerConfig , error ) {
31
+ config , err := common .GenerateServerConfig ()
32
+ if err != nil {
33
+ return nil , err
252
34
}
253
- if err = generateBasicSingboxServerConfig (); err != nil {
254
- return err
35
+ if err = common . GenerateBasicSingboxServerConfig (); err != nil {
36
+ return nil , err
255
37
}
38
+ return config , nil
39
+ }
256
40
257
- printRootToken (config )
41
+ func (c InitCmd ) Run () error {
42
+ if config , err := InitializeConfigs (); err != nil {
43
+ return err
44
+ } else {
45
+ printRootToken (config )
46
+ }
258
47
259
48
return nil
260
49
}
261
50
262
- func printRootToken (config * ServerConfig ) {
51
+ func printRootToken (config * common. ServerConfig ) {
263
52
publicIP , err := getPublicIP ()
264
53
if err != nil {
265
54
log .Error ("Cannot detect your public IP, please get if from your host provider" )
0 commit comments