├── LICENSE
├── README.md
├── client
├── .gitignore
├── index.ts
├── package.json
├── scripts
│ └── live.sh
├── tsconfig.json
└── yarn.lock
└── server
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── flake.lock
├── flake.nix
└── src
├── auth.rs
├── main.rs
├── proxy_http.rs
└── proxy_tls.rs
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright Vir Chaudhury
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # proxy-proxy-proxyer
2 |
3 | A proxyer that proxies HTTP as a proxy request to another proxy through a proxy, which is itself a proxy.
4 |
5 | The only use case I actually know of for this is to bypass restrictive proxies on networks.
6 |
7 | ## Why did you make this?
8 |
9 | Let's say that one day you want to hack on something with a friend, and you decide to try
10 | coding together at one of those new trendy coworking spaces. You bring yourself and your laptop,
11 | amble into the siloed rows of partitioned desks, and sit down at the most convenient one
12 | furthest from the door. You relax back in your chair, take a good gander at the amazing view of
13 | three panels of white drywall, and decide to get cracking before your friend shows up. A charging
14 | cable and wireless connection later, you're staring at a network sign-in screen, telling you to
15 | change your browser proxy settings to 10.10.60.33 port 4438.
16 |
17 | This is maybe about the point at which any sane programmer would get up and leave, but this place was reviewed
18 | as 4.8 stars and it already took you an hour to get here, so surely it can't be that bad, right? I mean,
19 | sure, the proxy is probably monitoring all of your network traffic, but your ISP was doing that anyway,
20 | and that's what HTTPS is for, isn't it? So you decide, well whatever, set your proxy to 10.10.60.33 port 4438, restart your browser,
21 | and open your favourite new tab page. Nothing appears too different, so you open your laptop to GitHub to take a look at the
22 | latest PRs to your hot new open-source project. Rather than GitHub, however, you are presented with an error banner that looks like it was
23 | lifted directly from the Silverlight days:
24 |
25 | ```
26 | Permission Denied
27 |
28 | This webpage (github.com) cannot be displayed due to an error: PERMISSION_DENIED.
29 | Category: Malware Distribution is denied by default.
30 |
31 | Please contact your system administrator for further information.
32 | ```
33 |
34 | The lingering smell of `` aside, you stare in disbelief at the message. Who would block _GitHub?_ For _malware distribution?_ Who even works here? Are all the 5 star reviews from finance people or something?
35 |
36 | But you really don't want to pack your bag; I mean, you've just settled down, and the chair is quite comfortable, true, and the world-class snacks do encourage you to please stay the cause,
37 | maybe you can figure out a way to get around this?
38 |
39 | Option #1: Force HTTPS. Now you just get an insecure error page.
40 |
41 | Option #2: Change the preset DNS. This does absolutely nothing. A couple of tries later, you figure out that _all_ outbound UDP on port 53 is blocked, and you just don't have a DNS server; HTTP proxies resolve the hostname for you.
42 |
43 | Option #3: Don't use the proxy. This does not work either. Turns out that nevermind, it's not just outbound DNS, _all_ outbound traffic is blocked, and you have to go through the proxy to access any page. Oh, and the proxy also only allows connections to external servers on port 80 or 443. Fun.
44 |
45 | Option #4: Direct IP address through the proxy. This does not work; the proxy is not badly implemented.
46 |
47 | This is starting to get annoying. So you've got this proxy, it works perfectly for every site except GitHub, but you really need to access GitHub. If only you could somehow go through the proxy to a _different_ server, that sends you the actual webpage, while also hiding your traffic like HTTPS does, then you could access any site without the proxy knowing. Hmm, the outside server would be a proxy also, no? So that would make this solution a proxy-proxy. Not a bad name, you think.
48 |
49 | Some investigation later, it turns out that for some reason no browser supports proxy-proxying by default. This is sad. Perhaps you could write your own solution? Hmm... well you don't want to modify the browser code, since that's too complicated. What if you made a proxy that runs locally, that then proxies the request to the outside proxy through the network proxy? Then you could just use it as a regular HTTP browser proxy. Hmm... that would be a proxy-proxy-proxy. Maybe a proxy-proxy-proxyer, in fact, since it has to do custom proxying to circumvent the middle proxy. That name's a bit more contrived, but it's fun to say, so whatever, you think.
50 |
51 | And then it also turns out that nobody has coded that before. Why don't people write weird triple nested proxying engines? You really can't imagine why. Oh well, that means it just falls back down to you again. I mean, your friend cancelled last minute on you, so why not do something fun?
52 |
53 | ### How am I going to build this?
54 |
55 | #### Remembering your basics of HTTP proxies
56 |
57 | HTTP proxies have two methods of operation:
58 | 1. HTTP requests (i.e. the insecure method). By this method, in order to send a GET request via HTTP to `http://example.com/some/path` through the `evil-proxy.com` proxy, you send a GET request to `evil-proxy.com` that looks like this:
59 | ```http
60 | GET http://example.com/some/path HTTP/1.1
61 | Host: http://example.com/some/path
62 | # ...more headers...
63 | ```
64 | Yes, your eyes aren't deceiving you. It turns out that's it's perfectly A-OK by the HTTP specification to send a full URI in your request, instead of `GET /some/path HTTP/1.1`. To be fair, most (sane) HTTP server libraries will automatically 400 reject these requests, but when you're implementing a server using very low-level libraries (for example, Rust's `hyper` or Node.js's `http` inbuilt module), you cannot always trust that your GET path will start with a `/`. Be careful out there!
65 | And for other HTTP verbs, like `POST`, `PUT`, whatever, you send the same request to the `evil-proxy.com` server but change the verb. To put it succinctly, in order to send a request to `{location}/{path}` through a proxy, you will send the exact same request to `evil-proxy.com`, except you will rewrite the path parameter from just `/{path}` to be `{location}/{path}` verbatim.
66 |
67 | 2. HTTPS requests. By this method, in order to send _any_ HTTPS request to URL `{location}/{path}` through `evil-proxy.com`, you will send the following HTTP request to `evil-proxy.com`:
68 | ```http
69 | CONNECT {location}:443 HTTP/1.1
70 | Host: {location}:443
71 | ```
72 | The proxy will respond with this if it likes you:
73 | ```http
74 | HTTP/1.1 202 Accepted
75 | ```
76 | And after that you can treat your connection as a direct TCP connection to your target. Go do your TLS ClientHello or whatever. The proxy has essentially turned into a TCP relay proxy.
77 | This is nice because it means that your HTTPS connection is still private _and_ you're still using the proxy.
78 |
79 | Now, if you're smarter than me, you've probably already formed an idea of how you would achieve something like this. Every time the browser wanted to send a HTTP request, the program would send a CONNECT request to `friendly-proxy.net:443`, then send the actual proxy request through the tunnel. This is perfect, you think! So then you would then burn 2 hours implementing a server and client in Node.js, and only then you would discover that while this works to bypass whatever custom proxy server you can find online, this doesn't work with the real proxy you're trying to bypass. What's going on???
80 |
81 | #### Some further investigation
82 |
83 | Hmm... let's spin up the old netcat and try doing the request manually (`>` marks inputted lines, `<` marks responses from the server):
84 | ```
85 | $ cat | sed 's/^> //; s/$/\r/' | nc evil-proxy.com 4438 | sed 's/^/< /'
86 | > CONNECT friendly-proxy.net:443 HTTP/1.1
87 | > Host: friendly-proxy.net:443
88 | >
89 | < HTTP/1.1 202 Accepted
90 | <
91 | > GET http://example.com/ HTTP/1.1
92 | > Host: example.com
93 | >
94 | [connection terminated]
95 | ```
96 |
97 | Huh? What's with the sudden termination??
98 | Direct HTTPS connections to `friendly-proxy.net:443` work, so you're not exactly sure what's... wait, what if this is just DPI?
99 |
100 | #### The Scourge of Deep Packet Inspection (DPI)
101 | I mean, you've _heard_ of DPI. You've read those couple of national security infosec articles that talk about "using DPI" to detect hostile content. But it's always been an ethereal _thing_, somewhere in the latent space of all possible MITM techniques, something that only nations can afford and will pay for. But this might be the very real first time you've encountered DPI in your day-to-day life. Something about this is super unsettling. Your fragile Internet traffic, being pored over and examined, twisted and prod from every angle, just so that the people whose identity and intentions you do not know can deduce faint trails of the data you might be accessing, like expert hunters poring over your tracks in the wilderness, expert hunters which are out to get _you_ in particular.
102 |
103 | Actually it's probably not any of that. It's probably just something like they record the hostname that your browser wants from the TLS server, so that at the end of every month Mr. Bossman can take a look at the graph labeled "aggregated internet traffic of every domain, by percentage" and ask the IT guys pointed questions. Yeah, probably something like that. Probably.
104 |
105 | Well, there's no point in speculating. Probably best to test the hypothesis first.
106 | You first gather the test data by executing the following on your phone (remember, you still don't have proper internet on your laptop):
107 | ```
108 | $ touch sent-by-server
109 | $ tail -f sent-by-server | nc -l 4444 | tee sent-by-client | nc example.com 443 > sent-by-server &
110 | $ curl --connect-to 'example.com:443':'localhost:4444' https://example.com
111 | ```
112 |
113 | You use Bluetooth file transfer to transfer the `sent-by-{client,server}` files to your laptop, which takes _forever_ for some reason, and now you have a snapshot of valid TLS traffic. You use this to set up a test of the proxy:
114 | ```
115 | # on `friendly-proxy.net` (you set the PS1 awhile ago and although you find it more tacky than funny now you also don't feel like changing it):
116 | USER root AT friendly-proxy DIR ~ $ cat sent-by-server | nc -l 443 -v
117 |
118 | # on your laptop:
119 | $ cat | sed 's/$/\r/' > pre-request << EOF
120 | > CONNECT friendly-proxy.net:443 HTTP/1.1
121 | > Host: friendly-proxy.net:443
122 | >
123 | > EOF
124 | $ cat pre-request sent-by-client | nc evil-proxy.net 4438 -v > output-file
125 | $ diff output-file sent-by-server
126 | # no output, so the files do not differ
127 | $
128 | ```
129 | No early request cutoff! So there's definitely at least one thing that the proxy is doing that allows TLS through but not plaintext HTTP. No matter! You can work with this!
130 |
131 | The first packet of the TLS handshake, as you know from... well, you're not actually sure, but somewhere in that deeply wise brain of yours you know this fact, probably sourced from a blogpost or news article which got garbage collected later but the information it gave you was judged valuable enough to keep, leaving behind knowledge that you can't find a source of... anyway, the first packet of the TLS handshake from the client to the server contains a field known as the _Server Name Indication_ (SNI), which specifies which domain the browser is requesting. This is to enable... oh yeah, maybe you got the information from a CDN blogpost or something... anyway, this is to enable servers which host multiple domains to choose the correct respondent for the domain without compromising the security of TLS. The great thing about SNI is that you can use it for this proxying task!
132 |
133 | We just saw before that the evil proxy allowed through the TLS handshake, _despite_ the fact that the `CONNECT` request was for `friendly-proxy.net:443`, and the SNI in the first TLS packet was definitely `example.com` (since that's where the data was captured from!) So therefore the friendly proxy can just parse the browser's SNI packet, look at the SNI, and proxy the HTTPS connection to that SNI port 443! This way, we have traffic that is both (a) TLS-shaped (since it is literally TLS) and (b) proxyable!
134 |
135 | You then proceed to burn another 2 hours implementing this in Node.js.
136 |
137 | #### RIIR
138 |
139 | Finally, everything works! Well, until you notice the latency and decide to change `friendly-proxy.net` for a closer server. You rent the cheapest possible cloud VM you can find that's also in a datacenter near your desk, wow only 250MB of RAM? and then you stick your Node.js server process on it. This works great! You're happy, and so happy in fact that you spin up your favourite intensive full multiplayer web game to cool off after that monumental achievement of 300 lines of code, before noticing that your proxy doesn't work anymore. Huh? You check the server, and see that the proxy server process has been killed because it took too much memory.
140 |
141 | Well then.
142 |
143 | This is probably because you wrote it really inefficiently. But rewriting it to be more efficient so that it won't take up so much memory will involve a full rewrite anyway, so you decide to take the risk and rewrite it in Rust instead, because then surely it will work, right? It does, after another 2 hours of pain. You decide to call it a day here. Who knows, maybe you'll come back to this place tomorrow? The snacks were really good, after all...
144 |
145 | ## Usage
146 |
147 | Please don't actually use this. I wrote this as a proof-of-concept over the course of about six hours. To be specific, here's exactly why you should not use this:
148 | * There is no proper authentication; anyone who is smart enough and also knows your proxy's domain and has found this GitHub repository can abuse your cloud VM as a free proxy. (I mean, there _is_ authentication so that random people can't just take advantage of your free proxy, but it's not very good. I'm not going to talk about how I implemented it, because to be honest I don't want to type it up, and it's pretty easy to break anyway. I don't really have any plans for making this more secure, but feel free to contribute some code if you come across this repository and feel a deep sense of kinship.),
149 | * You can't connect to HTTPS other than on port 443, because SNI does not specify the port. (Or at least, if it does, I haven't implemented it.)
150 | * If you're actually trying to bypass a proxy server, there are probably better solutions you can use. (The reason why I didn't use any of them is that I didn't have any of them installed on my laptop, and I didn't want to waste my minimal mobile data plan on GBs of packages, and also because I wanted to have some fun writing something. I won't list them here but they're naught but a quick search away.)
151 |
152 | But if you really insist, here's how you use this:
153 | 1. Set up a cloud VM that has a public IP that you can listen on. Leave both ports 80 and 443 open.
154 | 2. Run the Rust server binary on the VM: `cd server/; cargo run --release -- --password PUT_A_COMMON_PASSWORD_HERE` (please do not use any actual important password, it just has to be common between the client and server)
155 | 3. Run Node on the client: `cd client/; yarn; yarn build; node ./built/index.js --realProxy REAL_PROXY --proxyPw PUT_A_COMMON_PASSWORD_HERE --thisProxy FRIENDLY_PROXY -p 5000`, where `REAL_PROXY` is the address of the proxy you're trying to bypass (in `{host}:{port}` form), and `FRIENDLY_PROXY` is the address of the friendly proxy out on the wider Internet.
156 | 4. Configure your browser's proxy settings to use `localhost` port 5000 as your proxy.
157 | 5. Rejoice!
158 |
--------------------------------------------------------------------------------
/client/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 | .pnpm-debug.log*
9 |
10 | # Diagnostic reports (https://nodejs.org/api/report.html)
11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/Release
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 |
45 | # Snowpack dependency directory (https://snowpack.dev/)
46 | web_modules/
47 |
48 | # TypeScript cache
49 | *.tsbuildinfo
50 |
51 | # Optional npm cache directory
52 | .npm
53 |
54 | # Optional eslint cache
55 | .eslintcache
56 |
57 | # Optional stylelint cache
58 | .stylelintcache
59 |
60 | # Microbundle cache
61 | .rpt2_cache/
62 | .rts2_cache_cjs/
63 | .rts2_cache_es/
64 | .rts2_cache_umd/
65 |
66 | # Optional REPL history
67 | .node_repl_history
68 |
69 | # Output of 'npm pack'
70 | *.tgz
71 |
72 | # Yarn Integrity file
73 | .yarn-integrity
74 |
75 | # dotenv environment variable files
76 | .env
77 | .env.development.local
78 | .env.test.local
79 | .env.production.local
80 | .env.local
81 |
82 | # parcel-bundler cache (https://parceljs.org/)
83 | .cache
84 | .parcel-cache
85 |
86 | # Next.js build output
87 | .next
88 | out
89 |
90 | # Nuxt.js build / generate output
91 | .nuxt
92 | dist
93 |
94 | # Gatsby files
95 | .cache/
96 | # Comment in the public line in if your project uses Gatsby and not Next.js
97 | # https://nextjs.org/blog/next-9-1#public-directory-support
98 | # public
99 |
100 | # vuepress build output
101 | .vuepress/dist
102 |
103 | # vuepress v2.x temp and cache directory
104 | .temp
105 | .cache
106 |
107 | # Docusaurus cache and generated files
108 | .docusaurus
109 |
110 | # Serverless directories
111 | .serverless/
112 |
113 | # FuseBox cache
114 | .fusebox/
115 |
116 | # DynamoDB Local files
117 | .dynamodb/
118 |
119 | # TernJS port file
120 | .tern-port
121 |
122 | # Stores VSCode versions used for testing VSCode extensions
123 | .vscode-test
124 |
125 | # yarn v2
126 | .yarn/cache
127 | .yarn/unplugged
128 | .yarn/build-state.yml
129 | .yarn/install-state.gz
130 | .pnp
131 |
--------------------------------------------------------------------------------
/client/index.ts:
--------------------------------------------------------------------------------
1 | import { HeaderObject, HTTPParser } from "http-parser-js";
2 | import * as net from "net";
3 | import * as http from "http";
4 | import { parseArgs } from "util";
5 | import { createHash } from "crypto";
6 |
7 | function panic(msg: string): never {
8 | throw new Error("panic: " + msg);
9 | }
10 |
11 | function sha256(s: string): string {
12 | const hash = createHash("sha256");
13 | hash.update(s);
14 | return hash.digest("hex");
15 | }
16 |
17 | // parseResponse {{{
18 |
19 | // Taken and modified from https://github.com/creationix/http-parser-js/blob/master/standalone-example.js.
20 | // Full credit to them for this.
21 | // This is just a slightly modified version of the original parser so we can save the head chunk.
22 | type Response = {
23 | shouldKeepAlive: boolean;
24 | upgrade: boolean;
25 | statusCode: number;
26 | statusMessage: string;
27 | versionMajor: number;
28 | versionMinor: number;
29 | headers: HeaderObject;
30 | body: Buffer;
31 | trailers: string[];
32 | };
33 | export function parseResponse(
34 | input: net.Socket,
35 | cb: (err: any, response: Response, head: Buffer) => void
36 | ) {
37 | // The last chunk sent by the input. Think of this as the "extra" data sent directly after the HTTP request.
38 | // This will clearly contain useful data, so we must pass it on to the callback.
39 | let lastChunk = Buffer.alloc(0),
40 | lastLen = 0;
41 |
42 | const parser = new HTTPParser(HTTPParser.RESPONSE);
43 | let shouldKeepAlive: boolean;
44 | let upgrade: boolean;
45 | let statusCode: number;
46 | let statusMessage: string;
47 | let versionMajor: number;
48 | let versionMinor: number;
49 | let headers: HeaderObject = [];
50 | let trailers: string[] = [];
51 | let bodyChunks: Buffer[] = [];
52 |
53 | const onComplete = () => {
54 | console.log("http Response completed parsing");
55 | input.removeListener("data", listener);
56 | parser.finish();
57 | let body = Buffer.concat(bodyChunks);
58 | const ret = {
59 | shouldKeepAlive,
60 | upgrade,
61 | statusCode,
62 | statusMessage,
63 | versionMajor,
64 | versionMinor,
65 | headers,
66 | body,
67 | trailers,
68 | };
69 | // no error , ret, the head chunk
70 | cb(undefined, ret, lastChunk.subarray(0, lastLen));
71 | };
72 |
73 | parser[HTTPParser.kOnHeadersComplete] = function (res) {
74 | shouldKeepAlive = res.shouldKeepAlive;
75 | upgrade = res.upgrade;
76 | statusCode = res.statusCode;
77 | statusMessage = res.statusMessage;
78 | versionMajor = res.versionMajor;
79 | versionMinor = res.versionMinor;
80 | headers = res.headers;
81 | // we don't care about the body, just do the complete here
82 | onComplete();
83 | };
84 |
85 | // Doesn't parse the body; `parser[HTTPParser.kOnBody]` not set.
86 | // (If we get a response body, that means either we made an invalid request, or the proxy is broken.)
87 |
88 | // Doesn't parse trailers; `parser[HTTPParser.kOnHeaders]` (yes, that is in fact the event for trailers) is not set.
89 | // We don't need this, because again, we don't need the body.
90 |
91 | // We don't listen for the completion event (`parser[HTTPParser.kOnMessageComplete]`).
92 | // It's instead triggered after header-complete.
93 |
94 | const listener = (chunk: Buffer) => {
95 | let lenOrError;
96 | if (typeof (lenOrError = parser.execute(chunk)) !== "number") {
97 | // We got an error, report it
98 | cb(lenOrError, null as any, null as any);
99 | input.removeListener("data", listener);
100 | return;
101 | }
102 | lastLen = lenOrError;
103 | lastChunk = chunk;
104 | };
105 | input.on("data", listener);
106 | }
107 | // }}}
108 |
109 | // argument parsing {{{
110 | const {
111 | values: { realProxyUri, thisProxyUri, proxyPw, port: listenPort },
112 | } = parseArgs({
113 | options: {
114 | realProxyUri: {
115 | type: "string",
116 | short: "r",
117 | },
118 | thisProxyUri: {
119 | type: "string",
120 | short: "t",
121 | },
122 | proxyPw: {
123 | type: "string",
124 | short: "w",
125 | },
126 | port: {
127 | type: "string",
128 | short: "p",
129 | default: "5000",
130 | },
131 | },
132 | });
133 |
134 | try {
135 | // validate args
136 | if (!realProxyUri) throw "need realProxyUri";
137 | if (!thisProxyUri) throw "need thisProxyUri";
138 | if (!proxyPw) throw "need proxyPw (proxy password)";
139 | } catch (e) {
140 | console.error(e);
141 | console.error(`
142 | Usage: -r REAL_PROXY -t THIS_PROXY -w PROXY_PW [-p PORT]
143 |
144 | -r, --realProxyUri: Specifies the location (\`{host}:{port}\` form) of the "real proxy" that you are trying to get around.
145 | -t, --thisProxyUri: Specifies the location (just \`{host}\` form with no port, the port will always be 80 or 443) of the Rust server proxy running on the real internet.
146 | -w, --proxyPw: Specifies the proxy password. This should have the same value on both the server and client.
147 | -p: Specifies the port to listen on. Defaults to 5000.
148 | `);
149 | process.exit(1);
150 | }
151 |
152 | const extractHost = (uri: string) => ({
153 | host: uri.split(":")[0],
154 | port: parseInt(uri.split(":")[1]),
155 | });
156 |
157 | const REAL_PROXY = extractHost(realProxyUri || ":");
158 | const THIS_PROXY = thisProxyUri;
159 |
160 | const PROXY_PW = proxyPw;
161 | // }}}
162 |
163 | const server = http.createServer((req, userRes) => {
164 | const [_error, ifError] = mkError(() => {
165 | try {
166 | userRes.writeHead(502, []);
167 | userRes.end();
168 | } catch (_) {}
169 | });
170 | // basic HTTP proxy
171 | // just rewrite url and remake the request
172 | try {
173 | let url = req.url ?? "";
174 | console.log("basic HTTP proxy:", url);
175 | req.headers["x-proxyer-proxy-dest"] = url;
176 | req.headers["x-proxyer-proxy-auth"] = makeAuth(url);
177 | // The proxy will probably rewrite the Host header,
178 | // so preserve the original here.
179 | req.headers["x-proxyer-real-host"] = req.headers["host"];
180 | let common = {
181 | method: req.method,
182 | headers: req.headers,
183 | };
184 | let options;
185 | let dontCache = Date.now().toString();
186 | options = {
187 | ...common,
188 | hostname: REAL_PROXY.host,
189 | port: REAL_PROXY.port,
190 | path: "http://" + THIS_PROXY + "/" + dontCache,
191 | };
192 | console.log("sending request with options", options);
193 | req.on(
194 | "error",
195 | ifError("(user) req", () => {})
196 | );
197 | let toProxy = http.request(options, (proxyRes) => {
198 | userRes.writeHead(
199 | proxyRes.statusCode ?? 500,
200 | proxyRes.statusMessage,
201 | proxyRes.headers
202 | );
203 | proxyRes.pipe(userRes);
204 | userRes.on(
205 | "error",
206 | ifError("userRes", () => {})
207 | );
208 | proxyRes.on(
209 | "error",
210 | ifError("proxyRes", () => {})
211 | );
212 | });
213 | toProxy.on(
214 | "error",
215 | ifError("toProxy", () => {})
216 | );
217 | req.pipe(toProxy);
218 | } catch (e) {
219 | console.error("Error in basic proxy handler:");
220 | console.error(e);
221 | }
222 | });
223 |
224 | // mk{,If}Error, {,If}ErrorF {{{
225 |
226 | type ErrorF = (msg: string) => (e: any) => void;
227 | type IfErrorF = (
228 | msg: string,
229 | cb?: (...rest: Rest) => void
230 | ) => (err: any, ...rest: Rest) => void;
231 |
232 | const mkError = (
233 | action: () => void
234 | ): [ErrorF, IfErrorF] => {
235 | const error = (msg: string) => (e: any) => {
236 | console.error("error:", msg + ":", e);
237 | action();
238 | };
239 | const ifError = mkIfError(error);
240 | return [error, ifError];
241 | };
242 |
243 | const mkIfError =
244 | (error: ErrorF) =>
245 | (msg: string, cb?: (...rest: Rest) => void) =>
246 | (err: any, ...rest: Rest) => {
247 | if (err) {
248 | error(msg)(err);
249 | } else {
250 | if (cb) cb(...rest);
251 | }
252 | };
253 | // }}}
254 |
255 | type HostPort = { host: string; port: number };
256 |
257 | function connectThroughProxy(
258 | error: ErrorF,
259 | { host, port }: HostPort,
260 | proxySock: net.Socket,
261 | cb: (head: Buffer) => void,
262 | sendAuth?: boolean
263 | ) {
264 | const ifError = mkIfError(error);
265 | proxySock.write(
266 | `CONNECT ${host}:${port} HTTP/1.1\r
267 | Host: ${host}:${port}\r
268 | ${sendAuth ? `${AUTH_HEADER_NAME}: ${makeAuth(host + ":" + port)}\r\n` : ""}\r
269 | `,
270 | ifError("proxy CONNECT write failure", () => {
271 | console.log("wrote CONNECT to proxy");
272 | })
273 | );
274 | parseResponse(
275 | proxySock,
276 | ifError("Proxy HTTP CONNECT response parse error", (resp, head) => {
277 | if (resp.statusCode !== 200) {
278 | // lol ded
279 | error("proxy request failed with")(resp);
280 | } else {
281 | // lets go
282 | console.log("received OK from proxy, connection established");
283 | cb(head);
284 | }
285 | })
286 | );
287 | }
288 |
289 | // If you're having trouble getting to this to work on your locked-down real proxy,
290 | // this function will be helpful to debug.
291 | function debugSock(sock: { on(ev: string, cb: (a: any) => any): void }) {
292 | sock.on("data", (buf) => console.log(buf.toString("utf-8")));
293 | }
294 |
295 | function connectToThisProxy(
296 | error: ErrorF,
297 | cb: (head: Buffer) => void
298 | ): net.Socket {
299 | const ifError = mkIfError(error);
300 |
301 | const proxySock = new net.Socket();
302 | proxySock.on(
303 | "error",
304 | ifError("proxySock", () => {})
305 | );
306 | proxySock.connect(REAL_PROXY, () => {
307 | console.log("connected to real proxy");
308 | connectThroughProxy(
309 | error,
310 | { host: THIS_PROXY ?? "", port: 443 },
311 | proxySock,
312 | (head1) => {
313 | console.log("connected through proxy to this proxy");
314 | // we can pipe the direct TLS connection through here,
315 | // no need to be special about it
316 | cb(head1);
317 | }
318 | );
319 | });
320 | return proxySock;
321 | }
322 |
323 | // auth {{{
324 |
325 | function makeAuth(uri: string): string {
326 | let hour = new Date().getUTCHours();
327 | return makeAuthWithHour(uri, hour);
328 | }
329 |
330 | function makeAuthWithHour(uri: string, hour: number): string {
331 | return sha256(hour + "#" + PROXY_PW + "#" + uri);
332 | }
333 |
334 | // }}}
335 |
336 | const AUTH_HEADER_NAME = "x-proxyer-proxy-auth";
337 |
338 | server.on("connect", (req, userSock, connHead) => {
339 | const [error, ifError] = mkError(() =>
340 | userSock.end("HTTP/1.1 502 Bad Gateway\r\n\r\n")
341 | );
342 | userSock.on("error", ifError("userSock"));
343 | try {
344 | // just pipe it!
345 | const hostport = (req.url ?? "").split(":");
346 | console.log("received CONNECT request for: " + req.url);
347 | const host = hostport[0] ?? panic("no host found in url");
348 | let port = parseInt(hostport[1] ?? panic("no port found in url"));
349 | // add auth just before the TLS request
350 | connHead = Buffer.concat([
351 | Buffer.from(makeAuth(host + ":" + port), "ascii"),
352 | connHead,
353 | ]);
354 | // This is callback hell but there's not much I can do about it, so whatever.
355 | // At least it's only in one place.
356 | const serverSock = connectToThisProxy(error, (thisProxyHead) => {
357 | serverSock.write(
358 | connHead,
359 | ifError("serverSock.write(head)", () => {
360 | userSock.write(
361 | "HTTP/1.1 200 OK\r\n\r\n",
362 | ifError("writing OK response failed", () => {
363 | userSock.write(
364 | thisProxyHead,
365 | ifError("writing remote head failed", () => {
366 | serverSock.pipe(userSock);
367 | userSock.pipe(serverSock);
368 | })
369 | );
370 | })
371 | );
372 | })
373 | );
374 | });
375 | } catch (e) {
376 | error("CONNECT handler")(e);
377 | }
378 | });
379 |
380 | server.listen(parseInt(listenPort || process.env.PORT || "5000"));
381 |
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "@types/express": "^4.17.17",
4 | "@types/http-proxy": "^1.17.10",
5 | "axios": "^1.3.4",
6 | "esbuild": "^0.17.14",
7 | "express": "^4.18.2",
8 | "http-parser-js": "^0.5.8",
9 | "http-proxy": "^1.18.1",
10 | "nexe": "^4.0.0-rc.2",
11 | "pkg": "^5.8.1",
12 | "tsc": "^2.0.4",
13 | "tsc-watch": "^6.0.0",
14 | "typescript": "^5.0.2"
15 | },
16 | "scripts": {
17 | "start": "yarn build && node build/index.js",
18 | "build": "tsc --noEmit && esbuild index.ts --bundle --platform=node --outfile=build/index.js",
19 | "package": "yarn build && pkg build/index.js",
20 | "live": "./scripts/live.sh"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/client/scripts/live.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | tsc-watch --onSuccess "node index.js $(printf '%q ' "$@")"
3 |
--------------------------------------------------------------------------------
/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26 |
27 | /* Modules */
28 | "module": "commonjs", /* Specify what module code is generated. */
29 | // "rootDir": "./", /* Specify the root folder within your source files. */
30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
42 | // "resolveJsonModule": true, /* Enable importing .json files. */
43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
45 |
46 | /* JavaScript Support */
47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50 |
51 | /* Emit */
52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58 | // "outDir": "./", /* Specify an output folder for all emitted files. */
59 | // "removeComments": true, /* Disable emitting comments. */
60 | // "noEmit": true, /* Disable emitting files from a compilation. */
61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
68 | // "newLine": "crlf", /* Set the newline character for emitting files. */
69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
75 |
76 | /* Interop Constraints */
77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
83 |
84 | /* Type Checking */
85 | "strict": true, /* Enable all strict type-checking options. */
86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
104 |
105 | /* Completeness */
106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
107 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | *.old
3 |
--------------------------------------------------------------------------------
/server/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "android_system_properties"
7 | version = "0.1.5"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
10 | dependencies = [
11 | "libc",
12 | ]
13 |
14 | [[package]]
15 | name = "anstream"
16 | version = "0.2.6"
17 | source = "registry+https://github.com/rust-lang/crates.io-index"
18 | checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f"
19 | dependencies = [
20 | "anstyle",
21 | "anstyle-parse",
22 | "anstyle-wincon",
23 | "concolor-override",
24 | "concolor-query",
25 | "is-terminal",
26 | "utf8parse",
27 | ]
28 |
29 | [[package]]
30 | name = "anstyle"
31 | version = "0.3.5"
32 | source = "registry+https://github.com/rust-lang/crates.io-index"
33 | checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2"
34 |
35 | [[package]]
36 | name = "anstyle-parse"
37 | version = "0.1.1"
38 | source = "registry+https://github.com/rust-lang/crates.io-index"
39 | checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116"
40 | dependencies = [
41 | "utf8parse",
42 | ]
43 |
44 | [[package]]
45 | name = "anstyle-wincon"
46 | version = "0.2.0"
47 | source = "registry+https://github.com/rust-lang/crates.io-index"
48 | checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa"
49 | dependencies = [
50 | "anstyle",
51 | "windows-sys 0.45.0",
52 | ]
53 |
54 | [[package]]
55 | name = "anyhow"
56 | version = "1.0.70"
57 | source = "registry+https://github.com/rust-lang/crates.io-index"
58 | checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
59 |
60 | [[package]]
61 | name = "async-trait"
62 | version = "0.1.68"
63 | source = "registry+https://github.com/rust-lang/crates.io-index"
64 | checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
65 | dependencies = [
66 | "proc-macro2",
67 | "quote",
68 | "syn 2.0.11",
69 | ]
70 |
71 | [[package]]
72 | name = "autocfg"
73 | version = "1.1.0"
74 | source = "registry+https://github.com/rust-lang/crates.io-index"
75 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
76 |
77 | [[package]]
78 | name = "bitflags"
79 | version = "1.3.2"
80 | source = "registry+https://github.com/rust-lang/crates.io-index"
81 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
82 |
83 | [[package]]
84 | name = "block-buffer"
85 | version = "0.9.0"
86 | source = "registry+https://github.com/rust-lang/crates.io-index"
87 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
88 | dependencies = [
89 | "generic-array",
90 | ]
91 |
92 | [[package]]
93 | name = "bumpalo"
94 | version = "3.12.0"
95 | source = "registry+https://github.com/rust-lang/crates.io-index"
96 | checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
97 |
98 | [[package]]
99 | name = "bytes"
100 | version = "1.4.0"
101 | source = "registry+https://github.com/rust-lang/crates.io-index"
102 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
103 |
104 | [[package]]
105 | name = "cc"
106 | version = "1.0.79"
107 | source = "registry+https://github.com/rust-lang/crates.io-index"
108 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
109 |
110 | [[package]]
111 | name = "cfg-if"
112 | version = "1.0.0"
113 | source = "registry+https://github.com/rust-lang/crates.io-index"
114 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
115 |
116 | [[package]]
117 | name = "chrono"
118 | version = "0.4.24"
119 | source = "registry+https://github.com/rust-lang/crates.io-index"
120 | checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
121 | dependencies = [
122 | "iana-time-zone",
123 | "js-sys",
124 | "num-integer",
125 | "num-traits 0.2.15",
126 | "time",
127 | "wasm-bindgen",
128 | "winapi",
129 | ]
130 |
131 | [[package]]
132 | name = "clap"
133 | version = "4.2.1"
134 | source = "registry+https://github.com/rust-lang/crates.io-index"
135 | checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3"
136 | dependencies = [
137 | "clap_builder",
138 | "clap_derive",
139 | "once_cell",
140 | ]
141 |
142 | [[package]]
143 | name = "clap_builder"
144 | version = "4.2.1"
145 | source = "registry+https://github.com/rust-lang/crates.io-index"
146 | checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f"
147 | dependencies = [
148 | "anstream",
149 | "anstyle",
150 | "bitflags",
151 | "clap_lex",
152 | "strsim",
153 | ]
154 |
155 | [[package]]
156 | name = "clap_derive"
157 | version = "4.2.0"
158 | source = "registry+https://github.com/rust-lang/crates.io-index"
159 | checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
160 | dependencies = [
161 | "heck",
162 | "proc-macro2",
163 | "quote",
164 | "syn 2.0.11",
165 | ]
166 |
167 | [[package]]
168 | name = "clap_lex"
169 | version = "0.4.1"
170 | source = "registry+https://github.com/rust-lang/crates.io-index"
171 | checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
172 |
173 | [[package]]
174 | name = "codespan-reporting"
175 | version = "0.11.1"
176 | source = "registry+https://github.com/rust-lang/crates.io-index"
177 | checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
178 | dependencies = [
179 | "termcolor",
180 | "unicode-width",
181 | ]
182 |
183 | [[package]]
184 | name = "concolor-override"
185 | version = "1.0.0"
186 | source = "registry+https://github.com/rust-lang/crates.io-index"
187 | checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f"
188 |
189 | [[package]]
190 | name = "concolor-query"
191 | version = "0.3.3"
192 | source = "registry+https://github.com/rust-lang/crates.io-index"
193 | checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf"
194 | dependencies = [
195 | "windows-sys 0.45.0",
196 | ]
197 |
198 | [[package]]
199 | name = "core-foundation-sys"
200 | version = "0.8.3"
201 | source = "registry+https://github.com/rust-lang/crates.io-index"
202 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
203 |
204 | [[package]]
205 | name = "cpufeatures"
206 | version = "0.2.6"
207 | source = "registry+https://github.com/rust-lang/crates.io-index"
208 | checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181"
209 | dependencies = [
210 | "libc",
211 | ]
212 |
213 | [[package]]
214 | name = "cxx"
215 | version = "1.0.94"
216 | source = "registry+https://github.com/rust-lang/crates.io-index"
217 | checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93"
218 | dependencies = [
219 | "cc",
220 | "cxxbridge-flags",
221 | "cxxbridge-macro",
222 | "link-cplusplus",
223 | ]
224 |
225 | [[package]]
226 | name = "cxx-build"
227 | version = "1.0.94"
228 | source = "registry+https://github.com/rust-lang/crates.io-index"
229 | checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b"
230 | dependencies = [
231 | "cc",
232 | "codespan-reporting",
233 | "once_cell",
234 | "proc-macro2",
235 | "quote",
236 | "scratch",
237 | "syn 2.0.11",
238 | ]
239 |
240 | [[package]]
241 | name = "cxxbridge-flags"
242 | version = "1.0.94"
243 | source = "registry+https://github.com/rust-lang/crates.io-index"
244 | checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb"
245 |
246 | [[package]]
247 | name = "cxxbridge-macro"
248 | version = "1.0.94"
249 | source = "registry+https://github.com/rust-lang/crates.io-index"
250 | checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
251 | dependencies = [
252 | "proc-macro2",
253 | "quote",
254 | "syn 2.0.11",
255 | ]
256 |
257 | [[package]]
258 | name = "data-encoding"
259 | version = "2.3.3"
260 | source = "registry+https://github.com/rust-lang/crates.io-index"
261 | checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"
262 |
263 | [[package]]
264 | name = "digest"
265 | version = "0.9.0"
266 | source = "registry+https://github.com/rust-lang/crates.io-index"
267 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
268 | dependencies = [
269 | "generic-array",
270 | ]
271 |
272 | [[package]]
273 | name = "enum-as-inner"
274 | version = "0.5.1"
275 | source = "registry+https://github.com/rust-lang/crates.io-index"
276 | checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116"
277 | dependencies = [
278 | "heck",
279 | "proc-macro2",
280 | "quote",
281 | "syn 1.0.109",
282 | ]
283 |
284 | [[package]]
285 | name = "enum_primitive"
286 | version = "0.1.1"
287 | source = "registry+https://github.com/rust-lang/crates.io-index"
288 | checksum = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
289 | dependencies = [
290 | "num-traits 0.1.43",
291 | ]
292 |
293 | [[package]]
294 | name = "errno"
295 | version = "0.3.1"
296 | source = "registry+https://github.com/rust-lang/crates.io-index"
297 | checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
298 | dependencies = [
299 | "errno-dragonfly",
300 | "libc",
301 | "windows-sys 0.48.0",
302 | ]
303 |
304 | [[package]]
305 | name = "errno-dragonfly"
306 | version = "0.1.2"
307 | source = "registry+https://github.com/rust-lang/crates.io-index"
308 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
309 | dependencies = [
310 | "cc",
311 | "libc",
312 | ]
313 |
314 | [[package]]
315 | name = "fnv"
316 | version = "1.0.7"
317 | source = "registry+https://github.com/rust-lang/crates.io-index"
318 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
319 |
320 | [[package]]
321 | name = "form_urlencoded"
322 | version = "1.1.0"
323 | source = "registry+https://github.com/rust-lang/crates.io-index"
324 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
325 | dependencies = [
326 | "percent-encoding",
327 | ]
328 |
329 | [[package]]
330 | name = "futures-channel"
331 | version = "0.3.27"
332 | source = "registry+https://github.com/rust-lang/crates.io-index"
333 | checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac"
334 | dependencies = [
335 | "futures-core",
336 | ]
337 |
338 | [[package]]
339 | name = "futures-core"
340 | version = "0.3.27"
341 | source = "registry+https://github.com/rust-lang/crates.io-index"
342 | checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
343 |
344 | [[package]]
345 | name = "futures-io"
346 | version = "0.3.27"
347 | source = "registry+https://github.com/rust-lang/crates.io-index"
348 | checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
349 |
350 | [[package]]
351 | name = "futures-sink"
352 | version = "0.3.27"
353 | source = "registry+https://github.com/rust-lang/crates.io-index"
354 | checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2"
355 |
356 | [[package]]
357 | name = "futures-task"
358 | version = "0.3.27"
359 | source = "registry+https://github.com/rust-lang/crates.io-index"
360 | checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879"
361 |
362 | [[package]]
363 | name = "futures-util"
364 | version = "0.3.27"
365 | source = "registry+https://github.com/rust-lang/crates.io-index"
366 | checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab"
367 | dependencies = [
368 | "futures-core",
369 | "futures-task",
370 | "pin-project-lite",
371 | "pin-utils",
372 | "slab",
373 | ]
374 |
375 | [[package]]
376 | name = "generic-array"
377 | version = "0.14.7"
378 | source = "registry+https://github.com/rust-lang/crates.io-index"
379 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
380 | dependencies = [
381 | "typenum",
382 | "version_check",
383 | ]
384 |
385 | [[package]]
386 | name = "getrandom"
387 | version = "0.2.8"
388 | source = "registry+https://github.com/rust-lang/crates.io-index"
389 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
390 | dependencies = [
391 | "cfg-if",
392 | "libc",
393 | "wasi 0.11.0+wasi-snapshot-preview1",
394 | ]
395 |
396 | [[package]]
397 | name = "h2"
398 | version = "0.3.16"
399 | source = "registry+https://github.com/rust-lang/crates.io-index"
400 | checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
401 | dependencies = [
402 | "bytes",
403 | "fnv",
404 | "futures-core",
405 | "futures-sink",
406 | "futures-util",
407 | "http",
408 | "indexmap",
409 | "slab",
410 | "tokio",
411 | "tokio-util",
412 | "tracing",
413 | ]
414 |
415 | [[package]]
416 | name = "hashbrown"
417 | version = "0.12.3"
418 | source = "registry+https://github.com/rust-lang/crates.io-index"
419 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
420 |
421 | [[package]]
422 | name = "heck"
423 | version = "0.4.1"
424 | source = "registry+https://github.com/rust-lang/crates.io-index"
425 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
426 |
427 | [[package]]
428 | name = "hermit-abi"
429 | version = "0.2.6"
430 | source = "registry+https://github.com/rust-lang/crates.io-index"
431 | checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
432 | dependencies = [
433 | "libc",
434 | ]
435 |
436 | [[package]]
437 | name = "hermit-abi"
438 | version = "0.3.1"
439 | source = "registry+https://github.com/rust-lang/crates.io-index"
440 | checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
441 |
442 | [[package]]
443 | name = "hex"
444 | version = "0.4.3"
445 | source = "registry+https://github.com/rust-lang/crates.io-index"
446 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
447 |
448 | [[package]]
449 | name = "http"
450 | version = "0.2.9"
451 | source = "registry+https://github.com/rust-lang/crates.io-index"
452 | checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
453 | dependencies = [
454 | "bytes",
455 | "fnv",
456 | "itoa",
457 | ]
458 |
459 | [[package]]
460 | name = "http-body"
461 | version = "0.4.5"
462 | source = "registry+https://github.com/rust-lang/crates.io-index"
463 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
464 | dependencies = [
465 | "bytes",
466 | "http",
467 | "pin-project-lite",
468 | ]
469 |
470 | [[package]]
471 | name = "httparse"
472 | version = "1.8.0"
473 | source = "registry+https://github.com/rust-lang/crates.io-index"
474 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
475 |
476 | [[package]]
477 | name = "httpdate"
478 | version = "1.0.2"
479 | source = "registry+https://github.com/rust-lang/crates.io-index"
480 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
481 |
482 | [[package]]
483 | name = "hyper"
484 | version = "0.14.25"
485 | source = "registry+https://github.com/rust-lang/crates.io-index"
486 | checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
487 | dependencies = [
488 | "bytes",
489 | "futures-channel",
490 | "futures-core",
491 | "futures-util",
492 | "h2",
493 | "http",
494 | "http-body",
495 | "httparse",
496 | "httpdate",
497 | "itoa",
498 | "pin-project-lite",
499 | "socket2",
500 | "tokio",
501 | "tower-service",
502 | "tracing",
503 | "want",
504 | ]
505 |
506 | [[package]]
507 | name = "hyper-rustls"
508 | version = "0.23.2"
509 | source = "registry+https://github.com/rust-lang/crates.io-index"
510 | checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c"
511 | dependencies = [
512 | "http",
513 | "hyper",
514 | "rustls",
515 | "tokio",
516 | "tokio-rustls",
517 | "webpki-roots",
518 | ]
519 |
520 | [[package]]
521 | name = "hyper-trust-dns"
522 | version = "0.5.0"
523 | source = "registry+https://github.com/rust-lang/crates.io-index"
524 | checksum = "0deaf08b5c5409c0c74011f696a82bdadae4c6d70b7a71edf8378b29bdd840bd"
525 | dependencies = [
526 | "hyper",
527 | "hyper-rustls",
528 | "tokio",
529 | "trust-dns-resolver",
530 | ]
531 |
532 | [[package]]
533 | name = "iana-time-zone"
534 | version = "0.1.54"
535 | source = "registry+https://github.com/rust-lang/crates.io-index"
536 | checksum = "0c17cc76786e99f8d2f055c11159e7f0091c42474dcc3189fbab96072e873e6d"
537 | dependencies = [
538 | "android_system_properties",
539 | "core-foundation-sys",
540 | "iana-time-zone-haiku",
541 | "js-sys",
542 | "wasm-bindgen",
543 | "windows",
544 | ]
545 |
546 | [[package]]
547 | name = "iana-time-zone-haiku"
548 | version = "0.1.1"
549 | source = "registry+https://github.com/rust-lang/crates.io-index"
550 | checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
551 | dependencies = [
552 | "cxx",
553 | "cxx-build",
554 | ]
555 |
556 | [[package]]
557 | name = "idna"
558 | version = "0.2.3"
559 | source = "registry+https://github.com/rust-lang/crates.io-index"
560 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
561 | dependencies = [
562 | "matches",
563 | "unicode-bidi",
564 | "unicode-normalization",
565 | ]
566 |
567 | [[package]]
568 | name = "idna"
569 | version = "0.3.0"
570 | source = "registry+https://github.com/rust-lang/crates.io-index"
571 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
572 | dependencies = [
573 | "unicode-bidi",
574 | "unicode-normalization",
575 | ]
576 |
577 | [[package]]
578 | name = "indexmap"
579 | version = "1.9.3"
580 | source = "registry+https://github.com/rust-lang/crates.io-index"
581 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
582 | dependencies = [
583 | "autocfg",
584 | "hashbrown",
585 | ]
586 |
587 | [[package]]
588 | name = "io-lifetimes"
589 | version = "1.0.10"
590 | source = "registry+https://github.com/rust-lang/crates.io-index"
591 | checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
592 | dependencies = [
593 | "hermit-abi 0.3.1",
594 | "libc",
595 | "windows-sys 0.48.0",
596 | ]
597 |
598 | [[package]]
599 | name = "ipnet"
600 | version = "2.7.2"
601 | source = "registry+https://github.com/rust-lang/crates.io-index"
602 | checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
603 |
604 | [[package]]
605 | name = "is-terminal"
606 | version = "0.4.7"
607 | source = "registry+https://github.com/rust-lang/crates.io-index"
608 | checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
609 | dependencies = [
610 | "hermit-abi 0.3.1",
611 | "io-lifetimes",
612 | "rustix",
613 | "windows-sys 0.48.0",
614 | ]
615 |
616 | [[package]]
617 | name = "itoa"
618 | version = "1.0.6"
619 | source = "registry+https://github.com/rust-lang/crates.io-index"
620 | checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
621 |
622 | [[package]]
623 | name = "js-sys"
624 | version = "0.3.61"
625 | source = "registry+https://github.com/rust-lang/crates.io-index"
626 | checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
627 | dependencies = [
628 | "wasm-bindgen",
629 | ]
630 |
631 | [[package]]
632 | name = "lazy_static"
633 | version = "1.4.0"
634 | source = "registry+https://github.com/rust-lang/crates.io-index"
635 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
636 |
637 | [[package]]
638 | name = "libc"
639 | version = "0.2.140"
640 | source = "registry+https://github.com/rust-lang/crates.io-index"
641 | checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
642 |
643 | [[package]]
644 | name = "link-cplusplus"
645 | version = "1.0.8"
646 | source = "registry+https://github.com/rust-lang/crates.io-index"
647 | checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
648 | dependencies = [
649 | "cc",
650 | ]
651 |
652 | [[package]]
653 | name = "linked-hash-map"
654 | version = "0.5.6"
655 | source = "registry+https://github.com/rust-lang/crates.io-index"
656 | checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
657 |
658 | [[package]]
659 | name = "linux-raw-sys"
660 | version = "0.3.1"
661 | source = "registry+https://github.com/rust-lang/crates.io-index"
662 | checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
663 |
664 | [[package]]
665 | name = "lock_api"
666 | version = "0.4.9"
667 | source = "registry+https://github.com/rust-lang/crates.io-index"
668 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
669 | dependencies = [
670 | "autocfg",
671 | "scopeguard",
672 | ]
673 |
674 | [[package]]
675 | name = "log"
676 | version = "0.4.17"
677 | source = "registry+https://github.com/rust-lang/crates.io-index"
678 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
679 | dependencies = [
680 | "cfg-if",
681 | ]
682 |
683 | [[package]]
684 | name = "lru-cache"
685 | version = "0.1.2"
686 | source = "registry+https://github.com/rust-lang/crates.io-index"
687 | checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
688 | dependencies = [
689 | "linked-hash-map",
690 | ]
691 |
692 | [[package]]
693 | name = "matchers"
694 | version = "0.1.0"
695 | source = "registry+https://github.com/rust-lang/crates.io-index"
696 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
697 | dependencies = [
698 | "regex-automata",
699 | ]
700 |
701 | [[package]]
702 | name = "matches"
703 | version = "0.1.10"
704 | source = "registry+https://github.com/rust-lang/crates.io-index"
705 | checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
706 |
707 | [[package]]
708 | name = "memchr"
709 | version = "2.5.0"
710 | source = "registry+https://github.com/rust-lang/crates.io-index"
711 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
712 |
713 | [[package]]
714 | name = "minimal-lexical"
715 | version = "0.2.1"
716 | source = "registry+https://github.com/rust-lang/crates.io-index"
717 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
718 |
719 | [[package]]
720 | name = "mio"
721 | version = "0.8.6"
722 | source = "registry+https://github.com/rust-lang/crates.io-index"
723 | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
724 | dependencies = [
725 | "libc",
726 | "log",
727 | "wasi 0.11.0+wasi-snapshot-preview1",
728 | "windows-sys 0.45.0",
729 | ]
730 |
731 | [[package]]
732 | name = "nom"
733 | version = "7.1.3"
734 | source = "registry+https://github.com/rust-lang/crates.io-index"
735 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
736 | dependencies = [
737 | "memchr",
738 | "minimal-lexical",
739 | ]
740 |
741 | [[package]]
742 | name = "nom-derive"
743 | version = "0.10.1"
744 | source = "registry+https://github.com/rust-lang/crates.io-index"
745 | checksum = "1ff943d68b88d0b87a6e0d58615e8fa07f9fd5a1319fa0a72efc1f62275c79a7"
746 | dependencies = [
747 | "nom",
748 | "nom-derive-impl",
749 | "rustversion",
750 | ]
751 |
752 | [[package]]
753 | name = "nom-derive-impl"
754 | version = "0.10.1"
755 | source = "registry+https://github.com/rust-lang/crates.io-index"
756 | checksum = "cd0b9a93a84b0d3ec3e70e02d332dc33ac6dfac9cde63e17fcb77172dededa62"
757 | dependencies = [
758 | "proc-macro2",
759 | "quote",
760 | "syn 1.0.109",
761 | ]
762 |
763 | [[package]]
764 | name = "nu-ansi-term"
765 | version = "0.46.0"
766 | source = "registry+https://github.com/rust-lang/crates.io-index"
767 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
768 | dependencies = [
769 | "overload",
770 | "winapi",
771 | ]
772 |
773 | [[package]]
774 | name = "num-integer"
775 | version = "0.1.45"
776 | source = "registry+https://github.com/rust-lang/crates.io-index"
777 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
778 | dependencies = [
779 | "autocfg",
780 | "num-traits 0.2.15",
781 | ]
782 |
783 | [[package]]
784 | name = "num-traits"
785 | version = "0.1.43"
786 | source = "registry+https://github.com/rust-lang/crates.io-index"
787 | checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
788 | dependencies = [
789 | "num-traits 0.2.15",
790 | ]
791 |
792 | [[package]]
793 | name = "num-traits"
794 | version = "0.2.15"
795 | source = "registry+https://github.com/rust-lang/crates.io-index"
796 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
797 | dependencies = [
798 | "autocfg",
799 | ]
800 |
801 | [[package]]
802 | name = "num_cpus"
803 | version = "1.15.0"
804 | source = "registry+https://github.com/rust-lang/crates.io-index"
805 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
806 | dependencies = [
807 | "hermit-abi 0.2.6",
808 | "libc",
809 | ]
810 |
811 | [[package]]
812 | name = "once_cell"
813 | version = "1.17.1"
814 | source = "registry+https://github.com/rust-lang/crates.io-index"
815 | checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
816 |
817 | [[package]]
818 | name = "opaque-debug"
819 | version = "0.3.0"
820 | source = "registry+https://github.com/rust-lang/crates.io-index"
821 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
822 |
823 | [[package]]
824 | name = "overload"
825 | version = "0.1.1"
826 | source = "registry+https://github.com/rust-lang/crates.io-index"
827 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
828 |
829 | [[package]]
830 | name = "parking_lot"
831 | version = "0.12.1"
832 | source = "registry+https://github.com/rust-lang/crates.io-index"
833 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
834 | dependencies = [
835 | "lock_api",
836 | "parking_lot_core",
837 | ]
838 |
839 | [[package]]
840 | name = "parking_lot_core"
841 | version = "0.9.7"
842 | source = "registry+https://github.com/rust-lang/crates.io-index"
843 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
844 | dependencies = [
845 | "cfg-if",
846 | "libc",
847 | "redox_syscall",
848 | "smallvec",
849 | "windows-sys 0.45.0",
850 | ]
851 |
852 | [[package]]
853 | name = "percent-encoding"
854 | version = "2.2.0"
855 | source = "registry+https://github.com/rust-lang/crates.io-index"
856 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
857 |
858 | [[package]]
859 | name = "phf"
860 | version = "0.10.1"
861 | source = "registry+https://github.com/rust-lang/crates.io-index"
862 | checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
863 | dependencies = [
864 | "phf_shared",
865 | ]
866 |
867 | [[package]]
868 | name = "phf_codegen"
869 | version = "0.10.0"
870 | source = "registry+https://github.com/rust-lang/crates.io-index"
871 | checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
872 | dependencies = [
873 | "phf_generator",
874 | "phf_shared",
875 | ]
876 |
877 | [[package]]
878 | name = "phf_generator"
879 | version = "0.10.0"
880 | source = "registry+https://github.com/rust-lang/crates.io-index"
881 | checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
882 | dependencies = [
883 | "phf_shared",
884 | "rand",
885 | ]
886 |
887 | [[package]]
888 | name = "phf_shared"
889 | version = "0.10.0"
890 | source = "registry+https://github.com/rust-lang/crates.io-index"
891 | checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
892 | dependencies = [
893 | "siphasher",
894 | ]
895 |
896 | [[package]]
897 | name = "pin-project-lite"
898 | version = "0.2.9"
899 | source = "registry+https://github.com/rust-lang/crates.io-index"
900 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
901 |
902 | [[package]]
903 | name = "pin-utils"
904 | version = "0.1.0"
905 | source = "registry+https://github.com/rust-lang/crates.io-index"
906 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
907 |
908 | [[package]]
909 | name = "ppv-lite86"
910 | version = "0.2.17"
911 | source = "registry+https://github.com/rust-lang/crates.io-index"
912 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
913 |
914 | [[package]]
915 | name = "proc-macro2"
916 | version = "1.0.53"
917 | source = "registry+https://github.com/rust-lang/crates.io-index"
918 | checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
919 | dependencies = [
920 | "unicode-ident",
921 | ]
922 |
923 | [[package]]
924 | name = "proxyer"
925 | version = "0.1.0"
926 | dependencies = [
927 | "anyhow",
928 | "chrono",
929 | "clap",
930 | "hyper",
931 | "hyper-trust-dns",
932 | "once_cell",
933 | "sha256",
934 | "tls-parser",
935 | "tokio",
936 | "tracing",
937 | "tracing-subscriber",
938 | ]
939 |
940 | [[package]]
941 | name = "quote"
942 | version = "1.0.26"
943 | source = "registry+https://github.com/rust-lang/crates.io-index"
944 | checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
945 | dependencies = [
946 | "proc-macro2",
947 | ]
948 |
949 | [[package]]
950 | name = "rand"
951 | version = "0.8.5"
952 | source = "registry+https://github.com/rust-lang/crates.io-index"
953 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
954 | dependencies = [
955 | "libc",
956 | "rand_chacha",
957 | "rand_core",
958 | ]
959 |
960 | [[package]]
961 | name = "rand_chacha"
962 | version = "0.3.1"
963 | source = "registry+https://github.com/rust-lang/crates.io-index"
964 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
965 | dependencies = [
966 | "ppv-lite86",
967 | "rand_core",
968 | ]
969 |
970 | [[package]]
971 | name = "rand_core"
972 | version = "0.6.4"
973 | source = "registry+https://github.com/rust-lang/crates.io-index"
974 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
975 | dependencies = [
976 | "getrandom",
977 | ]
978 |
979 | [[package]]
980 | name = "redox_syscall"
981 | version = "0.2.16"
982 | source = "registry+https://github.com/rust-lang/crates.io-index"
983 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
984 | dependencies = [
985 | "bitflags",
986 | ]
987 |
988 | [[package]]
989 | name = "regex"
990 | version = "1.7.2"
991 | source = "registry+https://github.com/rust-lang/crates.io-index"
992 | checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c"
993 | dependencies = [
994 | "regex-syntax",
995 | ]
996 |
997 | [[package]]
998 | name = "regex-automata"
999 | version = "0.1.10"
1000 | source = "registry+https://github.com/rust-lang/crates.io-index"
1001 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
1002 | dependencies = [
1003 | "regex-syntax",
1004 | ]
1005 |
1006 | [[package]]
1007 | name = "regex-syntax"
1008 | version = "0.6.29"
1009 | source = "registry+https://github.com/rust-lang/crates.io-index"
1010 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
1011 |
1012 | [[package]]
1013 | name = "ring"
1014 | version = "0.16.20"
1015 | source = "registry+https://github.com/rust-lang/crates.io-index"
1016 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
1017 | dependencies = [
1018 | "cc",
1019 | "libc",
1020 | "once_cell",
1021 | "spin",
1022 | "untrusted",
1023 | "web-sys",
1024 | "winapi",
1025 | ]
1026 |
1027 | [[package]]
1028 | name = "rusticata-macros"
1029 | version = "4.1.0"
1030 | source = "registry+https://github.com/rust-lang/crates.io-index"
1031 | checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
1032 | dependencies = [
1033 | "nom",
1034 | ]
1035 |
1036 | [[package]]
1037 | name = "rustix"
1038 | version = "0.37.7"
1039 | source = "registry+https://github.com/rust-lang/crates.io-index"
1040 | checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d"
1041 | dependencies = [
1042 | "bitflags",
1043 | "errno",
1044 | "io-lifetimes",
1045 | "libc",
1046 | "linux-raw-sys",
1047 | "windows-sys 0.45.0",
1048 | ]
1049 |
1050 | [[package]]
1051 | name = "rustls"
1052 | version = "0.20.8"
1053 | source = "registry+https://github.com/rust-lang/crates.io-index"
1054 | checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
1055 | dependencies = [
1056 | "ring",
1057 | "sct",
1058 | "webpki",
1059 | ]
1060 |
1061 | [[package]]
1062 | name = "rustversion"
1063 | version = "1.0.12"
1064 | source = "registry+https://github.com/rust-lang/crates.io-index"
1065 | checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
1066 |
1067 | [[package]]
1068 | name = "scopeguard"
1069 | version = "1.1.0"
1070 | source = "registry+https://github.com/rust-lang/crates.io-index"
1071 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
1072 |
1073 | [[package]]
1074 | name = "scratch"
1075 | version = "1.0.5"
1076 | source = "registry+https://github.com/rust-lang/crates.io-index"
1077 | checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
1078 |
1079 | [[package]]
1080 | name = "sct"
1081 | version = "0.7.0"
1082 | source = "registry+https://github.com/rust-lang/crates.io-index"
1083 | checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
1084 | dependencies = [
1085 | "ring",
1086 | "untrusted",
1087 | ]
1088 |
1089 | [[package]]
1090 | name = "sha2"
1091 | version = "0.9.9"
1092 | source = "registry+https://github.com/rust-lang/crates.io-index"
1093 | checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
1094 | dependencies = [
1095 | "block-buffer",
1096 | "cfg-if",
1097 | "cpufeatures",
1098 | "digest",
1099 | "opaque-debug",
1100 | ]
1101 |
1102 | [[package]]
1103 | name = "sha256"
1104 | version = "1.1.2"
1105 | source = "registry+https://github.com/rust-lang/crates.io-index"
1106 | checksum = "328169f167261957e83d82be47f9e36629e257c62308129033d7f7e7c173d180"
1107 | dependencies = [
1108 | "hex",
1109 | "sha2",
1110 | ]
1111 |
1112 | [[package]]
1113 | name = "sharded-slab"
1114 | version = "0.1.4"
1115 | source = "registry+https://github.com/rust-lang/crates.io-index"
1116 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
1117 | dependencies = [
1118 | "lazy_static",
1119 | ]
1120 |
1121 | [[package]]
1122 | name = "signal-hook-registry"
1123 | version = "1.4.1"
1124 | source = "registry+https://github.com/rust-lang/crates.io-index"
1125 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
1126 | dependencies = [
1127 | "libc",
1128 | ]
1129 |
1130 | [[package]]
1131 | name = "siphasher"
1132 | version = "0.3.10"
1133 | source = "registry+https://github.com/rust-lang/crates.io-index"
1134 | checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
1135 |
1136 | [[package]]
1137 | name = "slab"
1138 | version = "0.4.8"
1139 | source = "registry+https://github.com/rust-lang/crates.io-index"
1140 | checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
1141 | dependencies = [
1142 | "autocfg",
1143 | ]
1144 |
1145 | [[package]]
1146 | name = "smallvec"
1147 | version = "1.10.0"
1148 | source = "registry+https://github.com/rust-lang/crates.io-index"
1149 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
1150 |
1151 | [[package]]
1152 | name = "socket2"
1153 | version = "0.4.9"
1154 | source = "registry+https://github.com/rust-lang/crates.io-index"
1155 | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
1156 | dependencies = [
1157 | "libc",
1158 | "winapi",
1159 | ]
1160 |
1161 | [[package]]
1162 | name = "spin"
1163 | version = "0.5.2"
1164 | source = "registry+https://github.com/rust-lang/crates.io-index"
1165 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
1166 |
1167 | [[package]]
1168 | name = "strsim"
1169 | version = "0.10.0"
1170 | source = "registry+https://github.com/rust-lang/crates.io-index"
1171 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
1172 |
1173 | [[package]]
1174 | name = "syn"
1175 | version = "1.0.109"
1176 | source = "registry+https://github.com/rust-lang/crates.io-index"
1177 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
1178 | dependencies = [
1179 | "proc-macro2",
1180 | "quote",
1181 | "unicode-ident",
1182 | ]
1183 |
1184 | [[package]]
1185 | name = "syn"
1186 | version = "2.0.11"
1187 | source = "registry+https://github.com/rust-lang/crates.io-index"
1188 | checksum = "21e3787bb71465627110e7d87ed4faaa36c1f61042ee67badb9e2ef173accc40"
1189 | dependencies = [
1190 | "proc-macro2",
1191 | "quote",
1192 | "unicode-ident",
1193 | ]
1194 |
1195 | [[package]]
1196 | name = "termcolor"
1197 | version = "1.2.0"
1198 | source = "registry+https://github.com/rust-lang/crates.io-index"
1199 | checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
1200 | dependencies = [
1201 | "winapi-util",
1202 | ]
1203 |
1204 | [[package]]
1205 | name = "thiserror"
1206 | version = "1.0.40"
1207 | source = "registry+https://github.com/rust-lang/crates.io-index"
1208 | checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
1209 | dependencies = [
1210 | "thiserror-impl",
1211 | ]
1212 |
1213 | [[package]]
1214 | name = "thiserror-impl"
1215 | version = "1.0.40"
1216 | source = "registry+https://github.com/rust-lang/crates.io-index"
1217 | checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
1218 | dependencies = [
1219 | "proc-macro2",
1220 | "quote",
1221 | "syn 2.0.11",
1222 | ]
1223 |
1224 | [[package]]
1225 | name = "thread_local"
1226 | version = "1.1.7"
1227 | source = "registry+https://github.com/rust-lang/crates.io-index"
1228 | checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
1229 | dependencies = [
1230 | "cfg-if",
1231 | "once_cell",
1232 | ]
1233 |
1234 | [[package]]
1235 | name = "time"
1236 | version = "0.1.45"
1237 | source = "registry+https://github.com/rust-lang/crates.io-index"
1238 | checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
1239 | dependencies = [
1240 | "libc",
1241 | "wasi 0.10.0+wasi-snapshot-preview1",
1242 | "winapi",
1243 | ]
1244 |
1245 | [[package]]
1246 | name = "tinyvec"
1247 | version = "1.6.0"
1248 | source = "registry+https://github.com/rust-lang/crates.io-index"
1249 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
1250 | dependencies = [
1251 | "tinyvec_macros",
1252 | ]
1253 |
1254 | [[package]]
1255 | name = "tinyvec_macros"
1256 | version = "0.1.1"
1257 | source = "registry+https://github.com/rust-lang/crates.io-index"
1258 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
1259 |
1260 | [[package]]
1261 | name = "tls-parser"
1262 | version = "0.11.0"
1263 | source = "registry+https://github.com/rust-lang/crates.io-index"
1264 | checksum = "409206e2de64edbf7ea99a44ac31680daf9ef1a57895fb3c5bd738a903691be0"
1265 | dependencies = [
1266 | "enum_primitive",
1267 | "nom",
1268 | "nom-derive",
1269 | "phf",
1270 | "phf_codegen",
1271 | "rusticata-macros",
1272 | ]
1273 |
1274 | [[package]]
1275 | name = "tokio"
1276 | version = "1.26.0"
1277 | source = "registry+https://github.com/rust-lang/crates.io-index"
1278 | checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
1279 | dependencies = [
1280 | "autocfg",
1281 | "bytes",
1282 | "libc",
1283 | "memchr",
1284 | "mio",
1285 | "num_cpus",
1286 | "parking_lot",
1287 | "pin-project-lite",
1288 | "signal-hook-registry",
1289 | "socket2",
1290 | "tokio-macros",
1291 | "windows-sys 0.45.0",
1292 | ]
1293 |
1294 | [[package]]
1295 | name = "tokio-macros"
1296 | version = "1.8.2"
1297 | source = "registry+https://github.com/rust-lang/crates.io-index"
1298 | checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
1299 | dependencies = [
1300 | "proc-macro2",
1301 | "quote",
1302 | "syn 1.0.109",
1303 | ]
1304 |
1305 | [[package]]
1306 | name = "tokio-rustls"
1307 | version = "0.23.4"
1308 | source = "registry+https://github.com/rust-lang/crates.io-index"
1309 | checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
1310 | dependencies = [
1311 | "rustls",
1312 | "tokio",
1313 | "webpki",
1314 | ]
1315 |
1316 | [[package]]
1317 | name = "tokio-util"
1318 | version = "0.7.7"
1319 | source = "registry+https://github.com/rust-lang/crates.io-index"
1320 | checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
1321 | dependencies = [
1322 | "bytes",
1323 | "futures-core",
1324 | "futures-sink",
1325 | "pin-project-lite",
1326 | "tokio",
1327 | "tracing",
1328 | ]
1329 |
1330 | [[package]]
1331 | name = "tower-service"
1332 | version = "0.3.2"
1333 | source = "registry+https://github.com/rust-lang/crates.io-index"
1334 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
1335 |
1336 | [[package]]
1337 | name = "tracing"
1338 | version = "0.1.37"
1339 | source = "registry+https://github.com/rust-lang/crates.io-index"
1340 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
1341 | dependencies = [
1342 | "cfg-if",
1343 | "pin-project-lite",
1344 | "tracing-attributes",
1345 | "tracing-core",
1346 | ]
1347 |
1348 | [[package]]
1349 | name = "tracing-attributes"
1350 | version = "0.1.23"
1351 | source = "registry+https://github.com/rust-lang/crates.io-index"
1352 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
1353 | dependencies = [
1354 | "proc-macro2",
1355 | "quote",
1356 | "syn 1.0.109",
1357 | ]
1358 |
1359 | [[package]]
1360 | name = "tracing-core"
1361 | version = "0.1.30"
1362 | source = "registry+https://github.com/rust-lang/crates.io-index"
1363 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
1364 | dependencies = [
1365 | "once_cell",
1366 | "valuable",
1367 | ]
1368 |
1369 | [[package]]
1370 | name = "tracing-log"
1371 | version = "0.1.3"
1372 | source = "registry+https://github.com/rust-lang/crates.io-index"
1373 | checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
1374 | dependencies = [
1375 | "lazy_static",
1376 | "log",
1377 | "tracing-core",
1378 | ]
1379 |
1380 | [[package]]
1381 | name = "tracing-subscriber"
1382 | version = "0.3.16"
1383 | source = "registry+https://github.com/rust-lang/crates.io-index"
1384 | checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
1385 | dependencies = [
1386 | "matchers",
1387 | "nu-ansi-term",
1388 | "once_cell",
1389 | "regex",
1390 | "sharded-slab",
1391 | "smallvec",
1392 | "thread_local",
1393 | "tracing",
1394 | "tracing-core",
1395 | "tracing-log",
1396 | ]
1397 |
1398 | [[package]]
1399 | name = "trust-dns-proto"
1400 | version = "0.22.0"
1401 | source = "registry+https://github.com/rust-lang/crates.io-index"
1402 | checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26"
1403 | dependencies = [
1404 | "async-trait",
1405 | "cfg-if",
1406 | "data-encoding",
1407 | "enum-as-inner",
1408 | "futures-channel",
1409 | "futures-io",
1410 | "futures-util",
1411 | "idna 0.2.3",
1412 | "ipnet",
1413 | "lazy_static",
1414 | "rand",
1415 | "smallvec",
1416 | "thiserror",
1417 | "tinyvec",
1418 | "tokio",
1419 | "tracing",
1420 | "url",
1421 | ]
1422 |
1423 | [[package]]
1424 | name = "trust-dns-resolver"
1425 | version = "0.22.0"
1426 | source = "registry+https://github.com/rust-lang/crates.io-index"
1427 | checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe"
1428 | dependencies = [
1429 | "cfg-if",
1430 | "futures-util",
1431 | "lazy_static",
1432 | "lru-cache",
1433 | "parking_lot",
1434 | "smallvec",
1435 | "thiserror",
1436 | "tokio",
1437 | "tracing",
1438 | "trust-dns-proto",
1439 | ]
1440 |
1441 | [[package]]
1442 | name = "try-lock"
1443 | version = "0.2.4"
1444 | source = "registry+https://github.com/rust-lang/crates.io-index"
1445 | checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
1446 |
1447 | [[package]]
1448 | name = "typenum"
1449 | version = "1.16.0"
1450 | source = "registry+https://github.com/rust-lang/crates.io-index"
1451 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
1452 |
1453 | [[package]]
1454 | name = "unicode-bidi"
1455 | version = "0.3.13"
1456 | source = "registry+https://github.com/rust-lang/crates.io-index"
1457 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
1458 |
1459 | [[package]]
1460 | name = "unicode-ident"
1461 | version = "1.0.8"
1462 | source = "registry+https://github.com/rust-lang/crates.io-index"
1463 | checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
1464 |
1465 | [[package]]
1466 | name = "unicode-normalization"
1467 | version = "0.1.22"
1468 | source = "registry+https://github.com/rust-lang/crates.io-index"
1469 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
1470 | dependencies = [
1471 | "tinyvec",
1472 | ]
1473 |
1474 | [[package]]
1475 | name = "unicode-width"
1476 | version = "0.1.10"
1477 | source = "registry+https://github.com/rust-lang/crates.io-index"
1478 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
1479 |
1480 | [[package]]
1481 | name = "untrusted"
1482 | version = "0.7.1"
1483 | source = "registry+https://github.com/rust-lang/crates.io-index"
1484 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
1485 |
1486 | [[package]]
1487 | name = "url"
1488 | version = "2.3.1"
1489 | source = "registry+https://github.com/rust-lang/crates.io-index"
1490 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
1491 | dependencies = [
1492 | "form_urlencoded",
1493 | "idna 0.3.0",
1494 | "percent-encoding",
1495 | ]
1496 |
1497 | [[package]]
1498 | name = "utf8parse"
1499 | version = "0.2.1"
1500 | source = "registry+https://github.com/rust-lang/crates.io-index"
1501 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
1502 |
1503 | [[package]]
1504 | name = "valuable"
1505 | version = "0.1.0"
1506 | source = "registry+https://github.com/rust-lang/crates.io-index"
1507 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
1508 |
1509 | [[package]]
1510 | name = "version_check"
1511 | version = "0.9.4"
1512 | source = "registry+https://github.com/rust-lang/crates.io-index"
1513 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
1514 |
1515 | [[package]]
1516 | name = "want"
1517 | version = "0.3.0"
1518 | source = "registry+https://github.com/rust-lang/crates.io-index"
1519 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
1520 | dependencies = [
1521 | "log",
1522 | "try-lock",
1523 | ]
1524 |
1525 | [[package]]
1526 | name = "wasi"
1527 | version = "0.10.0+wasi-snapshot-preview1"
1528 | source = "registry+https://github.com/rust-lang/crates.io-index"
1529 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
1530 |
1531 | [[package]]
1532 | name = "wasi"
1533 | version = "0.11.0+wasi-snapshot-preview1"
1534 | source = "registry+https://github.com/rust-lang/crates.io-index"
1535 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
1536 |
1537 | [[package]]
1538 | name = "wasm-bindgen"
1539 | version = "0.2.84"
1540 | source = "registry+https://github.com/rust-lang/crates.io-index"
1541 | checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
1542 | dependencies = [
1543 | "cfg-if",
1544 | "wasm-bindgen-macro",
1545 | ]
1546 |
1547 | [[package]]
1548 | name = "wasm-bindgen-backend"
1549 | version = "0.2.84"
1550 | source = "registry+https://github.com/rust-lang/crates.io-index"
1551 | checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
1552 | dependencies = [
1553 | "bumpalo",
1554 | "log",
1555 | "once_cell",
1556 | "proc-macro2",
1557 | "quote",
1558 | "syn 1.0.109",
1559 | "wasm-bindgen-shared",
1560 | ]
1561 |
1562 | [[package]]
1563 | name = "wasm-bindgen-macro"
1564 | version = "0.2.84"
1565 | source = "registry+https://github.com/rust-lang/crates.io-index"
1566 | checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
1567 | dependencies = [
1568 | "quote",
1569 | "wasm-bindgen-macro-support",
1570 | ]
1571 |
1572 | [[package]]
1573 | name = "wasm-bindgen-macro-support"
1574 | version = "0.2.84"
1575 | source = "registry+https://github.com/rust-lang/crates.io-index"
1576 | checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
1577 | dependencies = [
1578 | "proc-macro2",
1579 | "quote",
1580 | "syn 1.0.109",
1581 | "wasm-bindgen-backend",
1582 | "wasm-bindgen-shared",
1583 | ]
1584 |
1585 | [[package]]
1586 | name = "wasm-bindgen-shared"
1587 | version = "0.2.84"
1588 | source = "registry+https://github.com/rust-lang/crates.io-index"
1589 | checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
1590 |
1591 | [[package]]
1592 | name = "web-sys"
1593 | version = "0.3.61"
1594 | source = "registry+https://github.com/rust-lang/crates.io-index"
1595 | checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
1596 | dependencies = [
1597 | "js-sys",
1598 | "wasm-bindgen",
1599 | ]
1600 |
1601 | [[package]]
1602 | name = "webpki"
1603 | version = "0.22.0"
1604 | source = "registry+https://github.com/rust-lang/crates.io-index"
1605 | checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
1606 | dependencies = [
1607 | "ring",
1608 | "untrusted",
1609 | ]
1610 |
1611 | [[package]]
1612 | name = "webpki-roots"
1613 | version = "0.22.6"
1614 | source = "registry+https://github.com/rust-lang/crates.io-index"
1615 | checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
1616 | dependencies = [
1617 | "webpki",
1618 | ]
1619 |
1620 | [[package]]
1621 | name = "winapi"
1622 | version = "0.3.9"
1623 | source = "registry+https://github.com/rust-lang/crates.io-index"
1624 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1625 | dependencies = [
1626 | "winapi-i686-pc-windows-gnu",
1627 | "winapi-x86_64-pc-windows-gnu",
1628 | ]
1629 |
1630 | [[package]]
1631 | name = "winapi-i686-pc-windows-gnu"
1632 | version = "0.4.0"
1633 | source = "registry+https://github.com/rust-lang/crates.io-index"
1634 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1635 |
1636 | [[package]]
1637 | name = "winapi-util"
1638 | version = "0.1.5"
1639 | source = "registry+https://github.com/rust-lang/crates.io-index"
1640 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
1641 | dependencies = [
1642 | "winapi",
1643 | ]
1644 |
1645 | [[package]]
1646 | name = "winapi-x86_64-pc-windows-gnu"
1647 | version = "0.4.0"
1648 | source = "registry+https://github.com/rust-lang/crates.io-index"
1649 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1650 |
1651 | [[package]]
1652 | name = "windows"
1653 | version = "0.46.0"
1654 | source = "registry+https://github.com/rust-lang/crates.io-index"
1655 | checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25"
1656 | dependencies = [
1657 | "windows-targets 0.42.2",
1658 | ]
1659 |
1660 | [[package]]
1661 | name = "windows-sys"
1662 | version = "0.45.0"
1663 | source = "registry+https://github.com/rust-lang/crates.io-index"
1664 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
1665 | dependencies = [
1666 | "windows-targets 0.42.2",
1667 | ]
1668 |
1669 | [[package]]
1670 | name = "windows-sys"
1671 | version = "0.48.0"
1672 | source = "registry+https://github.com/rust-lang/crates.io-index"
1673 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
1674 | dependencies = [
1675 | "windows-targets 0.48.0",
1676 | ]
1677 |
1678 | [[package]]
1679 | name = "windows-targets"
1680 | version = "0.42.2"
1681 | source = "registry+https://github.com/rust-lang/crates.io-index"
1682 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
1683 | dependencies = [
1684 | "windows_aarch64_gnullvm 0.42.2",
1685 | "windows_aarch64_msvc 0.42.2",
1686 | "windows_i686_gnu 0.42.2",
1687 | "windows_i686_msvc 0.42.2",
1688 | "windows_x86_64_gnu 0.42.2",
1689 | "windows_x86_64_gnullvm 0.42.2",
1690 | "windows_x86_64_msvc 0.42.2",
1691 | ]
1692 |
1693 | [[package]]
1694 | name = "windows-targets"
1695 | version = "0.48.0"
1696 | source = "registry+https://github.com/rust-lang/crates.io-index"
1697 | checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
1698 | dependencies = [
1699 | "windows_aarch64_gnullvm 0.48.0",
1700 | "windows_aarch64_msvc 0.48.0",
1701 | "windows_i686_gnu 0.48.0",
1702 | "windows_i686_msvc 0.48.0",
1703 | "windows_x86_64_gnu 0.48.0",
1704 | "windows_x86_64_gnullvm 0.48.0",
1705 | "windows_x86_64_msvc 0.48.0",
1706 | ]
1707 |
1708 | [[package]]
1709 | name = "windows_aarch64_gnullvm"
1710 | version = "0.42.2"
1711 | source = "registry+https://github.com/rust-lang/crates.io-index"
1712 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
1713 |
1714 | [[package]]
1715 | name = "windows_aarch64_gnullvm"
1716 | version = "0.48.0"
1717 | source = "registry+https://github.com/rust-lang/crates.io-index"
1718 | checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
1719 |
1720 | [[package]]
1721 | name = "windows_aarch64_msvc"
1722 | version = "0.42.2"
1723 | source = "registry+https://github.com/rust-lang/crates.io-index"
1724 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
1725 |
1726 | [[package]]
1727 | name = "windows_aarch64_msvc"
1728 | version = "0.48.0"
1729 | source = "registry+https://github.com/rust-lang/crates.io-index"
1730 | checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
1731 |
1732 | [[package]]
1733 | name = "windows_i686_gnu"
1734 | version = "0.42.2"
1735 | source = "registry+https://github.com/rust-lang/crates.io-index"
1736 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
1737 |
1738 | [[package]]
1739 | name = "windows_i686_gnu"
1740 | version = "0.48.0"
1741 | source = "registry+https://github.com/rust-lang/crates.io-index"
1742 | checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
1743 |
1744 | [[package]]
1745 | name = "windows_i686_msvc"
1746 | version = "0.42.2"
1747 | source = "registry+https://github.com/rust-lang/crates.io-index"
1748 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
1749 |
1750 | [[package]]
1751 | name = "windows_i686_msvc"
1752 | version = "0.48.0"
1753 | source = "registry+https://github.com/rust-lang/crates.io-index"
1754 | checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
1755 |
1756 | [[package]]
1757 | name = "windows_x86_64_gnu"
1758 | version = "0.42.2"
1759 | source = "registry+https://github.com/rust-lang/crates.io-index"
1760 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
1761 |
1762 | [[package]]
1763 | name = "windows_x86_64_gnu"
1764 | version = "0.48.0"
1765 | source = "registry+https://github.com/rust-lang/crates.io-index"
1766 | checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
1767 |
1768 | [[package]]
1769 | name = "windows_x86_64_gnullvm"
1770 | version = "0.42.2"
1771 | source = "registry+https://github.com/rust-lang/crates.io-index"
1772 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
1773 |
1774 | [[package]]
1775 | name = "windows_x86_64_gnullvm"
1776 | version = "0.48.0"
1777 | source = "registry+https://github.com/rust-lang/crates.io-index"
1778 | checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
1779 |
1780 | [[package]]
1781 | name = "windows_x86_64_msvc"
1782 | version = "0.42.2"
1783 | source = "registry+https://github.com/rust-lang/crates.io-index"
1784 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
1785 |
1786 | [[package]]
1787 | name = "windows_x86_64_msvc"
1788 | version = "0.48.0"
1789 | source = "registry+https://github.com/rust-lang/crates.io-index"
1790 | checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
1791 |
--------------------------------------------------------------------------------
/server/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "proxy-proxy-proxyer"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 |
8 | [dependencies]
9 | anyhow = "1.0.70"
10 | chrono = "0.4.24"
11 | clap = { version = "4.2.1", features = ["derive"] }
12 | #clap = { version = "4.1.11", features = ["derive"] }
13 | #futures-util = "0.3.27"
14 | hyper = { version = "0.14.25", features = ["full"] }
15 | hyper-trust-dns = "0.5.0"
16 | once_cell = "1.17.1"
17 | sha256 = "1.1.2"
18 | tls-parser = "0.11.0"
19 | tokio = { version = "1.26.0", features = ["full"] }
20 | #tower = "0.4.13"
21 | tracing = "0.1.37"
22 | tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
23 |
--------------------------------------------------------------------------------
/server/flake.lock:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": {
3 | "fenix": {
4 | "inputs": {
5 | "nixpkgs": "nixpkgs",
6 | "rust-analyzer-src": "rust-analyzer-src"
7 | },
8 | "locked": {
9 | "lastModified": 1679984598,
10 | "narHash": "sha256-0WLOZveWNqfLbG04AokSLBvt13uH0obEXHCaHJJzYQQ=",
11 | "owner": "nix-community",
12 | "repo": "fenix",
13 | "rev": "cd1d2eb0f33b0dde9c2a95b56e4ca823873859ef",
14 | "type": "github"
15 | },
16 | "original": {
17 | "owner": "nix-community",
18 | "repo": "fenix",
19 | "type": "github"
20 | }
21 | },
22 | "flake-utils": {
23 | "locked": {
24 | "lastModified": 1678901627,
25 | "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
26 | "owner": "numtide",
27 | "repo": "flake-utils",
28 | "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
29 | "type": "github"
30 | },
31 | "original": {
32 | "owner": "numtide",
33 | "repo": "flake-utils",
34 | "type": "github"
35 | }
36 | },
37 | "naersk": {
38 | "inputs": {
39 | "nixpkgs": "nixpkgs_2"
40 | },
41 | "locked": {
42 | "lastModified": 1679567394,
43 | "narHash": "sha256-ZvLuzPeARDLiQUt6zSZFGOs+HZmE+3g4QURc8mkBsfM=",
44 | "owner": "nix-community",
45 | "repo": "naersk",
46 | "rev": "88cd22380154a2c36799fe8098888f0f59861a15",
47 | "type": "github"
48 | },
49 | "original": {
50 | "owner": "nix-community",
51 | "repo": "naersk",
52 | "type": "github"
53 | }
54 | },
55 | "nixpkgs": {
56 | "locked": {
57 | "lastModified": 1679865578,
58 | "narHash": "sha256-sYQmxxqIYL3QFsRYjW0AufhGur8qWfwoOGPGHRJZlGc=",
59 | "owner": "nixos",
60 | "repo": "nixpkgs",
61 | "rev": "4361baa782dc3d3b35fd455a1adc370681d9187c",
62 | "type": "github"
63 | },
64 | "original": {
65 | "owner": "nixos",
66 | "ref": "nixos-unstable",
67 | "repo": "nixpkgs",
68 | "type": "github"
69 | }
70 | },
71 | "nixpkgs_2": {
72 | "locked": {
73 | "lastModified": 1679999353,
74 | "narHash": "sha256-Gv9FpNoQqVtRWaNHJF7s6CguT5AT/HZkAvHJQVpLgw8=",
75 | "owner": "NixOS",
76 | "repo": "nixpkgs",
77 | "rev": "98f3b08f58ff125ef02d55cd52a83f44f245f2ea",
78 | "type": "github"
79 | },
80 | "original": {
81 | "id": "nixpkgs",
82 | "type": "indirect"
83 | }
84 | },
85 | "nixpkgs_3": {
86 | "locked": {
87 | "lastModified": 1679999353,
88 | "narHash": "sha256-Gv9FpNoQqVtRWaNHJF7s6CguT5AT/HZkAvHJQVpLgw8=",
89 | "owner": "NixOS",
90 | "repo": "nixpkgs",
91 | "rev": "98f3b08f58ff125ef02d55cd52a83f44f245f2ea",
92 | "type": "github"
93 | },
94 | "original": {
95 | "owner": "NixOS",
96 | "ref": "nixpkgs-unstable",
97 | "repo": "nixpkgs",
98 | "type": "github"
99 | }
100 | },
101 | "root": {
102 | "inputs": {
103 | "fenix": "fenix",
104 | "flake-utils": "flake-utils",
105 | "naersk": "naersk",
106 | "nixpkgs": "nixpkgs_3"
107 | }
108 | },
109 | "rust-analyzer-src": {
110 | "flake": false,
111 | "locked": {
112 | "lastModified": 1679958651,
113 | "narHash": "sha256-AOiqocXIFeAvEMv8VSQQU+omhU9ifgGj43IcHwsu3rg=",
114 | "owner": "rust-lang",
115 | "repo": "rust-analyzer",
116 | "rev": "a869ca3c29c19c7467864fc44a28877610433afe",
117 | "type": "github"
118 | },
119 | "original": {
120 | "owner": "rust-lang",
121 | "ref": "nightly",
122 | "repo": "rust-analyzer",
123 | "type": "github"
124 | }
125 | }
126 | },
127 | "root": "root",
128 | "version": 7
129 | }
130 |
--------------------------------------------------------------------------------
/server/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | inputs = {
3 | fenix.url = "github:nix-community/fenix";
4 | flake-utils.url = "github:numtide/flake-utils";
5 | naersk.url = "github:nix-community/naersk";
6 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
7 | };
8 |
9 | outputs = { self, fenix, flake-utils, naersk, nixpkgs }:
10 | flake-utils.lib.eachDefaultSystem (
11 | system: let
12 | pkgs = (import nixpkgs) {
13 | inherit system;
14 | };
15 |
16 | toolchain = with fenix.packages.${system};
17 | combine [
18 | minimal.rustc
19 | minimal.cargo
20 | targets.x86_64-unknown-linux-musl.latest.rust-std
21 | ];
22 |
23 | naersk' = naersk.lib.${system}.override {
24 | cargo = toolchain;
25 | rustc = toolchain;
26 | };
27 |
28 | in rec {
29 | defaultPackage = naersk'.buildPackage {
30 | src = ./.;
31 | doCheck = true;
32 | nativeBuildInputs = with pkgs; [ pkgsStatic.stdenv.cc ];
33 |
34 | # Tells Cargo that we're building for musl.
35 | # (https://doc.rust-lang.org/cargo/reference/config.html#buildtarget)
36 | CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
37 |
38 | # Tells Cargo to enable static compilation.
39 | # (https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags)
40 | #
41 | # Note that the resulting binary might still be considered dynamically
42 | # linked by ldd, but that's just because the binary might have
43 | # position-independent-execution enabled.
44 | # (see: https://github.com/rust-lang/rust/issues/79624#issuecomment-737415388)
45 | CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static";
46 | };
47 | }
48 | );
49 | }
50 |
--------------------------------------------------------------------------------
/server/src/auth.rs:
--------------------------------------------------------------------------------
1 | pub const HASH_LENGTH: usize = 64;
2 | use std::ops::Deref;
3 |
4 | use crate::PROXY_PW;
5 | use chrono::Timelike;
6 |
7 | pub fn make_auth_with_hour(uri: &str, hour: u16) -> String {
8 | sha256::digest(format!("{hour}#{}#{uri}", PROXY_PW.deref()))
9 | }
10 |
11 | #[tracing::instrument]
12 | pub fn verify_auth(auth: &str, uri: &str) -> bool {
13 | let hour = chrono::offset::Utc::now().hour();
14 | for offset in 23..=25 {
15 | let hour = (hour + offset) % 24;
16 | let should_be = make_auth_with_hour(uri, hour as u16);
17 | if should_be == auth {
18 | return true;
19 | } else {
20 | tracing::debug!("auth does not match {should_be}");
21 | }
22 | }
23 | false
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/server/src/main.rs:
--------------------------------------------------------------------------------
1 | mod auth;
2 | mod proxy_http;
3 | mod proxy_tls;
4 |
5 | use clap::Parser;
6 | use once_cell::sync::Lazy;
7 |
8 | #[derive(Debug, Clone, Parser)]
9 | struct Opts {
10 | #[clap(short, long, required = true)]
11 | /// The password.
12 | /// Make sure this is the same as the password passed to the client.
13 | password: String,
14 | }
15 |
16 | // Password never changes, so make it global
17 | pub static PROXY_PW: Lazy<&'static str> = Lazy::new(|| {
18 | let opts = Opts::parse();
19 | Box::leak(opts.password.into_boxed_str())
20 | });
21 |
22 | #[tokio::main]
23 | async fn main() -> anyhow::Result<()> {
24 | use tracing_subscriber::{fmt, prelude::*, EnvFilter};
25 |
26 | tracing_subscriber::registry()
27 | .with(fmt::layer())
28 | .with(EnvFilter::from_default_env())
29 | .init();
30 |
31 | let (_res1, _res2) = tokio::join!(
32 | tokio::task::spawn(proxy_tls::main()),
33 | tokio::task::spawn(proxy_http::main())
34 | );
35 | Ok(())
36 | }
37 |
--------------------------------------------------------------------------------
/server/src/proxy_http.rs:
--------------------------------------------------------------------------------
1 | use std::convert::Infallible;
2 | use std::net::SocketAddr;
3 |
4 | use anyhow::Context;
5 | use hyper::service::{make_service_fn, service_fn};
6 | use hyper::{Body, Client, Request, Response, Server, StatusCode, Uri};
7 |
8 | type HttpClient = Client;
9 |
10 | pub async fn main() {
11 | let addr = SocketAddr::from(([0, 0, 0, 0], 80));
12 |
13 | let client = Client::builder()
14 | .http1_title_case_headers(true)
15 | .http1_preserve_header_case(true)
16 | .build_http();
17 |
18 | let make_service = make_service_fn(move |_| {
19 | let client = client.clone();
20 | async move { Ok::<_, Infallible>(service_fn(move |req| proxy(client.clone(), req))) }
21 | });
22 |
23 | let server = Server::bind(&addr)
24 | .http1_preserve_header_case(true)
25 | .http1_title_case_headers(true)
26 | .serve(make_service);
27 |
28 | println!("HTTP listener ready");
29 |
30 | if let Err(e) = server.await {
31 | eprintln!("server error: {}", e);
32 | }
33 | }
34 |
35 | fn bad_request() -> Response {
36 | Response::builder()
37 | .status(StatusCode::BAD_REQUEST)
38 | .body(Body::empty())
39 | .unwrap()
40 | }
41 |
42 | async fn proxy(client: HttpClient, mut req: Request) -> anyhow::Result> {
43 | tracing::debug!("got HTTP request {:?}", req);
44 | let uri = req.headers()
45 | .get("X-Proxyer-Proxy-Dest")
46 | .and_then(|val| val.to_str().ok())
47 | .and_then(|val| val.parse::().ok())
48 | .ok_or(anyhow::anyhow!("bad URI given"))?;
49 | if !do_auth(&req, &uri) {
50 | return Ok(bad_request());
51 | }
52 | *req.uri_mut() = uri.clone();
53 | req.headers_mut().remove("X-Proxyer-Proxy-Dest");
54 | req.headers_mut().remove("X-Proxyer-Proxy-Auth");
55 | let real_host = req.headers_mut().remove("X-Proxyer-Real-Host");
56 | if let Some(real_host) = real_host {
57 | req.headers_mut().insert("Host", real_host);
58 | } else {
59 | // try to guess
60 | req.headers_mut().insert("Host", uri.to_string().try_into().context("URI is not ASCII")?);
61 | }
62 | tracing::debug!("sending HTTP request {:?}", req);
63 | Ok(client.request(req).await?)
64 | }
65 |
66 | pub fn do_auth(req: &Request, uri: &Uri) -> bool {
67 | if let Some(auth) = req.headers().get("X-Proxyer-Proxy-Auth") {
68 | if let Ok(auth) = auth.to_str() {
69 | let uri_str = uri.to_string();
70 | tracing::debug!("uri: {}", uri_str);
71 | if crate::auth::verify_auth(auth, &format!("{}", uri_str)) {
72 | return true;
73 | }
74 | }
75 | }
76 | false
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/server/src/proxy_tls.rs:
--------------------------------------------------------------------------------
1 | use anyhow::{anyhow, bail, Context};
2 | use tls_parser::{SNIType, TlsClientHelloContents, TlsExtension, TlsMessage, TlsMessageHandshake};
3 | use tokio::{
4 | io::{self, AsyncReadExt, AsyncWriteExt},
5 | net::{TcpListener, TcpStream},
6 | };
7 |
8 | type AResult = anyhow::Result;
9 |
10 | fn dbg_err(d: D) -> anyhow::Error {
11 | anyhow!(format!("{:?}", d))
12 | }
13 |
14 | // returns (sni, head) tuple
15 | // this is inefficient but i can't figure out a better way to do it
16 | async fn get_sni(sock: &mut TcpStream) -> Result<(Vec, Vec), anyhow::Error> {
17 | const AT_A_TIME: usize = 1024;
18 | let mut packet_buf = Vec::new();
19 | let (_, packet) = loop {
20 | let len = packet_buf.len();
21 | packet_buf.resize(len + AT_A_TIME, 0u8);
22 | let n = sock
23 | .read(&mut packet_buf[len..])
24 | .await
25 | .context("sock.read(&packet)")?;
26 | packet_buf.truncate(len + n);
27 | match tls_parser::parse_tls_plaintext(&packet_buf) {
28 | Ok(parsed) => break parsed,
29 | Err(err) => match err {
30 | tls_parser::Err::Incomplete(_) => {
31 | tracing::debug!("tls parse incomplete, packet size > {}", packet_buf.len());
32 | }
33 | _ => return Err(anyhow!(dbg_err(err)).context("parse_tls_plaintext")),
34 | },
35 | }
36 | if n == 0 {
37 | // EOF, just stop here
38 | bail!("TLS parsing hit EOF before completion");
39 | }
40 | };
41 | tracing::debug!("tls record parse complete");
42 | let msg = packet
43 | .msg
44 | .first()
45 | .ok_or(anyhow!("no message in TLS packet"))?;
46 | match msg {
47 | TlsMessage::Handshake(TlsMessageHandshake::ClientHello(TlsClientHelloContents {
48 | ext: Some(ext_buf),
49 | ..
50 | })) => {
51 | let (_, exts) = tls_parser::parse_tls_client_hello_extensions(ext_buf)
52 | .map_err(dbg_err)
53 | .context("parse_tls_client_hello_extensions")?;
54 | let mut server_name: Option> = None;
55 | for ext in exts {
56 | if let TlsExtension::SNI(snis) = ext {
57 | if let Some((SNIType::HostName, srv_name)) = snis.first() {
58 | server_name = Some(srv_name.to_vec());
59 | }
60 | }
61 | }
62 | if let Some(server_name) = server_name {
63 | Ok((server_name, packet_buf))
64 | } else {
65 | bail!("No SNI found")
66 | }
67 | }
68 | _ => bail!("TLS message was not a handshake/ClientHello"),
69 | }
70 | }
71 |
72 | async fn proxy_tls(sock: TcpStream) {
73 | if let Err(e) = real_proxy_tls(sock).await {
74 | tracing::debug!("proxy_tls: {:?}", e);
75 | }
76 | }
77 | async fn real_proxy_tls(mut sock: TcpStream) -> AResult<()> {
78 | tracing::info!("got connection");
79 | let mut authbuf = [0u8; crate::auth::HASH_LENGTH];
80 | sock.read_exact(&mut authbuf)
81 | .await
82 | .context("sock.read_exact")?;
83 | let auth = std::str::from_utf8(&authbuf).context("authbuf not valid UTF-8")?;
84 | tracing::debug!("got auth = {:?}", auth);
85 | let (server_name, head) = get_sni(&mut sock).await.context("get_sni")?;
86 | let mut server_name = String::from_utf8(server_name).context("non-utf8 server name")?;
87 | server_name += ":443";
88 | if !crate::auth::verify_auth(auth, &server_name) {
89 | bail!("bad auth");
90 | }
91 | tracing::debug!("good auth");
92 | let mut other_side = TcpStream::connect(&server_name)
93 | .await
94 | .with_context(|| format!("TcpStream::connect({server_name})"))?;
95 | other_side
96 | .write_all(&head)
97 | .await
98 | .context("other_side.write_all(&head)")?;
99 | tracing::debug!("calling copy_bidirectional");
100 | let (left ,right) = tokio::io::copy_bidirectional(&mut sock, &mut other_side)
101 | .await
102 | .context("copy_bidirectional")?;
103 | tracing::debug!("transferred to remote = {right} bytes, transferred to user = {left} bytes");
104 | Ok(())
105 | }
106 |
107 | pub async fn main() -> io::Result<()> {
108 | let listener = TcpListener::bind("0.0.0.0:443").await?;
109 | println!("TLS listener ready");
110 |
111 | loop {
112 | let (socket, _) = listener.accept().await?;
113 | tokio::task::spawn(proxy_tls(socket));
114 | }
115 | }
116 |
--------------------------------------------------------------------------------