├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── docs ├── SOCKS5协议.md ├── socks5.png ├── 前期准备.md ├── 加密.md ├── 原理.md ├── 部署.md └── 配置.md ├── images ├── .gitignore └── a.png ├── proxy.pac └── src ├── bin ├── local.rs ├── server.rs └── socket.rs ├── ciper.rs ├── config.rs ├── daemon.rs ├── lib.rs ├── local.rs ├── pac.rs ├── password.rs ├── server.rs └── socks5.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | config.json 3 | config2.json 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aho-corasick" 5 | version = "0.7.6" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "ansi_term" 13 | version = "0.11.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 17 | ] 18 | 19 | [[package]] 20 | name = "async-attributes" 21 | version = "1.1.1" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | dependencies = [ 24 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 25 | "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 26 | ] 27 | 28 | [[package]] 29 | name = "async-macros" 30 | version = "2.0.0" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | dependencies = [ 33 | "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 34 | "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", 35 | ] 36 | 37 | [[package]] 38 | name = "async-std" 39 | version = "1.2.0" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | dependencies = [ 42 | "async-attributes 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 43 | "async-macros 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 44 | "async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 45 | "broadcaster 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 46 | "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 47 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 48 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 49 | "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 50 | "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 51 | "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 53 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 54 | "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 55 | "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", 56 | "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", 57 | "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", 58 | "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 59 | "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 60 | "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", 61 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 62 | ] 63 | 64 | [[package]] 65 | name = "async-task" 66 | version = "1.0.0" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | dependencies = [ 69 | "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 70 | ] 71 | 72 | [[package]] 73 | name = "atty" 74 | version = "0.2.13" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | dependencies = [ 77 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 78 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 79 | ] 80 | 81 | [[package]] 82 | name = "autocfg" 83 | version = "0.1.7" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | 86 | [[package]] 87 | name = "base64" 88 | version = "0.11.0" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | 91 | [[package]] 92 | name = "bitflags" 93 | version = "1.2.1" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | 96 | [[package]] 97 | name = "boxfnonce" 98 | version = "0.1.1" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | 101 | [[package]] 102 | name = "broadcaster" 103 | version = "0.2.6" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | dependencies = [ 106 | "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 107 | "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 108 | "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 109 | "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 110 | "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 111 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 112 | ] 113 | 114 | [[package]] 115 | name = "byteorder" 116 | version = "1.3.2" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | 119 | [[package]] 120 | name = "bytes" 121 | version = "0.5.3" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | 124 | [[package]] 125 | name = "c2-chacha" 126 | version = "0.2.3" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | dependencies = [ 129 | "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 130 | ] 131 | 132 | [[package]] 133 | name = "cfg-if" 134 | version = "0.1.10" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | 137 | [[package]] 138 | name = "clap" 139 | version = "2.33.0" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | dependencies = [ 142 | "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 143 | "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", 144 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 145 | "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 146 | "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 147 | "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 148 | "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 149 | ] 150 | 151 | [[package]] 152 | name = "cloudabi" 153 | version = "0.0.3" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | dependencies = [ 156 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 157 | ] 158 | 159 | [[package]] 160 | name = "crossbeam-channel" 161 | version = "0.4.0" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | dependencies = [ 164 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 165 | ] 166 | 167 | [[package]] 168 | name = "crossbeam-deque" 169 | version = "0.7.2" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | dependencies = [ 172 | "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 173 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 174 | ] 175 | 176 | [[package]] 177 | name = "crossbeam-epoch" 178 | version = "0.8.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | dependencies = [ 181 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 182 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 183 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 184 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 185 | "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", 186 | "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 187 | ] 188 | 189 | [[package]] 190 | name = "crossbeam-utils" 191 | version = "0.6.6" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | dependencies = [ 194 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 195 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 196 | ] 197 | 198 | [[package]] 199 | name = "crossbeam-utils" 200 | version = "0.7.0" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | dependencies = [ 203 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 204 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 205 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 206 | ] 207 | 208 | [[package]] 209 | name = "daemonize" 210 | version = "0.4.1" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | dependencies = [ 213 | "boxfnonce 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 214 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 215 | ] 216 | 217 | [[package]] 218 | name = "env_logger" 219 | version = "0.7.1" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | dependencies = [ 222 | "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", 223 | "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 224 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 225 | "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 226 | "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 227 | ] 228 | 229 | [[package]] 230 | name = "fuchsia-zircon" 231 | version = "0.3.3" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | dependencies = [ 234 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 235 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 236 | ] 237 | 238 | [[package]] 239 | name = "fuchsia-zircon-sys" 240 | version = "0.3.3" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | 243 | [[package]] 244 | name = "futures" 245 | version = "0.3.1" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | dependencies = [ 248 | "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 249 | "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 250 | "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 251 | "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 252 | "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 253 | "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 254 | "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 255 | ] 256 | 257 | [[package]] 258 | name = "futures-channel" 259 | version = "0.3.1" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | dependencies = [ 262 | "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 263 | "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 264 | ] 265 | 266 | [[package]] 267 | name = "futures-channel-preview" 268 | version = "0.3.0-alpha.19" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | dependencies = [ 271 | "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 272 | "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 273 | ] 274 | 275 | [[package]] 276 | name = "futures-core" 277 | version = "0.3.1" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | 280 | [[package]] 281 | name = "futures-core-preview" 282 | version = "0.3.0-alpha.19" 283 | source = "registry+https://github.com/rust-lang/crates.io-index" 284 | 285 | [[package]] 286 | name = "futures-executor" 287 | version = "0.3.1" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | dependencies = [ 290 | "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 291 | "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 292 | "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 293 | ] 294 | 295 | [[package]] 296 | name = "futures-io" 297 | version = "0.3.1" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | 300 | [[package]] 301 | name = "futures-macro" 302 | version = "0.3.1" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | dependencies = [ 305 | "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", 306 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 307 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 308 | "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 309 | ] 310 | 311 | [[package]] 312 | name = "futures-sink" 313 | version = "0.3.1" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | 316 | [[package]] 317 | name = "futures-sink-preview" 318 | version = "0.3.0-alpha.19" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | 321 | [[package]] 322 | name = "futures-task" 323 | version = "0.3.1" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | 326 | [[package]] 327 | name = "futures-timer" 328 | version = "2.0.2" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | 331 | [[package]] 332 | name = "futures-util" 333 | version = "0.3.1" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | dependencies = [ 336 | "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 337 | "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 338 | "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 339 | "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 340 | "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 341 | "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 342 | "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 343 | "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", 344 | "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", 345 | "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 346 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 347 | ] 348 | 349 | [[package]] 350 | name = "futures-util-preview" 351 | version = "0.3.0-alpha.19" 352 | source = "registry+https://github.com/rust-lang/crates.io-index" 353 | dependencies = [ 354 | "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 355 | "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", 356 | "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", 357 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 358 | ] 359 | 360 | [[package]] 361 | name = "getrandom" 362 | version = "0.1.13" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | dependencies = [ 365 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 366 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 367 | "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 368 | ] 369 | 370 | [[package]] 371 | name = "gkd" 372 | version = "0.1.0" 373 | dependencies = [ 374 | "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 375 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 376 | "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", 377 | "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 378 | "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 379 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 380 | ] 381 | 382 | [[package]] 383 | name = "hermit-abi" 384 | version = "0.1.3" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | dependencies = [ 387 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 388 | ] 389 | 390 | [[package]] 391 | name = "httparse" 392 | version = "1.3.4" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | 395 | [[package]] 396 | name = "humantime" 397 | version = "1.3.0" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | dependencies = [ 400 | "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 401 | ] 402 | 403 | [[package]] 404 | name = "iovec" 405 | version = "0.1.4" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | dependencies = [ 408 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 409 | ] 410 | 411 | [[package]] 412 | name = "itoa" 413 | version = "0.4.4" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | 416 | [[package]] 417 | name = "kernel32-sys" 418 | version = "0.2.2" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | dependencies = [ 421 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 422 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 423 | ] 424 | 425 | [[package]] 426 | name = "kv-log-macro" 427 | version = "1.0.4" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | dependencies = [ 430 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 431 | ] 432 | 433 | [[package]] 434 | name = "lazy_static" 435 | version = "1.4.0" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | 438 | [[package]] 439 | name = "libc" 440 | version = "0.2.66" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | 443 | [[package]] 444 | name = "lock_api" 445 | version = "0.3.2" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | dependencies = [ 448 | "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 449 | ] 450 | 451 | [[package]] 452 | name = "log" 453 | version = "0.4.8" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | dependencies = [ 456 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 457 | ] 458 | 459 | [[package]] 460 | name = "maybe-uninit" 461 | version = "2.0.0" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | 464 | [[package]] 465 | name = "memchr" 466 | version = "2.2.1" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | 469 | [[package]] 470 | name = "memoffset" 471 | version = "0.5.3" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | dependencies = [ 474 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 475 | ] 476 | 477 | [[package]] 478 | name = "miniproxy" 479 | version = "0.1.0" 480 | dependencies = [ 481 | "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 482 | "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 483 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 484 | "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", 485 | "daemonize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 486 | "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 487 | "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 488 | "gkd 0.1.0", 489 | "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 490 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 491 | "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 492 | "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", 493 | "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", 494 | ] 495 | 496 | [[package]] 497 | name = "mio" 498 | version = "0.6.21" 499 | source = "registry+https://github.com/rust-lang/crates.io-index" 500 | dependencies = [ 501 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 502 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 503 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 504 | "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 505 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 506 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 507 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 508 | "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 509 | "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 510 | "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 511 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 512 | ] 513 | 514 | [[package]] 515 | name = "mio-uds" 516 | version = "0.6.7" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | dependencies = [ 519 | "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 520 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 521 | "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", 522 | ] 523 | 524 | [[package]] 525 | name = "miow" 526 | version = "0.2.1" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | dependencies = [ 529 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 530 | "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", 531 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 532 | "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 533 | ] 534 | 535 | [[package]] 536 | name = "net2" 537 | version = "0.2.33" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | dependencies = [ 540 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 541 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 542 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 543 | ] 544 | 545 | [[package]] 546 | name = "num_cpus" 547 | version = "1.11.1" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | dependencies = [ 550 | "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 551 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 552 | ] 553 | 554 | [[package]] 555 | name = "once_cell" 556 | version = "1.2.0" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | 559 | [[package]] 560 | name = "parking_lot" 561 | version = "0.9.0" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | dependencies = [ 564 | "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 565 | "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 566 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 567 | ] 568 | 569 | [[package]] 570 | name = "parking_lot_core" 571 | version = "0.6.2" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | dependencies = [ 574 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 575 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 576 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 577 | "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 578 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 579 | "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", 580 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 581 | ] 582 | 583 | [[package]] 584 | name = "pin-project-lite" 585 | version = "0.1.1" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | 588 | [[package]] 589 | name = "pin-utils" 590 | version = "0.1.0-alpha.4" 591 | source = "registry+https://github.com/rust-lang/crates.io-index" 592 | 593 | [[package]] 594 | name = "ppv-lite86" 595 | version = "0.2.6" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | 598 | [[package]] 599 | name = "proc-macro-hack" 600 | version = "0.5.11" 601 | source = "registry+https://github.com/rust-lang/crates.io-index" 602 | dependencies = [ 603 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 604 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 605 | "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 606 | ] 607 | 608 | [[package]] 609 | name = "proc-macro-nested" 610 | version = "0.1.3" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | 613 | [[package]] 614 | name = "proc-macro2" 615 | version = "1.0.6" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | dependencies = [ 618 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 619 | ] 620 | 621 | [[package]] 622 | name = "quick-error" 623 | version = "1.2.2" 624 | source = "registry+https://github.com/rust-lang/crates.io-index" 625 | 626 | [[package]] 627 | name = "quote" 628 | version = "1.0.2" 629 | source = "registry+https://github.com/rust-lang/crates.io-index" 630 | dependencies = [ 631 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 632 | ] 633 | 634 | [[package]] 635 | name = "rand" 636 | version = "0.7.2" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | dependencies = [ 639 | "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 640 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 641 | "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 642 | "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 643 | "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 644 | ] 645 | 646 | [[package]] 647 | name = "rand_chacha" 648 | version = "0.2.1" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | dependencies = [ 651 | "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 652 | "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 653 | ] 654 | 655 | [[package]] 656 | name = "rand_core" 657 | version = "0.5.1" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | dependencies = [ 660 | "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 661 | ] 662 | 663 | [[package]] 664 | name = "rand_hc" 665 | version = "0.2.0" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | dependencies = [ 668 | "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 669 | ] 670 | 671 | [[package]] 672 | name = "redox_syscall" 673 | version = "0.1.56" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | 676 | [[package]] 677 | name = "regex" 678 | version = "1.3.1" 679 | source = "registry+https://github.com/rust-lang/crates.io-index" 680 | dependencies = [ 681 | "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", 682 | "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 683 | "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", 684 | "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 685 | ] 686 | 687 | [[package]] 688 | name = "regex-syntax" 689 | version = "0.6.12" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | 692 | [[package]] 693 | name = "rustc_version" 694 | version = "0.2.3" 695 | source = "registry+https://github.com/rust-lang/crates.io-index" 696 | dependencies = [ 697 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 698 | ] 699 | 700 | [[package]] 701 | name = "ryu" 702 | version = "1.0.2" 703 | source = "registry+https://github.com/rust-lang/crates.io-index" 704 | 705 | [[package]] 706 | name = "scopeguard" 707 | version = "1.0.0" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | 710 | [[package]] 711 | name = "semver" 712 | version = "0.9.0" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | dependencies = [ 715 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 716 | ] 717 | 718 | [[package]] 719 | name = "semver-parser" 720 | version = "0.7.0" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | 723 | [[package]] 724 | name = "serde" 725 | version = "1.0.103" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | dependencies = [ 728 | "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", 729 | ] 730 | 731 | [[package]] 732 | name = "serde_derive" 733 | version = "1.0.103" 734 | source = "registry+https://github.com/rust-lang/crates.io-index" 735 | dependencies = [ 736 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 737 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 738 | "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 739 | ] 740 | 741 | [[package]] 742 | name = "serde_json" 743 | version = "1.0.44" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | dependencies = [ 746 | "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 747 | "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 748 | "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", 749 | ] 750 | 751 | [[package]] 752 | name = "slab" 753 | version = "0.4.2" 754 | source = "registry+https://github.com/rust-lang/crates.io-index" 755 | 756 | [[package]] 757 | name = "smallvec" 758 | version = "0.6.13" 759 | source = "registry+https://github.com/rust-lang/crates.io-index" 760 | dependencies = [ 761 | "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 762 | ] 763 | 764 | [[package]] 765 | name = "strsim" 766 | version = "0.8.0" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | 769 | [[package]] 770 | name = "syn" 771 | version = "1.0.11" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | dependencies = [ 774 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 775 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 776 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 777 | ] 778 | 779 | [[package]] 780 | name = "termcolor" 781 | version = "1.0.5" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | dependencies = [ 784 | "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 785 | ] 786 | 787 | [[package]] 788 | name = "textwrap" 789 | version = "0.11.0" 790 | source = "registry+https://github.com/rust-lang/crates.io-index" 791 | dependencies = [ 792 | "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 793 | ] 794 | 795 | [[package]] 796 | name = "thread_local" 797 | version = "0.3.6" 798 | source = "registry+https://github.com/rust-lang/crates.io-index" 799 | dependencies = [ 800 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 801 | ] 802 | 803 | [[package]] 804 | name = "unicode-width" 805 | version = "0.1.7" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | 808 | [[package]] 809 | name = "unicode-xid" 810 | version = "0.2.0" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | 813 | [[package]] 814 | name = "vec_map" 815 | version = "0.8.1" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | 818 | [[package]] 819 | name = "wasi" 820 | version = "0.7.0" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | 823 | [[package]] 824 | name = "winapi" 825 | version = "0.2.8" 826 | source = "registry+https://github.com/rust-lang/crates.io-index" 827 | 828 | [[package]] 829 | name = "winapi" 830 | version = "0.3.8" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | dependencies = [ 833 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 834 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 835 | ] 836 | 837 | [[package]] 838 | name = "winapi-build" 839 | version = "0.1.1" 840 | source = "registry+https://github.com/rust-lang/crates.io-index" 841 | 842 | [[package]] 843 | name = "winapi-i686-pc-windows-gnu" 844 | version = "0.4.0" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | 847 | [[package]] 848 | name = "winapi-util" 849 | version = "0.1.2" 850 | source = "registry+https://github.com/rust-lang/crates.io-index" 851 | dependencies = [ 852 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 853 | ] 854 | 855 | [[package]] 856 | name = "winapi-x86_64-pc-windows-gnu" 857 | version = "0.4.0" 858 | source = "registry+https://github.com/rust-lang/crates.io-index" 859 | 860 | [[package]] 861 | name = "wincolor" 862 | version = "1.0.2" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | dependencies = [ 865 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 866 | "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 867 | ] 868 | 869 | [[package]] 870 | name = "ws2_32-sys" 871 | version = "0.2.1" 872 | source = "registry+https://github.com/rust-lang/crates.io-index" 873 | dependencies = [ 874 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 875 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 876 | ] 877 | 878 | [metadata] 879 | "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" 880 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 881 | "checksum async-attributes 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "efd3d156917d94862e779f356c5acae312b08fd3121e792c857d7928c8088423" 882 | "checksum async-macros 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "644a5a8de80f2085a1e7e57cd1544a2a7438f6e003c0790999bd43b92a77cdb2" 883 | "checksum async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "513ee3c49800679a319912340f5601afda9e72848d7dea3a48bab489e8c1a46f" 884 | "checksum async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de6bd58f7b9cc49032559422595c81cbfcf04db2f2133592f70af19e258a1ced" 885 | "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" 886 | "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" 887 | "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" 888 | "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 889 | "checksum boxfnonce 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426" 890 | "checksum broadcaster 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "07a1446420a56f1030271649ba0da46d23239b3a68c73591cea5247f15a788a0" 891 | "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" 892 | "checksum bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38" 893 | "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" 894 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 895 | "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" 896 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 897 | "checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" 898 | "checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" 899 | "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" 900 | "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" 901 | "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" 902 | "checksum daemonize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70c24513e34f53b640819f0ac9f705b673fcf4006d7aab8778bee72ebfc89815" 903 | "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" 904 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 905 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 906 | "checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" 907 | "checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" 908 | "checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" 909 | "checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" 910 | "checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" 911 | "checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" 912 | "checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" 913 | "checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" 914 | "checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" 915 | "checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" 916 | "checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" 917 | "checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" 918 | "checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" 919 | "checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" 920 | "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" 921 | "checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" 922 | "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" 923 | "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" 924 | "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" 925 | "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" 926 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 927 | "checksum kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" 928 | "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 929 | "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" 930 | "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" 931 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 932 | "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" 933 | "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" 934 | "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" 935 | "checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" 936 | "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" 937 | "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 938 | "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" 939 | "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" 940 | "checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" 941 | "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" 942 | "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" 943 | "checksum pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" 944 | "checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" 945 | "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" 946 | "checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" 947 | "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" 948 | "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" 949 | "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" 950 | "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 951 | "checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" 952 | "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" 953 | "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 954 | "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 955 | "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" 956 | "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" 957 | "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" 958 | "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 959 | "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" 960 | "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" 961 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 962 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 963 | "checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" 964 | "checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" 965 | "checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" 966 | "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 967 | "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" 968 | "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 969 | "checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" 970 | "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" 971 | "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 972 | "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" 973 | "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" 974 | "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 975 | "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 976 | "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" 977 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 978 | "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" 979 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 980 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 981 | "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" 982 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 983 | "checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" 984 | "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 985 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "miniproxy" 3 | version = "0.1.0" 4 | authors = ["importcjj "] 5 | edition = "2018" 6 | 7 | [[bin]] 8 | name = "minilocal" 9 | path = "src/bin/local.rs" 10 | 11 | [[bin]] 12 | name = "miniserver" 13 | path = "src/bin/server.rs" 14 | 15 | [target.'cfg(not(windows))'.dependencies] 16 | daemonize = "0.4.1" 17 | 18 | [features] 19 | default = ["gkd"] 20 | 21 | [dependencies] 22 | byteorder = "1.3.2" 23 | httparse = "1.3.4" 24 | serde = {version = "1.0.0", features=["derive"]} 25 | serde_json = "1.0.0" 26 | log = "0.4.0" 27 | env_logger = "0.7.1" 28 | clap = "2.33.0" 29 | base64 = "0.11.0" 30 | rand = "0.7.2" 31 | # gkd = { version = "0.1.0", git = "https://github.com/importcjj/gkd-rs", optional = true} 32 | gkd = { version = "0.1.0", path = "../gkd-rs", optional = true} 33 | 34 | [dependencies.futures] 35 | version = "0.3" 36 | features = ["async-await"] 37 | 38 | [dependencies.async-std] 39 | version = "1.2" 40 | features = ["unstable"] 41 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # miniproxy 2 | 3 | > 1.39 stable终于发布啦! 4 | 5 | 使用Rust 1.39.0实现的简易代理,同时支持HTTP,HTTPS和SOCKS5协议。本项目仅用于学习交流。 6 | 7 | ## 如何编译 8 | 9 | 首先安装Rust,如何安装请移步[官网](https://www.rust-lang.org/learn/get-started) 10 | 注意由于需要使用async/await,所以需要指定rust版本为1.39(stable) 11 | 12 | ```sh 13 | cargo build --release 14 | ``` 15 | 16 | 默认开启TCP加速,使用[gkd-rs](https://github.com/importcjj/gkd-rs)提供加速功能。 17 | 可在编译时使用--no-default-features关闭加速功能。 18 | 19 | 二进制文件会在项目目录的target/release文件夹下,找到两个名为`minilocal`和`miniserver`的二进制文件即可。关于如何交叉编译,请自行搜索。不过我自己在macbook上交叉编译就没成功过。 20 | 21 | ## 如何使用 22 | 23 | 本代理分为两部分:`minilocal`和`miniserver`。`miniserver`运行于网络服务器上,`minilocal`运行于本地。 24 | 25 | a. 先在服务器上部署`miniserver`,启动的时候会随机产生一个base64编码的密码 26 | 27 | ``` 28 | RUST_LOG=mini=info ./miniserver -h 0.0.0.0 -p 59999 -d 29 | ``` 30 | 31 | b. 然后在本地启动`minilocal`,需要指定server的通讯密码 32 | 33 | ``` 34 | RUST_LOG=mini=info ./minilocal -s "xxx.xx.xx.xx:59999" -p 9998 -P xxxxxx 35 | ``` 36 | 37 | c. 进行系统代理设定,代理地址为`127.0.0.0:9998`,或者也可以设置自动代理,PAC文件地址为`http://127.0.0.1:9998/pac`。本代理同时支持HTTP,HTTPS和SOCKS5协议 38 | 39 | ## 原理及教程 40 | 41 | 尚在编写中,文档可见[docs](./docs) 42 | 43 | -------------------------------------------------------------------------------- /docs/SOCKS5协议.md: -------------------------------------------------------------------------------- 1 | # SOCKS5协议 2 | 3 | > SOCKS是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递。SOCKS是"SOCKetS"的缩写 4 | 5 | SOCKS的最小协议是版本5,与4相比,增加支持UDP,验证,以及IPv6。 6 | 7 | ## 基本原理 8 | 9 | 当防火墙后的客户端要访问外部的服务器时,要先和SOCKS代理服务器连接。通过鉴权之后,将外部服务器的地址告知代理服务器,代理服务器在建立与外部服务器的连接后,会将客户端的请求发往该外部服务器,并将外部服务器的响应结果返回给客户端。 10 | 11 | 本次教程将使用[async-std](https://docs.rs/async-std/1.4.0/async_std/)来完成网络部分的功能,所以文字中可能涉及相关代码。 12 | 13 | ## 过程图解 14 | 15 | ![socks5.png](socks5.png) 16 | 17 | 18 | 19 | ## 协议详解 20 | 21 | 1. 客户端在创建与SOCKS5服务器的TCP连接后,需要先发送请求的协议版本及认证方式,格式为(单位:字节): 22 | 23 | | VER | NMETHODS | METHODS | 24 | | ---- | -------- | ------- | 25 | | 1 | 1 | 1 | 26 | 27 | * VER是SOCKS版本,SOCKS5就是0x05 28 | * NMETHOS是METHODS部分的长度 29 | * METHODS是客户端支持的认证方式列表,每个方法占一字节。目前有L 30 | * 0x00 不需要认证 31 | * 0x01 GSSAPI 32 | * 0x02 用户名,密码认证 33 | * 0x03 - 0x7F 由IANA分配 34 | * 0x80 - 0xFE 为个人保留方法 35 | * 0xFF 无可接受的方法 36 | 37 | 38 | 2. 服务器从客户端提供的方法中选择一个并通过以下格式告知客户端: 39 | 40 | | VER | METHOD | 41 | | ---- | ------ | 42 | | 1 | 1 | 43 | 44 | * VER是SOCKS版本,SOCKS5就是0x05 45 | * METHOD是服务端选中的方法。如果返回0xFF表示没有一个认证方法被选中,客户端需要关闭连接。 46 | 47 | 48 | 3. 进行用户名,密码的认证时,客户端需要通过以下格式将用户名和密码发送给服务器: 49 | 50 | | VER | ULEN | UNAME | PLEN | PASSWD | 51 | | ---- | ---- | ----- | ---- | ------ | 52 | | 1 | 1 | 1-255 | 1 | 1-255 | 53 | 54 | * VER为认证的版本,SOCKS5请使用0x01 55 | * ULEN是用户名的长度 56 | * UNAME是用户名 57 | * PLEN是密码的长度 58 | * PASSWD是密码 59 | 60 | 61 | 62 | 4. 服务端完成用户名,密码的认证后,需要将认证结果通过以下格式发送给客户端: 63 | 64 | | VER | STATUS | | 65 | | ---- | ------ | ---- | 66 | | 1 | 1 | | 67 | 68 | * VER为认证的版本,SOCKS5请使用0x01 69 | * STATUS为认证结果,0x00表示认证成功,其他任意值视为认证失败,客户端需要关闭连接。 70 | 71 | 5. 客户端在完成认证后要发送请求,请求的格式如下: 72 | 73 | | VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | 74 | | ---- | ---- | ---- | ---- | -------- | -------- | 75 | | 1 | 1 | 0x00 | 1 | Variable | 2 | 76 | 77 | * VER是SOCKS版本,SOCKS5就是0x05 78 | * CMD为具体命令: 79 | * 0x01:CONNECT 80 | * 0x02:BIND 81 | * 0x03:UDP转发 82 | 83 | * RSV:保留字段 84 | * ATYP:地址的类型 85 | * 0x01:IPv4地址 86 | * 0x03:域名 87 | * 0x04:IPv6地址 88 | * DST.ADDR:目标地址 89 | * IPv4地址为4字节 90 | * 域名格式为1字节长度后跟1-255字节的域名 91 | * IPv6地址为16字节 92 | * DST.PORT:目标端口,为网络字节序 93 | 94 | 6. 服务器响应客户端请求,响应格式如下: 95 | 96 | | VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | 97 | | ---- | ---- | ---- | ---- | -------- | -------- | 98 | | 1 | 1 | 0x00 | 1 | Variable | 2 | 99 | 100 | * VER是SOCKS版本,SOCKS5就是0x05 101 | * REP是响应字段: 102 | * 0x00:成功 103 | * 0x01:服务器错误 104 | * 0x02:规则禁止 105 | * 0x03:网络不可达 106 | * 0x04:主机不可达 107 | * 0x05:连接被拒 108 | * 0x06: TTL超时 109 | * 0x07:不支持的命令 110 | * 0x08:不支持的地址类型 111 | * 0x09 - 0xFF:尚未定义 112 | 113 | * RSV:保留字段 114 | * ATYP:地址的类型 115 | * 0x01:IPv4地址 116 | * 0x03:域名 117 | * 0x04:IPv6地址 118 | * DST.ADDR:服务器绑定地址 119 | * DST.PORT:服务器绑定端口,为网络字节序 120 | 121 | 在完成了这些操作之后,就可以开始传输数据了。在下一篇文章中,我们一起使用async-std完成一个简单的无认证的SOCKS5客户端和服务器。 122 | -------------------------------------------------------------------------------- /docs/socks5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/importcjj/rust-miniproxy/303a69fd23539157b5ea9ffa40063d4404f27bed/docs/socks5.png -------------------------------------------------------------------------------- /docs/前期准备.md: -------------------------------------------------------------------------------- 1 | ## Rust的简单介绍 2 | 3 | 如果你只是对Rust感兴趣而并没有真正开始学习的话,还是建议先去学习下Rust的基本使用后,再来阅读这个系列。 4 | 在本项目中会使用async/await的特性,这需要1.39以上的Rust版本。我们需要预先准备好Rust的1.39版本 5 | 6 | ## 初始化项目 7 | 8 | 我们先试用Rust自带的包管理工具Cargo初始化一个项目。运行命令`cargo new myproxy`会得到一个初始的项目目录。大致如下 9 | 10 | ``` 11 | . 12 | ├── src 13 | │ └── main.rs 14 | ├── Cargo.lock 15 | └── Cargo.toml 16 | ``` 17 | 18 | #### 添加依赖 19 | 20 | ``` 21 | [dependencies] 22 | byteorder = "1.3.2" 23 | 24 | [dependencies.futures] 25 | version = "0.3" 26 | features = ["compat"] 27 | 28 | [dependencies.async-std] 29 | version = "0.99" 30 | features = ["unstable"] 31 | ``` 32 | 33 | `futures`是Rust中的异步抽象库,它将异步操作抽象成了Future。Future类似于Javascript中的Promise,当Future就绪时会返回结果。 34 | 这里选择将使用futures 0.3来配合async/await使用。另外,还需要借助`async-std`来进行所需的异步网络IO。 35 | -------------------------------------------------------------------------------- /docs/加密.md: -------------------------------------------------------------------------------- 1 | `minilocal`和`miniserver`的之间的通信应该采用加密的方式,这是为了防止网络请求的部分明文信息被第三方发现。 -------------------------------------------------------------------------------- /docs/原理.md: -------------------------------------------------------------------------------- 1 | 2 | 手把手教你用Rust写简易Proxy(一) 3 | 4 | ## 什么是代理? 5 | 6 | 客户端与服务器之前通讯时,需要经过中间的网络终端中转,这个中间的服务器就是代理服务器。 7 | 8 | ## 代理的功能? 9 | 10 | > 以下内容摘自网络百科 11 | 12 | 提供代理服务的计算机系统或其它类型的网络终端称为代理服务器(英文:Proxy Server)。一个完整的代理请求过程为:客户端首先与代理服务器创建连接,接着根据代理服务器所使用的代理协议,请求对目标服务器创建连接、或者获得目标服务器的指定资源(如:文件)。在后一种情况中,代理服务器可能对目标服务器的资源下载至本地缓存,如果客户端所要获取的资源在代理服务器的缓存之中,则代理服务器并不会向目标服务器发送请求,而是直接传回已缓存的资源。一些代理协议允许代理服务器改变客户端的原始请求、目标服务器的原始响应,以满足代理协议的需要。代理服务器的选项和设置在计算机程序中,通常包括一个“防火墙”,允许用户输入代理地址,它会遮盖他们的网络活动,可以允许绕过互联网过滤实现网络访问。 13 | 14 | 代理服务器的基本行为就是接收客户端发送的请求后转发给其他服务器。代理不改变请求URI,会直接发送给前方持有资源的目标服务器。 15 | 16 | 17 | ## 代理协议有哪些? 18 | 19 | 本系列中只涉及几种常用的协议 20 | 21 | * SOCKS5 22 | * HTTP代理 23 | * HTTPS代理 24 | 25 | ## 这些代理协议存在什么问题? 26 | 27 | 这些代理协议在通讯或者建立通讯的时候存在明文传输的情况,所以使用时可能会被网络提供者监测。这样的话就存在一定的隐私泄露问题。比如你通过HTTPS代理服务器访问pornhub时,由于浏览器会先发出一个CONNECT请求,报文内容中会包含pornhub服务器的地址。网管就会知道你在逛什么网站了。 28 | 29 | 那么该如何解决这一问题呢?有人就提出将代理服务器分成两部分,程序A运行在用户本地,它支持常规的代理协议,另一部分程序B运行在我们的服务器上。A和B之间的通讯采用我们自己定义的协议及加密方式。这样一来我们的网络访问请求将变得非常隐秘,不容易被识别。 30 | 31 | 综上所述,整个代理结构如下: 32 | 33 | ![图A](../images/a.png) -------------------------------------------------------------------------------- /docs/部署.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/importcjj/rust-miniproxy/303a69fd23539157b5ea9ffa40063d4404f27bed/docs/部署.md -------------------------------------------------------------------------------- /docs/配置.md: -------------------------------------------------------------------------------- 1 | minilocal和miniserver在启动时除了可以单独指定某项配置外,还应当允许用户指定配置文件。目前流行的配置文件格式有很多,例如:YAML、TOML、JSON等。这里我们钦点JSON作为配置文件的格式。 2 | 3 | 在RUST中最常用的JSON解析库是serde_json。我们将server和local的配置分别定义成如下两个struct。 4 | 5 | ```rust 6 | #[derive(Serialize, Deserialize, Debug)] 7 | pub struct LocalConfig { 8 | pub host: Option, 9 | pub port: Option, 10 | pub server: Option, 11 | } 12 | 13 | #[derive(Serialize, Deserialize, Debug)] 14 | pub struct ServerConfig { 15 | pub host: Option, 16 | pub port: Option, 17 | } 18 | ``` 19 | 20 | 使用`Option`是为了允许配置项缺省。接着我们需要分别为这两个struct实现Default trait,以及load_from_file方法。程序配置的配置读取逻辑时,如果用户指定了配置文件,将尝试从配置文件中读取配置,读取失败,程序报错并离开。若用户没有指定配置文件,则使用默认配置。最后读取命令行中单独指定的配置项,覆盖配置文件中对应的配置项。 -------------------------------------------------------------------------------- /images/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /images/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/importcjj/rust-miniproxy/303a69fd23539157b5ea9ffa40063d4404f27bed/images/a.png -------------------------------------------------------------------------------- /src/bin/local.rs: -------------------------------------------------------------------------------- 1 | use async_std::task; 2 | use clap::{App, Arg}; 3 | use log::error; 4 | use miniproxy::config::LocalConfig; 5 | use miniproxy::daemon::set_daemon; 6 | use miniproxy::local::run_local; 7 | const LOCAL_NAME: &'static str = "minilocal"; 8 | 9 | fn main() { 10 | env_logger::init(); 11 | let matches = App::new(LOCAL_NAME) 12 | .version(env!("CARGO_PKG_VERSION")) 13 | .arg( 14 | Arg::with_name("host") 15 | .short("h") 16 | .long("host") 17 | .value_name("HOST") 18 | .help("host"), 19 | ) 20 | .arg( 21 | Arg::with_name("port") 22 | .short("p") 23 | .long("port") 24 | .value_name("PORT") 25 | .help("port"), 26 | ) 27 | .arg( 28 | Arg::with_name("server") 29 | .short("s") 30 | .long("server") 31 | .value_name("SERVER") 32 | .help("server address"), 33 | ) 34 | .arg( 35 | Arg::with_name("password") 36 | .short("P") 37 | .long("password") 38 | .value_name("PASSWORD") 39 | .help("ciper password"), 40 | ) 41 | .arg(Arg::with_name("daemon").short("d").help("daemonize")) 42 | .arg( 43 | Arg::with_name("config") 44 | .short("c") 45 | .long("config") 46 | .value_name("CONFIG") 47 | .help("config path"), 48 | ) 49 | .get_matches(); 50 | 51 | let daemonize = matches.is_present("daemon"); 52 | let mut config = match matches.value_of("config") { 53 | Some(path) => match LocalConfig::load_from_file(path) { 54 | Ok(config) => config, 55 | Err(e) => { 56 | error!("{:?}", e); 57 | return; 58 | } 59 | }, 60 | None => LocalConfig::default(), 61 | }; 62 | 63 | if let Some(host) = matches.value_of("host") { 64 | config.host = Some(host.to_string()); 65 | } 66 | 67 | if let Some(port) = matches.value_of("port") { 68 | config.port = match port.parse::() { 69 | Ok(port) => Some(port), 70 | Err(e) => { 71 | error!("invalid port {:?}", e); 72 | return; 73 | } 74 | } 75 | } 76 | 77 | if let Some(server) = matches.value_of("server") { 78 | config.server = Some(server.to_string()); 79 | } 80 | 81 | if let Some(password) = matches.value_of("password") { 82 | config.password = Some(password.to_string()); 83 | } 84 | 85 | if config.server.is_none() { 86 | error!("server address required"); 87 | return; 88 | } 89 | 90 | if config.password.is_none() { 91 | error!("password required"); 92 | return; 93 | } 94 | 95 | if daemonize { 96 | set_daemon(LOCAL_NAME); 97 | } 98 | 99 | if let Err(e) = task::block_on(run_local(config)) { 100 | error!("{:?}", e); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/bin/server.rs: -------------------------------------------------------------------------------- 1 | use async_std::task; 2 | use clap::{App, Arg}; 3 | use log::error; 4 | use miniproxy::config::ServerConfig; 5 | use miniproxy::daemon::set_daemon; 6 | use miniproxy::server::run_server; 7 | 8 | const SERVER_NAME: &'static str = "miniserver"; 9 | 10 | fn main() { 11 | env_logger::init(); 12 | let matches = App::new(SERVER_NAME) 13 | .version(env!("CARGO_PKG_VERSION")) 14 | .arg( 15 | Arg::with_name("host") 16 | .short("h") 17 | .long("host") 18 | .value_name("HOST") 19 | .help("host"), 20 | ) 21 | .arg( 22 | Arg::with_name("port") 23 | .short("p") 24 | .long("port") 25 | .value_name("PORT") 26 | .help("port"), 27 | ) 28 | .arg(Arg::with_name("daemon").short("d").help("daemonize")) 29 | .arg( 30 | Arg::with_name("config") 31 | .short("c") 32 | .long("config") 33 | .value_name("CONFIG") 34 | .help("config path"), 35 | ) 36 | .get_matches(); 37 | 38 | let daemonize = matches.is_present("daemon"); 39 | let mut config = match matches.value_of("config") { 40 | Some(ref path) => match ServerConfig::load_from_file(path) { 41 | Ok(config) => config, 42 | Err(e) => { 43 | error!("{:?}", e); 44 | return; 45 | } 46 | }, 47 | None => ServerConfig::default(), 48 | }; 49 | 50 | if let Some(host) = matches.value_of("host") { 51 | config.host = Some(host.to_string()); 52 | } 53 | 54 | if let Some(port) = matches.value_of("port") { 55 | config.port = match port.parse::() { 56 | Ok(port) => Some(port), 57 | Err(e) => { 58 | error!("invalid port {:?}", e); 59 | return; 60 | } 61 | } 62 | } 63 | 64 | if let Some(password) = matches.value_of("password") { 65 | config.password = Some(password.to_string()); 66 | } 67 | 68 | if daemonize { 69 | set_daemon(SERVER_NAME); 70 | } 71 | 72 | if let Err(e) = task::block_on(run_server(config)) { 73 | error!("{:?}", e); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/bin/socket.rs: -------------------------------------------------------------------------------- 1 | use std::net::ToSocketAddrs; 2 | 3 | fn main() { 4 | let a = "google.com:443"; 5 | let b = "baidu.com:443"; 6 | println!("{:?}", a.to_socket_addrs()); 7 | println!("{:?}", b.to_socket_addrs()); 8 | } 9 | -------------------------------------------------------------------------------- /src/ciper.rs: -------------------------------------------------------------------------------- 1 | use async_std::io; 2 | use async_std::io::{Read, Write}; 3 | use async_std::net::TcpStream; 4 | use async_std::pin::Pin; 5 | use async_std::task::{Context, Poll}; 6 | #[cfg(feature = "gkd")] 7 | use gkd::Connection; 8 | use log::debug; 9 | pub struct CiperTcpStream { 10 | #[cfg(feature = "gkd")] 11 | stream: Connection, 12 | #[cfg(not(feature = "gkd"))] 13 | stream: TcpStream, 14 | decode_password: Vec, 15 | encode_password: Vec, 16 | } 17 | 18 | impl CiperTcpStream { 19 | #[cfg(feature = "gkd")] 20 | pub fn new(stream: Connection, encode_password: Vec) -> CiperTcpStream { 21 | let mut decode_password = vec![0; 256]; 22 | for (i, b) in encode_password.iter().enumerate() { 23 | decode_password[*b as usize] = i as u8; 24 | } 25 | Self { 26 | stream, 27 | encode_password, 28 | decode_password, 29 | } 30 | } 31 | #[cfg(not(feature = "gkd"))] 32 | pub fn new(stream: TcpStream, encode_password: Vec) -> CiperTcpStream { 33 | let mut decode_password = vec![0; 256]; 34 | for (i, b) in encode_password.iter().enumerate() { 35 | decode_password[*b as usize] = i as u8; 36 | } 37 | Self { 38 | stream, 39 | encode_password, 40 | decode_password, 41 | } 42 | } 43 | } 44 | 45 | impl Read for CiperTcpStream { 46 | fn poll_read( 47 | self: Pin<&mut Self>, 48 | cx: &mut Context, 49 | buf: &mut [u8], 50 | ) -> Poll> { 51 | Pin::new(&mut &*self).poll_read(cx, buf) 52 | } 53 | } 54 | 55 | impl Read for &CiperTcpStream { 56 | fn poll_read( 57 | self: Pin<&mut Self>, 58 | cx: &mut Context, 59 | buf: &mut [u8], 60 | ) -> Poll> { 61 | // debug!("read"); 62 | match Pin::new(&mut &self.stream).poll_read(cx, buf) { 63 | ok @ Poll::Ready(Ok(_)) => { 64 | for b in buf { 65 | *b = self.decode_password[*b as usize]; 66 | } 67 | ok 68 | } 69 | r @ _ => r, 70 | } 71 | } 72 | } 73 | 74 | impl Write for CiperTcpStream { 75 | fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll> { 76 | Pin::new(&mut &*self).poll_write(cx, buf) 77 | } 78 | 79 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { 80 | Pin::new(&mut &*self).poll_flush(cx) 81 | } 82 | 83 | fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { 84 | Pin::new(&mut &*self).poll_close(cx) 85 | } 86 | } 87 | 88 | impl Write for &CiperTcpStream { 89 | fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll> { 90 | // debug!("write"); 91 | let buf: Vec = buf 92 | .iter() 93 | .map(|b| self.encode_password[*b as usize]) 94 | .collect(); 95 | Pin::new(&mut &self.stream).poll_write(cx, &buf) 96 | } 97 | 98 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { 99 | Pin::new(&mut &self.stream).poll_flush(cx) 100 | } 101 | 102 | fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { 103 | Pin::new(&mut &self.stream).poll_close(cx) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use crate::password; 2 | use crate::Result; 3 | use serde::{Deserialize, Serialize}; 4 | use serde_json; 5 | use std::fs; 6 | 7 | #[derive(Serialize, Deserialize, Debug)] 8 | pub struct LocalConfig { 9 | pub host: Option, 10 | pub port: Option, 11 | pub server: Option, 12 | pub password: Option, 13 | } 14 | 15 | #[derive(Serialize, Deserialize, Debug)] 16 | pub struct ServerConfig { 17 | pub host: Option, 18 | pub port: Option, 19 | pub password: Option, 20 | } 21 | 22 | impl Default for ServerConfig { 23 | fn default() -> Self { 24 | Self { 25 | host: Some("0.0.0.0".to_string()), 26 | port: Some(59999), 27 | password: Some(password::new()), 28 | } 29 | } 30 | } 31 | 32 | impl Default for LocalConfig { 33 | fn default() -> Self { 34 | Self { 35 | host: Some("127.0.0.1".to_string()), 36 | port: Some(9998), 37 | server: None, 38 | password: None, 39 | } 40 | } 41 | } 42 | 43 | impl ServerConfig { 44 | pub fn load_from_file(path: &str) -> Result { 45 | let file = fs::OpenOptions::new().read(true).open(path)?; 46 | let config: ServerConfig = serde_json::from_reader(file)?; 47 | Ok(config) 48 | } 49 | } 50 | 51 | impl LocalConfig { 52 | pub fn load_from_file(path: &str) -> Result { 53 | let file = fs::OpenOptions::new().read(true).open(path)?; 54 | let config: LocalConfig = serde_json::from_reader(file)?; 55 | Ok(config) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/daemon.rs: -------------------------------------------------------------------------------- 1 | use log::{error, info}; 2 | 3 | #[cfg(target_os = "windows")] 4 | pub fn set_daemon(name: &str) { 5 | log::warn!("can't be daemonized on windows yet!"); 6 | } 7 | 8 | #[cfg(not(target_os = "windows"))] 9 | pub fn set_daemon(name: &str) { 10 | use daemonize::Daemonize; 11 | use std::fs::File; 12 | 13 | let stdout = File::create(format!("/tmp/{}.out", name)).unwrap(); 14 | let stderr = File::create(format!("/tmp/{}.err", name)).unwrap(); 15 | 16 | let daemonize = Daemonize::new() 17 | .pid_file(format!("/tmp/{}.pid", name)) // Every method except `new` and `start` 18 | .chown_pid_file(true) // is optional, see `Daemonize` documentation 19 | .working_directory("/tmp") // for default behaviour. 20 | .group("daemon") // Group name 21 | .group(2) // or group id. 22 | .umask(0o777) // Set umask, `0o027` by default. 23 | .stdout(stdout) // Redirect stdout to `/tmp/daemon.out`. 24 | .stderr(stderr) // Redirect stderr to `/tmp/daemon.err`. 25 | .privileged_action(|| "Executed before drop privileges"); 26 | 27 | match daemonize.start() { 28 | Ok(_) => info!("Success, daemonized"), 29 | Err(e) => error!("Error, {}", e), 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod ciper; 2 | pub mod config; 3 | pub mod daemon; 4 | pub mod local; 5 | mod pac; 6 | pub mod password; 7 | pub mod server; 8 | mod socks5; 9 | 10 | use async_std::future::Future; 11 | use async_std::task; 12 | 13 | pub type Result = std::result::Result>; 14 | 15 | fn spawn_and_log_err(fut: F) -> task::JoinHandle<()> 16 | where 17 | F: Future> + Send + 'static, 18 | { 19 | task::spawn(async move { 20 | if let Err(e) = fut.await { 21 | log::error!("conn err: {:?}", e); 22 | } 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /src/local.rs: -------------------------------------------------------------------------------- 1 | use async_std::net::{TcpListener, TcpStream}; 2 | use async_std::prelude::*; 3 | use log::{debug, error, info}; 4 | 5 | use crate::ciper::CiperTcpStream; 6 | use crate::config::LocalConfig; 7 | use crate::pac::serve_pac_file; 8 | use crate::password::decode_password; 9 | use crate::socks5::req_socks5; 10 | use crate::spawn_and_log_err; 11 | use crate::Result; 12 | use async_std::io::{Read, Write}; 13 | use futures::future::FutureExt; 14 | 15 | pub async fn run_local(config: LocalConfig) -> Result<()> { 16 | let addr = format!("{}:{}", config.host.unwrap(), config.port.unwrap()); 17 | let remote_addr = config.server.unwrap(); 18 | let password = config.password.unwrap(); 19 | info!("MINILOCAL listening on {}", addr); 20 | info!("Serve [ HTTP | HTTPS | SOCKS5 ]"); 21 | info!("PAC url http://{}/pac", addr); 22 | 23 | let password = decode_password(&password)?; 24 | 25 | #[cfg(feature = "gkd")] 26 | let gkd_client = { 27 | info!("powered by gkd-rs"); 28 | use gkd::Client; 29 | Client::connect(&remote_addr.clone(), 2).await? 30 | }; 31 | 32 | let server = TcpListener::bind(addr).await?; 33 | while let Some(stream) = server.incoming().next().await { 34 | let stream = stream?; 35 | 36 | #[cfg(feature = "gkd")] 37 | let conn_to_server = gkd_client.get_connection().await?; 38 | #[cfg(not(feature = "gkd"))] 39 | let conn_to_server = TcpStream::connect(remote_addr.clone()).await?; 40 | 41 | let server_stream = CiperTcpStream::new(conn_to_server, password.clone()); 42 | spawn_and_log_err(serve_conn(server_stream, stream)); 43 | } 44 | Ok(()) 45 | } 46 | 47 | async fn serve_conn( 48 | mut server_stream: T, 49 | // conn_to_server: TcpStream, 50 | mut stream: TcpStream, 51 | ) -> Result<()> 52 | where 53 | T: Read + Write + Unpin, 54 | for<'a> &'a T: Read + Write + Unpin, 55 | { 56 | let mut buf = vec![0_u8; 1024]; 57 | let n = stream.read(&mut buf).await?; 58 | 59 | let mut headers = [httparse::EMPTY_HEADER; 16]; 60 | let mut req = httparse::Request::new(&mut headers); 61 | 62 | match req.parse(&buf[0..n]) { 63 | Ok(_) => { 64 | let mut host: Option<&str> = None; 65 | debug!("req {:?}", req); 66 | for h in req.headers { 67 | if h.name == "Host" { 68 | host = Some(std::str::from_utf8(h.value)?); 69 | } 70 | } 71 | let host = match host { 72 | Some(h) => h, 73 | None => { 74 | error!("invalid request"); 75 | return Ok(()); 76 | } 77 | }; 78 | 79 | // Serve pac file 80 | if let Some(path) = req.path { 81 | if path == "/pac" { 82 | return serve_pac_file(stream).await; 83 | } 84 | } 85 | 86 | // Do nothing 87 | if host.contains("127.0.0.1") { 88 | return Ok(()); 89 | } 90 | 91 | info!("{}", host); 92 | 93 | server_stream = req_socks5(server_stream, host).await?; 94 | match req.method { 95 | Some("CONNECT") => { 96 | stream 97 | .write_all("HTTP/1.1 200 Tunnel established\r\n\r\n".as_bytes()) 98 | .await?; 99 | } 100 | _ => { 101 | server_stream.write_all(&buf[..n]).await?; 102 | } 103 | } 104 | } 105 | // 解析失败 则直接理解为socks5代理 106 | Err(_) => { 107 | server_stream.write_all(&buf[..n]).await?; 108 | } 109 | } 110 | 111 | let (lr, lw) = &mut (&stream, &stream); 112 | let (tr, tw) = &mut (&server_stream, &server_stream); 113 | 114 | let copy_a = async_std::io::copy(lr, tw); 115 | let copy_b = async_std::io::copy(tr, lw); 116 | let r = futures::select! { 117 | r1 = copy_a.fuse() => r1, 118 | r2 = copy_b.fuse() => r2 119 | }; 120 | 121 | Ok(()) 122 | } 123 | -------------------------------------------------------------------------------- /src/pac.rs: -------------------------------------------------------------------------------- 1 | use crate::Result; 2 | use async_std::fs; 3 | use async_std::net::TcpStream; 4 | use async_std::prelude::*; 5 | use log::info; 6 | 7 | pub async fn serve_pac_file(mut stream: TcpStream) -> Result<()> { 8 | info!("serve pac file"); 9 | 10 | let file_contents = fs::read("proxy.pac").await?; 11 | 12 | stream.write_all("HTTP/1.1 200 OK\r\n".as_bytes()).await?; 13 | let header_content_length = format!("Content-Length: {}\r\n", file_contents.len()); 14 | stream.write_all(header_content_length.as_bytes()).await?; 15 | stream.write_all("Server: minilocal".as_bytes()).await?; 16 | stream.write_all("Connection: close".as_bytes()).await?; 17 | stream 18 | .write_all("Content-Type: application/x-ns-proxy-autoconfig\r\n".as_bytes()) 19 | .await?; 20 | stream.write_all("\r\n".as_bytes()).await?; 21 | stream.write_all(&file_contents).await?; 22 | 23 | Ok(()) 24 | } 25 | -------------------------------------------------------------------------------- /src/password.rs: -------------------------------------------------------------------------------- 1 | use base64::{self, DecodeError}; 2 | use rand::seq::SliceRandom; 3 | use rand::thread_rng; 4 | 5 | pub fn new() -> String { 6 | let mut rng = thread_rng(); 7 | let mut password: Vec = (0..=255).collect(); 8 | password.shuffle(&mut rng); 9 | 10 | base64::encode(&password) 11 | } 12 | 13 | pub fn decode_password(password: &str) -> Result, DecodeError> { 14 | base64::decode(password) 15 | } 16 | -------------------------------------------------------------------------------- /src/server.rs: -------------------------------------------------------------------------------- 1 | use crate::ciper::CiperTcpStream; 2 | use crate::config::ServerConfig; 3 | use crate::password::decode_password; 4 | use crate::socks5::serve_socks5; 5 | use crate::{spawn_and_log_err, Result}; 6 | use async_std::net::ToSocketAddrs; 7 | use log::info; 8 | 9 | pub async fn run_server(config: ServerConfig) -> Result<()> { 10 | let addr = format!("{}:{}", config.host.unwrap(), config.port.unwrap()); 11 | let password = config.password.unwrap(); 12 | info!("server listening on {}...", addr); 13 | info!("{}", password); 14 | 15 | let password = decode_password(&password)?; 16 | 17 | serve(addr, password).await 18 | } 19 | 20 | #[cfg(feature = "gkd")] 21 | async fn serve(addr: A, ciper_password: Vec) -> Result<()> { 22 | info!("powered by gkd-rs"); 23 | use gkd::Server; 24 | 25 | let server = Server::bind(addr).await?; 26 | while let Some((stream, _)) = server.accept().await { 27 | let stream = CiperTcpStream::new(stream, ciper_password.clone()); 28 | spawn_and_log_err(serve_socks5(stream)); 29 | } 30 | Ok(()) 31 | } 32 | 33 | #[cfg(not(feature = "gkd"))] 34 | async fn serve(addr: A, ciper_password: Vec) -> Result<()> { 35 | use async_std::net::TcpListener; 36 | use async_std::prelude::*; 37 | 38 | let server = TcpListener::bind(addr).await?; 39 | while let Some(stream) = server.incoming().next().await { 40 | let stream = stream?; 41 | let stream = CiperTcpStream::new(stream, ciper_password.clone()); 42 | spawn_and_log_err(serve_socks5(stream)); 43 | } 44 | 45 | Ok(()) 46 | } 47 | -------------------------------------------------------------------------------- /src/socks5.rs: -------------------------------------------------------------------------------- 1 | use async_std::io::{Read, Write}; 2 | use async_std::net::TcpStream; 3 | use async_std::net::ToSocketAddrs; 4 | use async_std::prelude::*; 5 | use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; 6 | use futures::future::FutureExt; 7 | use log::info; 8 | use std::io::Cursor; 9 | use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; 10 | type Result = std::result::Result>; 11 | 12 | pub async fn serve_socks5(mut stream: T) -> Result<()> 13 | where 14 | T: Read + Write + Unpin, 15 | for<'a> &'a T: Read + Write + Unpin, 16 | { 17 | let mut buf = vec![0; 257]; 18 | // SOCK5 协议详见 https://zh.wikipedia.org/wiki/SOCKS#SOCKS5 19 | 20 | // VER NMETHODS METHODS 21 | // 1 1 1-255 22 | // let _n = stream.read(&mut buf).await?; 23 | let _n = stream.read(&mut buf).await?; 24 | 25 | // VER METHOD 26 | // 1 1 27 | stream.write_all(&[0x05_u8, 0x00_u8]).await?; 28 | 29 | // VER CMD RSV ATYP DST.ADDR DST.PORT 30 | // 1 1 0x00 1 动态 2 31 | 32 | let mut buf = vec![0; 1024]; 33 | let n = stream.read(&mut buf).await?; 34 | 35 | match buf[1] { 36 | // 0x01表示CONNECT请求 37 | 0x01 => (), 38 | 0x02 => (), 39 | 0x03 => (), 40 | _ => return Ok(()), 41 | } 42 | 43 | let port = Cursor::new(&buf[n - 2..n]).read_u16::().unwrap(); 44 | 45 | let addr = match buf[3] { 46 | 0x01 => SocketAddr::new( 47 | IpAddr::V4(Ipv4Addr::new(buf[4], buf[5], buf[6], buf[7])), 48 | port, 49 | ), 50 | 0x03 => { 51 | let domain = format!("{}:{}", String::from_utf8_lossy(&buf[5..n - 2]), port); 52 | let mut addrs = domain.to_socket_addrs().await?; 53 | addrs.next().unwrap() 54 | } 55 | 0x04 => SocketAddr::new( 56 | IpAddr::V6(Ipv6Addr::new( 57 | Cursor::new(&buf[4..6]).read_u16::().unwrap(), 58 | Cursor::new(&buf[6..8]).read_u16::().unwrap(), 59 | Cursor::new(&buf[8..10]).read_u16::().unwrap(), 60 | Cursor::new(&buf[10..12]).read_u16::().unwrap(), 61 | Cursor::new(&buf[12..14]).read_u16::().unwrap(), 62 | Cursor::new(&buf[14..16]).read_u16::().unwrap(), 63 | Cursor::new(&buf[16..18]).read_u16::().unwrap(), 64 | Cursor::new(&buf[18..20]).read_u16::().unwrap(), 65 | )), 66 | port, 67 | ), 68 | _ => return Ok(()), 69 | }; 70 | 71 | // VER REP RSV ATYP BND.ADDR BND.PORT 72 | // 1 1 0x00 1 动态 2 73 | 74 | stream.write_all(&[5, 0, 0, 1, 0, 0, 0, 0, 0, 0]).await?; 75 | 76 | // start to proxy. 77 | info!("connecting {:?}", addr); 78 | let target = TcpStream::connect(addr.clone()).await?; 79 | 80 | let (lr, lw) = &mut (&stream, &stream); 81 | let (tr, tw) = &mut (&target, &target); 82 | 83 | let copy_a = async_std::io::copy(lr, tw); 84 | let copy_b = async_std::io::copy(tr, lw); 85 | 86 | futures::select! { 87 | r1 = copy_a.fuse() => r1?, 88 | r2 = copy_b.fuse() => r2? 89 | }; 90 | 91 | Ok(()) 92 | } 93 | 94 | pub async fn req_socks5(mut stream: T, path: &str) -> Result 95 | where 96 | T: Read + Write + Unpin, 97 | { 98 | stream.write_all(&[5, 1, 0]).await?; 99 | stream.read_exact(&mut [0; 2]).await?; 100 | let mut data = vec![5, 1, 0]; 101 | 102 | match path.parse::() { 103 | // IPV4 104 | Ok(SocketAddr::V4(v4)) => { 105 | data.push(0x01); 106 | data.extend_from_slice(&v4.ip().octets()); 107 | data.write_u16::(v4.port()).unwrap(); 108 | } 109 | // IPV6 110 | Ok(SocketAddr::V6(v6)) => { 111 | data.push(0x05); 112 | data.extend_from_slice(&v6.ip().octets()); 113 | data.write_u16::(v6.port()).unwrap(); 114 | } 115 | // domain 116 | Err(_) => { 117 | data.push(0x03); 118 | let mut parts = path.split(":"); 119 | let domain = parts.next().unwrap(); 120 | let port: u16 = parts.next().unwrap_or("80").parse().unwrap(); 121 | data.push(domain.as_bytes().len() as u8); 122 | data.extend_from_slice(domain.as_bytes()); 123 | data.write_u16::(port).unwrap(); 124 | } 125 | } 126 | stream.write_all(&data).await?; 127 | stream.read(&mut [0; 1024]).await?; 128 | 129 | Ok(stream) 130 | } 131 | --------------------------------------------------------------------------------