├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitlab ├── issue_templates │ ├── Bug.md │ └── Feature.md └── merge_request_templates │ └── Merge Request.md ├── .seed-config.yaml ├── .travis.yml ├── CHANGELOG.md ├── CLA ├── CORPORATE_CONTRIBUTOR_LICENSE_AGREEMENT.md └── INDIVIDUAL_CONTRIBUTOR_LICENSE_AGREEMENT.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── OWNERS ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── VERSION ├── VISION.md ├── client.go ├── cmd └── torproxy │ └── main.go ├── config.go ├── docs ├── LICENSE ├── README.md └── configuration.md ├── go.mod ├── go.sum ├── response.go ├── setup.go ├── setup_test.go └── torproxy.go /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 5 | **Is this a BUG REPORT or FEATURE REQUEST?**: 6 | bug | feature 7 | 8 | **What happened**: 9 | 10 | **What you expected to happen**: 11 | 12 | **How to reproduce it (as minimally and precisely as possible)**: 13 | 14 | **Anything else we need to know?**: 15 | 16 | **Environment**: 17 | - Torproxy version: 18 | - Others: 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 5 | **What this PR does / why we need it**: 6 | 7 | 11 | 12 | **Special notes for your reviewer**: 13 | 14 | **Release note**: 15 | 18 | ```release-note 19 | 20 | ``` 21 | -------------------------------------------------------------------------------- /.gitlab/issue_templates/Bug.md: -------------------------------------------------------------------------------- 1 | 5 | **Bug report** 6 | 7 | **What happened**: 8 | 9 | **What you expected to happen**: 10 | 11 | **How to reproduce it (as minimally and precisely as possible)**: 12 | 13 | **Anything else we need to know?**: 14 | 15 | **Environment**: 16 | - Torproxy version: 17 | - Others: 18 | -------------------------------------------------------------------------------- /.gitlab/issue_templates/Feature.md: -------------------------------------------------------------------------------- 1 | 5 | **Feature request** 6 | 7 | **What this feature does / why we need it**: 8 | 9 | **Which issue this feature fix (if any)** 10 | 11 | **Anything else we need to know?**: 12 | -------------------------------------------------------------------------------- /.gitlab/merge_request_templates/Merge Request.md: -------------------------------------------------------------------------------- 1 | 5 | **What this PR does / why we need it**: 6 | 7 | 11 | 12 | **Special notes for your reviewer**: 13 | 14 | **Release note**: 15 | 18 | ```release-note 19 | 20 | ``` 21 | -------------------------------------------------------------------------------- /.seed-config.yaml: -------------------------------------------------------------------------------- 1 | project: 2 | name: "Torproxy" 3 | oneLiner: "An easy way to proxy your http requests through the onion network" 4 | state: "beta" 5 | image: "" 6 | website: "https://torproxy.okkur.org" 7 | description: | 8 | Route your http requests through the onion network without Tor browser 9 | version: "v0.3.1" 10 | 11 | vision: 12 | type: "community" 13 | overview: | 14 | Providing a fast and simple way to proxy your http requests through the onion network 15 | items: 16 | - "Simple and minimal config" 17 | - "Proxy multiple hosts to a single endpoint" 18 | concept: "Torproxy's core concept is to provide a simple way to proxy your http requsts using Caddy without needing to write complex logics and config" 19 | aim: "Our aim is to provide a secure and easy way to access onion network on any device." 20 | 21 | contributionLinks: 22 | issueTemplate: "/.github/ISSUE_TEMPLATE.md" 23 | starterIssues: "https://github.com/okkur/torproxy/labels/starter%20issue" 24 | 25 | supportLinks: 26 | documentation: "https://torproxy.okkur.org/docs" 27 | 28 | readme: 29 | usageExample: | 30 | Note: The `master` branch is using [Caddy v2](https://caddyserver.com/), if you 31 | want to use Torproxy with previous caddy versions, check the `caddy-v1` branch. 32 | 33 | If you want Torproxy to start a fresh instance of Tor, you need to install Tor 34 | on your machine. Take a look at the [Tor download instructions](https://www.torproject.org/download/) 35 | 36 | You can get torproxy as a plugin on Caddy's `v1` [build server](https://caddyserver.com/download). 37 | 38 | Or install torproxy's `v2` version using `go get`: 39 | ``` 40 | go get go.okkur.org/torproxy/cmd/torproxy 41 | ``` 42 | 43 | Create a config file like the example below. For more information about the 44 | available config options, check the [Configuration](/docs/configuration.md) page. 45 | ``` 46 | example.test { 47 | torproxy example.test somewhereonthe.onion 48 | } 49 | ``` 50 | 51 | You can run torproxy with Caddyfile config adapter using this command: 52 | ``` 53 | torproxy start -config torproxy.config -adapter caddyfile 54 | ``` 55 | 56 | docs: 57 | development: | 58 | Run the following command to get torproxy's source code and switch your working directory to the torproxy repository 59 | ``` 60 | git clone github.com/okkur/torproxy && cd torproxy 61 | ``` 62 | 63 | Then run the following command to build torproxy 64 | ``` 65 | make build 66 | ``` 67 | 68 | Do not forget to install Tor itself on your machine since torproxy needs that to operate correctly. 69 | 70 | emails: 71 | commercialSupport: "support@okkur.org" 72 | security: "security@okkur.org" 73 | coc: "coc@okkur.org" 74 | 75 | copyright: 76 | owner: "The Torproxy authors" 77 | year: "2019" 78 | 79 | cla: 80 | copyrightHolder: "nzt.ventures GmbH" 81 | mail: "legal@nzt.ventures" 82 | 83 | maintainers: 84 | - name: "Michael Grosser" 85 | nick: "stp-ip" 86 | 87 | repo: 88 | link: "https://torproxy.okkur.org/code" 89 | type: "Github" 90 | 91 | badges: 92 | - image: "https://img.shields.io/badge/state-beta-blue.svg" 93 | alt: "state" 94 | - image: "https://img.shields.io/github/release/okkur/torproxy.svg" 95 | link: "https://torproxy.okkur.org/releases/" 96 | alt: "release" 97 | - image: "https://img.shields.io/github/license/okkur/torproxy.svg" 98 | link: "LICENSE" 99 | alt: "license" 100 | 101 | reposeed: 102 | configVersion: "v1" 103 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: minimal 2 | 3 | services: 4 | - docker 5 | 6 | script: 7 | - make docker-test 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 18 | 19 | # v0.3.1 20 | 21 | _2020-04-23_ 22 | 23 | - [Downloads for v0.3.1](https://torproxy.okkur.org/releases/v0.3.1) 24 | - [Changelog since v0.3.0](#changes-since-v030) 25 | - [Documentation for v0.3.1](#documentation-for-v031) 26 | 27 | ## Documentation for v0.3.1 28 | 29 | [Documentation](https://torproxy.okkur.org/docs/) 30 | 31 | ## Changes since v0.3.0 32 | 33 | - Fix null pointer error in start 34 | - Use Go's internal reverse proxy module instead of Caddy 35 | 36 | --- 37 | 38 | # v0.3.0 39 | 40 | _2020-03-23_ 41 | 42 | - [Downloads for v0.3.0](https://torproxy.okkur.org/releases/v0.3.0) 43 | - [Changelog since v0.2.1](#changes-since-v021) 44 | - [Documentation for v0.3.0](#documentation-for-v030) 45 | 46 | ## Documentation for v0.3.0 47 | 48 | [Documentation](https://torproxy.okkur.org/docs/) 49 | 50 | ## Changes since v0.2.1 51 | 52 | - Upgrade the master branch to [Caddy v2](https://caddyserver.com/) 53 | - Use the new reverse proxy module 54 | - Add the `host` field to config for supporting custom Tor instances 55 | 56 | ## Fixes since v0.2.1 57 | 58 | - Fix the config parser bugs 59 | 60 | --- 61 | 62 | # v0.2.1 63 | 64 | _2020-01-23_ 65 | 66 | - [Downloads for v0.2.1](https://torproxy.okkur.org/releases/v0.2.1) 67 | - [Changelog since v0.2.0](#changes-since-v020) 68 | - [Documentation for v0.2.1](#documentation-for-v021) 69 | 70 | ## Documentation for v0.2.1 71 | 72 | [Documentation](https://torproxy.okkur.org/docs/) 73 | 74 | ## Changes since v0.2.0 75 | 76 | - Branch off Caddy v1 support 77 | - Update deps 78 | - Add makefile 79 | 80 | --- 81 | 82 | # v0.2.0 83 | 84 | _2019-07-30_ 85 | 86 | - [Downloads for v0.2.0](https://torproxy.okkur.org/releases/v0.2.0) 87 | - [Changelog since v0.1.0](#changes-since-v010) 88 | - [Documentation for v0.2.0](#documentation-for-v020) 89 | 90 | ## Documentation for v0.2.0 91 | 92 | [Documentation](https://torproxy.okkur.org/docs/) 93 | 94 | ## Changes since v0.1.0 95 | 96 | - Use vanity go imports 97 | - Update docs 98 | 99 | --- 100 | 101 | # v0.1.0 102 | 103 | _2019-07-10_ 104 | 105 | - [Downloads for v0.1.0](https://torproxy.okkur.org/releases/v0.1.0) 106 | - [Changelog since v0.0.0](#changes-since-v000) 107 | - [Documentation for v0.1.0](#documentation-for-v010) 108 | 109 | ## Documentation for v0.1.0 110 | 111 | [Documentation](https://torproxy.okkur.org/docs/) 112 | 113 | ## Changes since v0.0.0 114 | 115 | - Split out http based Tor proxy code from TXTDirect 116 | -------------------------------------------------------------------------------- /CLA/CORPORATE_CONTRIBUTOR_LICENSE_AGREEMENT.md: -------------------------------------------------------------------------------- 1 | # Corporate contributor license agreement 2 | 3 | You accept and agree to the following terms and conditions for Your present and future Contributions submitted to nzt.ventures GmbH. Except for the license granted herein to nzt.ventures GmbH and recipients of software distributed by nzt.ventures GmbH, You reserve all right, title, and interest in and to Your Contributions. 4 | 5 | 1. Definitions. 6 | 7 | "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with nzt.ventures GmbH. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 8 | 9 | "Contribution" shall mean the code, documentation or other original works of authorship, including any modifications or additions to an existing work, that is submitted by You to nzt.ventures GmbH for inclusion in, or documentation of, any of the products owned or managed by nzt.ventures GmbH (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to nzt.ventures GmbH or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, nzt.ventures GmbH for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 10 | 11 | 2. Grant of Copyright License. 12 | 13 | Subject to the terms and conditions of this Agreement, You hereby grant to nzt.ventures GmbH and to recipients of software distributed by nzt.ventures GmbH a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 14 | 15 | 3. Grant of Patent License. 16 | 17 | Subject to the terms and conditions of this Agreement, You hereby grant to nzt.ventures GmbH and to recipients of software distributed by nzt.ventures GmbH a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 18 | 19 | 4. You represent that You are legally entitled to grant the above license. You represent further that each of Your employees is authorized to submit Contributions on Your behalf, but excluding employees that are designated in writing by You as "Not authorized to submit Contributions on behalf of [name of Your corporation here]." Such designations of exclusion for unauthorized employees are to be submitted via email to legal@nzt.ventures. 20 | 21 | 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). 22 | 23 | 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 24 | 25 | 7. Should You wish to submit work that is not Your original creation, You may submit it to nzt.ventures GmbH separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". 26 | 27 | 8. It is Your responsibility to notify nzt.ventures GmbH when any change is required to the list of designated employees excluded from submitting Contributions on Your behalf per Section 4. Such notification should be sent via email to legal@nzt.ventures. 28 | 29 | This text is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. 30 | -------------------------------------------------------------------------------- /CLA/INDIVIDUAL_CONTRIBUTOR_LICENSE_AGREEMENT.md: -------------------------------------------------------------------------------- 1 | # Individual contributor license agreement 2 | 3 | You accept and agree to the following terms and conditions for Your present and future Contributions submitted to nzt.ventures GmbH Except for the license granted herein to nzt.ventures GmbH and recipients of software distributed by nzt.ventures GmbH, You reserve all right, title, and interest in and to Your Contributions. 4 | 5 | 1. Definitions. 6 | 7 | "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with nzt.ventures GmbH. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 8 | 9 | "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to nzt.ventures GmbH for inclusion in, or documentation of, any of the products owned or managed by nzt.ventures GmbH (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to nzt.ventures GmbH or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, nzt.ventures GmbH for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 10 | 11 | 2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to nzt.ventures GmbH and to recipients of software distributed by nzt.ventures GmbH a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. 12 | 13 | 3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to nzt.ventures GmbH and to recipients of software distributed by nzt.ventures GmbH a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. 14 | 15 | 4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to nzt.ventures GmbH, or that your employer has executed a separate Corporate CLA with nzt.ventures GmbH. 16 | 17 | 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. 18 | 19 | 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 20 | 21 | 7. Should You wish to submit work that is not Your original creation, You may submit it to nzt.ventures GmbH separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [insert_name_here]". 22 | 23 | 8. You agree to notify nzt.ventures GmbH of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. 24 | 25 | This text is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office. 26 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at coc@okkur.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributor license agreement 2 | 3 | By submitting code as an individual you agree to the 4 | [individual contributor license agreement](/CLA/INDIVIDUAL_CONTRIBUTOR_LICENSE_AGREEMENT.md). 5 | By submitting code as an entity you agree to the 6 | [corporate contributor license agreement](/CLA/CORPORATE_CONTRIBUTOR_LICENSE_AGREEMENT.md). 7 | 8 | 9 | 10 | --- 11 | 12 | ## Contribute to Project 13 | 14 | Thank you for your interest in contributing to Torproxy. 15 | This guide helps make contributing to Torproxy simple and efficient for everyone. 16 | 17 | ### First contribution 18 | 19 | If you are starting out contributing to Torproxy, there might be smaller scoped "starter issues" available: 20 | [Current starter issues](https://github.com/okkur/torproxy/labels/starter%20issue) 21 | 22 | ### Report bug 23 | 24 | If you are sure you found a bug and no issue exists yet, please feel free to create an issue following the [issue template](/.github/ISSUE_TEMPLATE.md). 25 | 26 | ### New feature 27 | 28 | As your time is precious and not all features might be in the scope of what the Torproxy wants to achieve, please open up an issue first. 29 | 30 | It would be helpful to answer some questions: 31 | * Why do you need this feature? 32 | * Why do you think it might be valuable for other users? 33 | * How would you implement the feature? 34 | 35 | ## Helping Others 36 | 37 | Please help other users whenever you can. 38 | 39 | 40 | 41 | ## User Support/Questions 42 | 43 | Non technical or user centric support might be available from the community for more information read our [support guidelines](/SUPPORT.md) 44 | 45 | ## Issue/Pull Request/Merge Request Closing Policy 46 | 47 | Time is precious and sparse, please consider this and search through available issues first. 48 | 49 | Treat every participant with courtesy, respect and add as much information when creating an issue or pull/merge request. 50 | 51 | All issues and pull/merge requests should be in English and refrain from using any inappropriate language. 52 | 53 | Any issues or pull/merge requests not following our [code of conduct](/CODE_OF_CONDUCT.md) or any other guidelines provided may be closed without notice out of respect for our volunteers. 54 | 55 | Inactive issues or pull/merge requests may be closed after a specific period. This enables us to focus and work on the current/primary items. 56 | 57 | ### Pull Request/Merge Request Guidelines 58 | 59 | Please keep the change in a single pull/merge request **as small as possible**. 60 | If you want to contribute a large feature think very hard what the minimum viable change is. 61 | The smaller a pull/merge request is the more likely it is it will be merged (quickly). 62 | Afterwards follow-up requests for enhancements are appreciated. 63 | 64 | ### Contribution Acceptance Criteria 65 | 66 | * The change is as small as possible 67 | * Includes proper tests and passes all tests 68 | * Does not break any existing functionality 69 | * Fixes one specific issue or implements one specific feature (do not combine things, send separate requests if needed) 70 | * Contains functionality we think other users will benefit from too 71 | * If the request adds any new libraries, they should have a compatible license. 72 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2019 - The Torproxy authors 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BIN := torproxy 2 | MAINTAINER := okkur 3 | VERSION := `cat $(VERSION_FILE)` 4 | IMAGE := $(MAINTAINER)/$(BIN):$(VERSION) 5 | 6 | BUILD_GOOS := $(if $(GOOS),$(GOOS),linux) 7 | BUILD_GOARCH := $(if $(GOARCH),$(GOARCH),amd64) 8 | 9 | CONTAINER ?= $(BIN) 10 | 11 | .DEFAULT_GOAL := build 12 | 13 | build: 14 | cd cmd/torproxy && \ 15 | GO111MODULE=on CGO_ENABLED=0 GOARCH=$(BUILD_GOARCH) GOOS=$(BUILD_GOOS) go build -ldflags="-s -w" 16 | mv cmd/torproxy/torproxy ./$(BIN) 17 | 18 | test: 19 | GO111MODULE=on go test -v `go list ./...` 20 | 21 | image-build: docker-build 22 | docker build -t $(IMAGE) . 23 | 24 | docker-run: image-build 25 | docker run --name $(CONTAINER) $(IMAGE) 26 | 27 | docker-test: 28 | docker run --network=host -v $(shell pwd):/source -v $(GOPATH)/pkg/mod:/go/pkg/mod golang:1.13-alpine /bin/sh \ 29 | -c "cd /source && apk add tor git gcc musl-dev make && GOROOT=\"/usr/local/go\" make test" 30 | 31 | docker-build: 32 | docker run --network=host -v $(shell pwd):/source -v $(GOPATH)/pkg/mod:/go/pkg/mod golang:1.13-alpine /bin/sh \ 33 | -c "cd /source && apk add tor git gcc musl-dev make && make build" 34 | 35 | version: 36 | @echo $(VERSION) 37 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # Current Owners/Maintainers. 2 | Michael Grosser (stp-ip) 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Torproxy 2 | 3 | An easy way to proxy your http requests through the onion network 4 | 5 | [![state](https://img.shields.io/badge/state-beta-blue.svg)]() [![release](https://img.shields.io/github/release/okkur/torproxy.svg)](https://torproxy.okkur.org/releases/) [![license](https://img.shields.io/github/license/okkur/torproxy.svg)](LICENSE) 6 | 7 | **NOTE: This is a beta release, we do not consider it completely production ready yet. Use at your own risk.** 8 | 9 | Route your http requests through the onion network without Tor browser 10 | 11 | ## Using Torproxy 12 | Note: The `master` branch is using [Caddy v2](https://caddyserver.com/), if you 13 | want to use Torproxy with previous caddy versions, check the `caddy-v1` branch. 14 | 15 | If you want Torproxy to start a fresh instance of Tor, you need to install Tor 16 | on your machine. Take a look at the [Tor download instructions](https://www.torproject.org/download/) 17 | 18 | You can get torproxy as a plugin on Caddy's `v1` [build server](https://caddyserver.com/download). 19 | 20 | Or install torproxy's `v2` version using `go get`: 21 | ``` 22 | go get go.okkur.org/torproxy/cmd/torproxy 23 | ``` 24 | 25 | Create a config file like the example below. For more information about the 26 | available config options, check the [Configuration](/docs/configuration.md) page. 27 | ``` 28 | example.test { 29 | torproxy example.test somewhereonthe.onion 30 | } 31 | ``` 32 | 33 | You can run torproxy with Caddyfile config adapter using this command: 34 | ``` 35 | torproxy start -config torproxy.config -adapter caddyfile 36 | ``` 37 | Take a look at our full [documentation](https://torproxy.okkur.org/docs). 38 | 39 | ## Support 40 | For detailed information on support options see our [support guide](/SUPPORT.md). 41 | 42 | ## Helping out 43 | Best place to start is our [contribution guide](/CONTRIBUTING.md). 44 | 45 | ---- 46 | 47 | *Code is licensed under the [Apache License, Version 2.0](/LICENSE).* 48 | *Documentation/examples are licensed under [Creative Commons BY-SA 4.0](/docs/LICENSE).* 49 | *Illustrations, trademarks and third-party resources are owned by their respective party and are subject to different licensing.* 50 | 51 | --- 52 | 53 | Copyright 2019 - The Torproxy authors 54 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Vulnerability Disclosure 2 | 3 | Please report any suspected security vulnerabilities privately to security@okkur.org. 4 | Please do **NOT** create publicly viewable issues for suspected security vulnerabilities. 5 | 6 | We will acknowledge receipt of your vulnerability report as soon as possible and strive to send you regular updates about our progress. 7 | If you're curious about the status of your disclosure please feel free to email us again. 8 | If you want to encrypt your disclosure email please email us to ask for our PGP key. 9 | 10 | Please refrain from requesting compensation for reporting vulnerabilities. 11 | If you want we will publicly acknowledge your responsible disclosure. 12 | We also try to make the issue public after the vulnerability is announced. 13 | Usually bug reports are made public after 30 days, if possible. 14 | 15 | You are not allowed to search for security vulnerabilities on any hosted service of Torproxy without the consent of the party hosting it. 16 | Torproxy is open source software and can be installed for testing and security issues on your own infrastructure. 17 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support using Torproxy 2 | 3 | Welcome to Torproxy! We use Github for tracking bugs and feature requests. 4 | There are helpful volunteers who may be able to help you. 5 | 6 | If it happens that you know the solution to an existing bug, please first open the issue in order to keep track of it. 7 | Afterwards open the relevant pull/merge request that potentially fixes it. 8 | 9 | Please remember this is a community project and you are not entitled to free support. 10 | Be kind to anyone helping out. 11 | 12 | For commercial support reach out to support@okkur.org 13 | 14 | ## Documentation 15 | * [User Documentation](https://torproxy.okkur.org/docs) 16 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | v0.3.1 2 | -------------------------------------------------------------------------------- /VISION.md: -------------------------------------------------------------------------------- 1 | # Vision 2 | Torproxy is a community project. From our current viewpoint, its role is: 3 | Providing a fast and simple way to proxy your http requests through the onion network 4 | 5 | Our detailed items: 6 | * Simple and minimal config 7 | * Proxy multiple hosts to a single endpoint 8 | 9 | ## Core Concept 10 | Torproxy's core concept is to provide a simple way to proxy your http requsts using Caddy without needing to write complex logics and config 11 | 12 | ## General Aim 13 | Our aim is to provide a secure and easy way to access onion network on any device. 14 | 15 | ## Communication 16 | A lot of discussion about Torproxy happens within Github issues. Ideally, we will keep it that way until Torproxy becomes big enough that this turns into a problem. The advantages of this is that all documentation and issues are publicly searchable and easily linked to the source code. 17 | 18 | ## Contributions 19 | The Torproxy project should always aim to devote a lot of time to making contributors feel like an important part of the community. We should strive to provide a place for anyone to be able to contribute. The aim of the core team should be to work on ways to showcase contributions, encourage adoption and show off great work. An example of where this worked is the [CocoaPods Quality Index](http://blog.cocoapods.org/CocoaPods.org-Two-point-Five/). 20 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package torproxy 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "log" 8 | "strconv" 9 | 10 | "github.com/cretz/bine/tor" 11 | ) 12 | 13 | func (t *Tor) Start() { 14 | torInstance, err := tor.Start(nil, t.starterConfig(t.debugger)) 15 | if err != nil { 16 | log.Panicf("Unable to start Tor: %v", err) 17 | } 18 | 19 | listenCtx := context.Background() 20 | 21 | onion, err := torInstance.Listen(listenCtx, &tor.ListenConf{LocalPort: 8868, RemotePorts: []int{80}}) 22 | if err != nil { 23 | log.Panicf("Unable to start onion service: %v", err) 24 | } 25 | 26 | t.onion = onion 27 | t.instance = torInstance 28 | } 29 | 30 | // Stop stops the tor instance, context listener and the onion service 31 | func (t *Tor) Stop() error { 32 | if err := t.instance.Close(); err != nil { 33 | return fmt.Errorf("[torproxy]: Couldn't close the tor instance. %s", err.Error()) 34 | } 35 | t.onion.Close() 36 | return nil 37 | } 38 | 39 | func (t *Tor) starterConfig(debugger io.Writer) *tor.StartConf { 40 | config := &tor.StartConf{ 41 | NoAutoSocksPort: true, 42 | ExtraArgs: []string{"--SocksPort", strconv.Itoa(t.Port)}, 43 | TempDataDirBase: t.DataDir, 44 | TorrcFile: t.Torrc, 45 | } 46 | 47 | if debugger != nil { 48 | config.DebugWriter = debugger 49 | } 50 | 51 | return config 52 | } 53 | -------------------------------------------------------------------------------- /cmd/torproxy/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | caddycmd "github.com/caddyserver/caddy/v2/cmd" 5 | _ "go.okkur.org/torproxy" 6 | ) 7 | 8 | func main() { 9 | caddycmd.Main() 10 | } 11 | -------------------------------------------------------------------------------- /config.go: -------------------------------------------------------------------------------- 1 | package torproxy 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "fmt" 7 | "io" 8 | "os" 9 | "os/exec" 10 | "strconv" 11 | "time" 12 | 13 | "github.com/caddyserver/caddy/v2" 14 | "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 15 | "github.com/cretz/bine/tor" 16 | "gopkg.in/natefinch/lumberjack.v2" 17 | ) 18 | 19 | // TorProxy config 20 | type Config struct { 21 | To map[string]string 22 | Client *Tor 23 | } 24 | 25 | // Tor instance config struct 26 | type Tor struct { 27 | // Socks5 proxy port 28 | Host string 29 | Port int 30 | DataDir string 31 | Torrc string 32 | DebugMode bool 33 | LogFile string 34 | 35 | debugger io.Writer 36 | instance *tor.Tor 37 | contextCanceler context.CancelFunc 38 | onion *tor.OnionService 39 | } 40 | 41 | // DefaultOnionServicePort is the port used to serve the onion service on 42 | const DefaultOnionServicePort = 4242 43 | 44 | // TODO: Discuss these values 45 | const ( 46 | torProxyKeepalive = 30000000 47 | torFallbackDelay = 30000000 * time.Millisecond 48 | torProxyTimeout = 30000000 * time.Second 49 | ) 50 | 51 | // ParseTor parses advanced config for Tor client 52 | func (t *Tor) ParseTor(d *caddyfile.Dispenser) error { 53 | switch d.Val() { 54 | case "host": 55 | t.Host = d.RemainingArgs()[0] 56 | 57 | case "port": 58 | value, err := strconv.Atoi(d.RemainingArgs()[0]) 59 | if err != nil { 60 | return fmt.Errorf("The given value for port field is not standard. It should be an integer") 61 | } 62 | t.Port = value 63 | 64 | case "datadir": 65 | t.DataDir = d.RemainingArgs()[0] 66 | 67 | case "torrc": 68 | t.Torrc = d.RemainingArgs()[0] 69 | 70 | case "debug_mode": 71 | value, err := strconv.ParseBool(d.RemainingArgs()[0]) 72 | if err != nil { 73 | return fmt.Errorf("The given value for debug_mode field is not standard. It should be a boolean") 74 | } 75 | t.DebugMode = value 76 | 77 | case "logfile": 78 | t.LogFile = d.RemainingArgs()[0] 79 | 80 | default: 81 | return d.ArgErr() // unhandled option for tor 82 | } 83 | 84 | return nil 85 | } 86 | 87 | // SetDefaults sets the default values for prometheus config 88 | // if the fields are empty 89 | func (t *Tor) SetDefaults() { 90 | if t.DebugMode { 91 | if t.LogFile != "" { 92 | t.debugger = &lumberjack.Logger{ 93 | Filename: t.LogFile, 94 | MaxSize: 100, 95 | MaxAge: 14, 96 | MaxBackups: 10, 97 | } 98 | } 99 | t.debugger = os.Stdout 100 | } 101 | 102 | if t.Host == "" { 103 | t.Host = "127.0.0.1" 104 | } 105 | 106 | if t.Port == 0 { 107 | t.Port = DefaultOnionServicePort 108 | } 109 | } 110 | 111 | // TorConstructor return a new instance of Tor client struct. 112 | // Used to manage the Tor client's life cycle 113 | func TorConstructor() (caddy.Destructor, error) { 114 | return &Tor{}, nil 115 | } 116 | 117 | // Destruct stops the Tor client 118 | func (t *Tor) Destruct() error { 119 | return t.Stop() 120 | } 121 | 122 | // IsInstalled checks the Tor client using the `tor --version` command 123 | func (t *Tor) IsInstalled() error { 124 | // Setup and run the "tor --version" command 125 | cmd := exec.Command("tor", "--version") 126 | stdout, err := cmd.StdoutPipe() 127 | if err != nil { 128 | return err 129 | } 130 | if err := cmd.Start(); err != nil { 131 | return err 132 | } 133 | 134 | // Read the output into buffer 135 | buf := new(bytes.Buffer) 136 | buf.ReadFrom(stdout) 137 | 138 | // Check if the output contains Tor's version 139 | if buf.String()[0:3] != "Tor" { 140 | return fmt.Errorf("Tor is not installed on you machine.Please follow these instructions to install Tor: https://www.torproject.org/download/") 141 | } 142 | 143 | return nil 144 | } 145 | -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | Attribution-ShareAlike 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More_considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution-ShareAlike 4.0 International Public 58 | License 59 | 60 | By exercising the Licensed Rights (defined below), You accept and agree 61 | to be bound by the terms and conditions of this Creative Commons 62 | Attribution-ShareAlike 4.0 International Public License ("Public 63 | License"). To the extent this Public License may be interpreted as a 64 | contract, You are granted the Licensed Rights in consideration of Your 65 | acceptance of these terms and conditions, and the Licensor grants You 66 | such rights in consideration of benefits the Licensor receives from 67 | making the Licensed Material available under these terms and 68 | conditions. 69 | 70 | 71 | Section 1 -- Definitions. 72 | 73 | a. Adapted Material means material subject to Copyright and Similar 74 | Rights that is derived from or based upon the Licensed Material 75 | and in which the Licensed Material is translated, altered, 76 | arranged, transformed, or otherwise modified in a manner requiring 77 | permission under the Copyright and Similar Rights held by the 78 | Licensor. For purposes of this Public License, where the Licensed 79 | Material is a musical work, performance, or sound recording, 80 | Adapted Material is always produced where the Licensed Material is 81 | synched in timed relation with a moving image. 82 | 83 | b. Adapter's License means the license You apply to Your Copyright 84 | and Similar Rights in Your contributions to Adapted Material in 85 | accordance with the terms and conditions of this Public License. 86 | 87 | c. BY-SA Compatible License means a license listed at 88 | creativecommons.org/compatiblelicenses, approved by Creative 89 | Commons as essentially the equivalent of this Public License. 90 | 91 | d. Copyright and Similar Rights means copyright and/or similar rights 92 | closely related to copyright including, without limitation, 93 | performance, broadcast, sound recording, and Sui Generis Database 94 | Rights, without regard to how the rights are labeled or 95 | categorized. For purposes of this Public License, the rights 96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 97 | Rights. 98 | 99 | e. Effective Technological Measures means those measures that, in the 100 | absence of proper authority, may not be circumvented under laws 101 | fulfilling obligations under Article 11 of the WIPO Copyright 102 | Treaty adopted on December 20, 1996, and/or similar international 103 | agreements. 104 | 105 | f. Exceptions and Limitations means fair use, fair dealing, and/or 106 | any other exception or limitation to Copyright and Similar Rights 107 | that applies to Your use of the Licensed Material. 108 | 109 | g. License Elements means the license attributes listed in the name 110 | of a Creative Commons Public License. The License Elements of this 111 | Public License are Attribution and ShareAlike. 112 | 113 | h. Licensed Material means the artistic or literary work, database, 114 | or other material to which the Licensor applied this Public 115 | License. 116 | 117 | i. Licensed Rights means the rights granted to You subject to the 118 | terms and conditions of this Public License, which are limited to 119 | all Copyright and Similar Rights that apply to Your use of the 120 | Licensed Material and that the Licensor has authority to license. 121 | 122 | j. Licensor means the individual(s) or entity(ies) granting rights 123 | under this Public License. 124 | 125 | k. Share means to provide material to the public by any means or 126 | process that requires permission under the Licensed Rights, such 127 | as reproduction, public display, public performance, distribution, 128 | dissemination, communication, or importation, and to make material 129 | available to the public including in ways that members of the 130 | public may access the material from a place and at a time 131 | individually chosen by them. 132 | 133 | l. Sui Generis Database Rights means rights other than copyright 134 | resulting from Directive 96/9/EC of the European Parliament and of 135 | the Council of 11 March 1996 on the legal protection of databases, 136 | as amended and/or succeeded, as well as other essentially 137 | equivalent rights anywhere in the world. 138 | 139 | m. You means the individual or entity exercising the Licensed Rights 140 | under this Public License. Your has a corresponding meaning. 141 | 142 | 143 | Section 2 -- Scope. 144 | 145 | a. License grant. 146 | 147 | 1. Subject to the terms and conditions of this Public License, 148 | the Licensor hereby grants You a worldwide, royalty-free, 149 | non-sublicensable, non-exclusive, irrevocable license to 150 | exercise the Licensed Rights in the Licensed Material to: 151 | 152 | a. reproduce and Share the Licensed Material, in whole or 153 | in part; and 154 | 155 | b. produce, reproduce, and Share Adapted Material. 156 | 157 | 2. Exceptions and Limitations. For the avoidance of doubt, where 158 | Exceptions and Limitations apply to Your use, this Public 159 | License does not apply, and You do not need to comply with 160 | its terms and conditions. 161 | 162 | 3. Term. The term of this Public License is specified in Section 163 | 6(a). 164 | 165 | 4. Media and formats; technical modifications allowed. The 166 | Licensor authorizes You to exercise the Licensed Rights in 167 | all media and formats whether now known or hereafter created, 168 | and to make technical modifications necessary to do so. The 169 | Licensor waives and/or agrees not to assert any right or 170 | authority to forbid You from making technical modifications 171 | necessary to exercise the Licensed Rights, including 172 | technical modifications necessary to circumvent Effective 173 | Technological Measures. For purposes of this Public License, 174 | simply making modifications authorized by this Section 2(a) 175 | (4) never produces Adapted Material. 176 | 177 | 5. Downstream recipients. 178 | 179 | a. Offer from the Licensor -- Licensed Material. Every 180 | recipient of the Licensed Material automatically 181 | receives an offer from the Licensor to exercise the 182 | Licensed Rights under the terms and conditions of this 183 | Public License. 184 | 185 | b. Additional offer from the Licensor -- Adapted Material. 186 | Every recipient of Adapted Material from You 187 | automatically receives an offer from the Licensor to 188 | exercise the Licensed Rights in the Adapted Material 189 | under the conditions of the Adapter's License You apply. 190 | 191 | c. No downstream restrictions. You may not offer or impose 192 | any additional or different terms or conditions on, or 193 | apply any Effective Technological Measures to, the 194 | Licensed Material if doing so restricts exercise of the 195 | Licensed Rights by any recipient of the Licensed 196 | Material. 197 | 198 | 6. No endorsement. Nothing in this Public License constitutes or 199 | may be construed as permission to assert or imply that You 200 | are, or that Your use of the Licensed Material is, connected 201 | with, or sponsored, endorsed, or granted official status by, 202 | the Licensor or others designated to receive attribution as 203 | provided in Section 3(a)(1)(A)(i). 204 | 205 | b. Other rights. 206 | 207 | 1. Moral rights, such as the right of integrity, are not 208 | licensed under this Public License, nor are publicity, 209 | privacy, and/or other similar personality rights; however, to 210 | the extent possible, the Licensor waives and/or agrees not to 211 | assert any such rights held by the Licensor to the limited 212 | extent necessary to allow You to exercise the Licensed 213 | Rights, but not otherwise. 214 | 215 | 2. Patent and trademark rights are not licensed under this 216 | Public License. 217 | 218 | 3. To the extent possible, the Licensor waives any right to 219 | collect royalties from You for the exercise of the Licensed 220 | Rights, whether directly or through a collecting society 221 | under any voluntary or waivable statutory or compulsory 222 | licensing scheme. In all other cases the Licensor expressly 223 | reserves any right to collect such royalties. 224 | 225 | 226 | Section 3 -- License Conditions. 227 | 228 | Your exercise of the Licensed Rights is expressly made subject to the 229 | following conditions. 230 | 231 | a. Attribution. 232 | 233 | 1. If You Share the Licensed Material (including in modified 234 | form), You must: 235 | 236 | a. retain the following if it is supplied by the Licensor 237 | with the Licensed Material: 238 | 239 | i. identification of the creator(s) of the Licensed 240 | Material and any others designated to receive 241 | attribution, in any reasonable manner requested by 242 | the Licensor (including by pseudonym if 243 | designated); 244 | 245 | ii. a copyright notice; 246 | 247 | iii. a notice that refers to this Public License; 248 | 249 | iv. a notice that refers to the disclaimer of 250 | warranties; 251 | 252 | v. a URI or hyperlink to the Licensed Material to the 253 | extent reasonably practicable; 254 | 255 | b. indicate if You modified the Licensed Material and 256 | retain an indication of any previous modifications; and 257 | 258 | c. indicate the Licensed Material is licensed under this 259 | Public License, and include the text of, or the URI or 260 | hyperlink to, this Public License. 261 | 262 | 2. You may satisfy the conditions in Section 3(a)(1) in any 263 | reasonable manner based on the medium, means, and context in 264 | which You Share the Licensed Material. For example, it may be 265 | reasonable to satisfy the conditions by providing a URI or 266 | hyperlink to a resource that includes the required 267 | information. 268 | 269 | 3. If requested by the Licensor, You must remove any of the 270 | information required by Section 3(a)(1)(A) to the extent 271 | reasonably practicable. 272 | 273 | b. ShareAlike. 274 | 275 | In addition to the conditions in Section 3(a), if You Share 276 | Adapted Material You produce, the following conditions also apply. 277 | 278 | 1. The Adapter's License You apply must be a Creative Commons 279 | license with the same License Elements, this version or 280 | later, or a BY-SA Compatible License. 281 | 282 | 2. You must include the text of, or the URI or hyperlink to, the 283 | Adapter's License You apply. You may satisfy this condition 284 | in any reasonable manner based on the medium, means, and 285 | context in which You Share Adapted Material. 286 | 287 | 3. You may not offer or impose any additional or different terms 288 | or conditions on, or apply any Effective Technological 289 | Measures to, Adapted Material that restrict exercise of the 290 | rights granted under the Adapter's License You apply. 291 | 292 | 293 | Section 4 -- Sui Generis Database Rights. 294 | 295 | Where the Licensed Rights include Sui Generis Database Rights that 296 | apply to Your use of the Licensed Material: 297 | 298 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 299 | to extract, reuse, reproduce, and Share all or a substantial 300 | portion of the contents of the database; 301 | 302 | b. if You include all or a substantial portion of the database 303 | contents in a database in which You have Sui Generis Database 304 | Rights, then the database in which You have Sui Generis Database 305 | Rights (but not its individual contents) is Adapted Material, 306 | 307 | including for purposes of Section 3(b); and 308 | c. You must comply with the conditions in Section 3(a) if You Share 309 | all or a substantial portion of the contents of the database. 310 | 311 | For the avoidance of doubt, this Section 4 supplements and does not 312 | replace Your obligations under this Public License where the Licensed 313 | Rights include other Copyright and Similar Rights. 314 | 315 | 316 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 317 | 318 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 319 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 320 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 321 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 322 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 323 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 324 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 325 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 326 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 327 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 328 | 329 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 330 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 331 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 332 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 333 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 334 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 335 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 336 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 337 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 338 | 339 | c. The disclaimer of warranties and limitation of liability provided 340 | above shall be interpreted in a manner that, to the extent 341 | possible, most closely approximates an absolute disclaimer and 342 | waiver of all liability. 343 | 344 | 345 | Section 6 -- Term and Termination. 346 | 347 | a. This Public License applies for the term of the Copyright and 348 | Similar Rights licensed here. However, if You fail to comply with 349 | this Public License, then Your rights under this Public License 350 | terminate automatically. 351 | 352 | b. Where Your right to use the Licensed Material has terminated under 353 | Section 6(a), it reinstates: 354 | 355 | 1. automatically as of the date the violation is cured, provided 356 | it is cured within 30 days of Your discovery of the 357 | violation; or 358 | 359 | 2. upon express reinstatement by the Licensor. 360 | 361 | For the avoidance of doubt, this Section 6(b) does not affect any 362 | right the Licensor may have to seek remedies for Your violations 363 | of this Public License. 364 | 365 | c. For the avoidance of doubt, the Licensor may also offer the 366 | Licensed Material under separate terms or conditions or stop 367 | distributing the Licensed Material at any time; however, doing so 368 | will not terminate this Public License. 369 | 370 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 371 | License. 372 | 373 | 374 | Section 7 -- Other Terms and Conditions. 375 | 376 | a. The Licensor shall not be bound by any additional or different 377 | terms or conditions communicated by You unless expressly agreed. 378 | 379 | b. Any arrangements, understandings, or agreements regarding the 380 | Licensed Material not stated herein are separate from and 381 | independent of the terms and conditions of this Public License. 382 | 383 | 384 | Section 8 -- Interpretation. 385 | 386 | a. For the avoidance of doubt, this Public License does not, and 387 | shall not be interpreted to, reduce, limit, restrict, or impose 388 | conditions on any use of the Licensed Material that could lawfully 389 | be made without permission under this Public License. 390 | 391 | b. To the extent possible, if any provision of this Public License is 392 | deemed unenforceable, it shall be automatically reformed to the 393 | minimum extent necessary to make it enforceable. If the provision 394 | cannot be reformed, it shall be severed from this Public License 395 | without affecting the enforceability of the remaining terms and 396 | conditions. 397 | 398 | c. No term or condition of this Public License will be waived and no 399 | failure to comply consented to unless expressly agreed to by the 400 | Licensor. 401 | 402 | d. Nothing in this Public License constitutes or may be interpreted 403 | as a limitation upon, or waiver of, any privileges and immunities 404 | that apply to the Licensor or You, including from the legal 405 | processes of any jurisdiction or authority. 406 | 407 | 408 | ======================================================================= 409 | 410 | Creative Commons is not a party to its public 411 | licenses. Notwithstanding, Creative Commons may elect to apply one of 412 | its public licenses to material it publishes and in those instances 413 | will be considered the “Licensor.” The text of the Creative Commons 414 | public licenses is dedicated to the public domain under the CC0 Public 415 | Domain Dedication. Except for the limited purpose of indicating that 416 | material is shared under a Creative Commons public license or as 417 | otherwise permitted by the Creative Commons policies published at 418 | creativecommons.org/policies, Creative Commons does not authorize the 419 | use of the trademark "Creative Commons" or any other trademark or logo 420 | of Creative Commons without its prior written consent including, 421 | without limitation, in connection with any unauthorized modifications 422 | to any of its public licenses or any other arrangements, 423 | understandings, or agreements concerning use of licensed material. For 424 | the avoidance of doubt, this paragraph does not form part of the 425 | public licenses. 426 | 427 | Creative Commons may be contacted at creativecommons.org. 428 | 429 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | ## Development 16 | Run the following command to get torproxy's source code and switch your working directory to the torproxy repository 17 | ``` 18 | git clone github.com/okkur/torproxy && cd torproxy 19 | ``` 20 | 21 | Then run the following command to build torproxy 22 | ``` 23 | make build 24 | ``` 25 | 26 | Do not forget to install Tor itself on your machine since torproxy needs that to operate correctly. 27 | 28 | # Documentation 29 | 30 | No documentation available yet. Start your first contribution with some documentation. 31 | 32 | See how you can contribute with our [contribution guide](/CONTRIBUTING.md). 33 | -------------------------------------------------------------------------------- /docs/configuration.md: -------------------------------------------------------------------------------- 1 | ## Configuration 2 | 3 | Torproxy provides two methods for configuration, one way to configure Torproxy is 4 | to only provide the source and target URIs like this example: 5 | 6 | ``` 7 | example.test { 8 | torproxy example.test somewhereonthe.onion 9 | } 10 | ``` 11 | 12 | In this case, Torproxy will use the default values to start a Tor instance on port 4242. 13 | Also note that you can specify more than one URI to proxy, like this example: 14 | 15 | ``` 16 | first.test, second.test, third.test { 17 | torproxy first.test somewhereonthe.onion 18 | torproxy second.test somewhereonthe.onion 19 | torproxy third.test somewhereonthe.onion 20 | } 21 | ``` 22 | 23 | If you want to use a custom Tor instance or customize the Tor instance that Torproxy starts, 24 | use the following options in the config: 25 | 26 | - `host`: Tor daemon's host (Default: `127.0.0.1`) 27 | - `port`: Tor daemon's port (Default: `4242`) 28 | - `datadir`: DataDir is the parent directory that a temporary data directory will be created under for use by Tor. 29 | - `torrc`: Tor's configuration file. If empty, a blank torrc is created in the data directory and is used instead. 30 | - `debug_mode`: If enabled, debug logs would be written to `stdout`. 31 | - `logfile`: Path to a file for storing logs. `debug_mode` should be enabled for this option. 32 | 33 | **Note: If `host` field isn't provided, Torproxy will start a fresh Tor instance itself.** 34 | 35 | Caddyfile Example: 36 | 37 | ``` 38 | from.com { 39 | torproxy from.com to.onion { 40 | host 172.168.1.1 41 | port 4200 42 | datadir /data/dir 43 | torrc /etc/tor/torrc 44 | debug_mode true 45 | logfile /var/logs/stdout 46 | } 47 | } 48 | ``` 49 | 50 | JSON Example: 51 | 52 | ```json 53 | { 54 | "apps": { 55 | "http": { 56 | "servers": { 57 | "srv0": { 58 | "listen": [":443"], 59 | "routes": [ 60 | { 61 | "match": [ 62 | { 63 | "host": ["from.com"] 64 | } 65 | ], 66 | "handle": [ 67 | { 68 | "handler": "subroute", 69 | "routes": [ 70 | { 71 | "handle": [ 72 | { 73 | "Config": { 74 | "Client": { 75 | "DataDir": "/data/dir", 76 | "DebugMode": true, 77 | "Host": "172.168.1.1", 78 | "LogFile": "/var/logs/stdout", 79 | "Port": 4200, 80 | "Torrc": "/etc/tor/torrc" 81 | }, 82 | "To": { 83 | "from.com": "http://to.onion" 84 | } 85 | }, 86 | "handler": "torproxy" 87 | } 88 | ] 89 | } 90 | ] 91 | } 92 | ] 93 | } 94 | ] 95 | } 96 | } 97 | } 98 | } 99 | } 100 | ``` 101 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module go.okkur.org/torproxy 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/caddyserver/caddy/v2 v2.0.0-beta9 7 | github.com/cretz/bine v0.1.0 8 | github.com/miekg/dns v1.1.16 // indirect 9 | golang.org/x/net v0.0.0-20191009170851-d66e71096ffb 10 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd // indirect 11 | gopkg.in/natefinch/lumberjack.v2 v2.0.0 12 | ) 13 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= 5 | github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 6 | github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= 7 | github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw= 8 | github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= 9 | github.com/Azure/go-autorest/autorest/adal v0.2.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= 10 | github.com/Azure/go-autorest/autorest/azure/auth v0.1.0/go.mod h1:Gf7/i2FUpyb/sGBLIFxTBzrNzBo7aPXXE3ZVeDRwdpM= 11 | github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U= 12 | github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= 13 | github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 14 | github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= 15 | github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= 16 | github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= 17 | github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= 18 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 19 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 20 | github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= 21 | github.com/Masterminds/semver/v3 v3.0.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= 22 | github.com/Masterminds/sprig/v3 v3.0.0/go.mod h1:NEUY/Qq8Gdm2xgYA+NwJM6wmfdRV9xkh8h/Rld20R0U= 23 | github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= 24 | github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= 25 | github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= 26 | github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k= 27 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 28 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 29 | github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= 30 | github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= 31 | github.com/andybalholm/brotli v0.0.0-20190821151343-b60f0d972eeb/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 32 | github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= 33 | github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 34 | github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= 35 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 36 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 37 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 38 | github.com/caddyserver/caddy/v2 v2.0.0-beta9 h1:oILdAOfunJ4ijBN9kOWjFIeH8EufBX/N1pC9HbnwjzU= 39 | github.com/caddyserver/caddy/v2 v2.0.0-beta9/go.mod h1:9clsTzx/LZmjGb10CnrYFVCwA53StOjLdhvR/3AGG9k= 40 | github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= 41 | github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= 42 | github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 43 | github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= 44 | github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= 45 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 46 | github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY= 47 | github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= 48 | github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= 49 | github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok= 50 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 51 | github.com/cretz/bine v0.1.0 h1:1/fvhLE+fk0bPzjdO5Ci+0ComYxEMuB1JhM4X5skT3g= 52 | github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw= 53 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 54 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 55 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 56 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 57 | github.com/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= 58 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 59 | github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= 60 | github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= 61 | github.com/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= 62 | github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= 63 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 64 | github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= 65 | github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= 66 | github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 67 | github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= 68 | github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= 69 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 70 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 71 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 72 | github.com/go-acme/lego/v3 v3.1.0 h1:yanYFoYW8azFkCvJfIk7edWWfjkYkhDxe45ZsxoW4Xk= 73 | github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= 74 | github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= 75 | github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 76 | github.com/go-ini/ini v1.44.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 77 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 78 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 79 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 80 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 81 | github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 82 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 83 | github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 84 | github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= 85 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 86 | github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 87 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 88 | github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= 89 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 90 | github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= 91 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 92 | github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= 93 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 94 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 95 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 96 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 97 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 98 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 99 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 100 | github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 101 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 102 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 103 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 104 | github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= 105 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 106 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 107 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 108 | github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= 109 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 110 | github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= 111 | github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 112 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 113 | github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= 114 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 115 | github.com/gravitational/trace v0.0.0-20190726142706-a535a178675f/go.mod h1:RvdOUHE4SHqR3oXlFFKnGzms8a5dugHygGw1bqDstYI= 116 | github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 117 | github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= 118 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 119 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 120 | github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 121 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 122 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 123 | github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= 124 | github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= 125 | github.com/ilibs/json5 v1.0.1/go.mod h1:kXsGuzHMPuZZTN15l0IQzy5PR8DrDhPB24tFgwpdKME= 126 | github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 127 | github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 128 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 129 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 130 | github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 131 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 132 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 133 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 134 | github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0= 135 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 136 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 137 | github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 h1:WjT3fLi9n8YWh/Ih8Q1LHAPsTqGddPcHqscN+PJ3i68= 138 | github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19/go.mod h1:hY+WOq6m2FpbvyrI93sMaypsttvaIL5nhVR92dTMUcQ= 139 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 140 | github.com/klauspost/compress v1.8.6/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= 141 | github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= 142 | github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= 143 | github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= 144 | github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= 145 | github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= 146 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 147 | github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= 148 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 149 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 150 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 151 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 152 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 153 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 154 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 155 | github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= 156 | github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= 157 | github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= 158 | github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= 159 | github.com/lucas-clemente/quic-go v0.12.1 h1:BPITli+6KnKogtTxBk2aS4okr5dUHz2LtIDAP1b8UL4= 160 | github.com/lucas-clemente/quic-go v0.12.1/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s= 161 | github.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f/go.mod h1:V3EvCedtJTvUYzJF2GZMRB0JMlai+6cBu3VCTQz33GQ= 162 | github.com/mailgun/multibuf v0.0.0-20150714184110-565402cd71fb/go.mod h1:E0vRBBIQUHcRtmL/oR6w/jehh4FJqJFxe86gBnw9gXc= 163 | github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 h1:Kg/NPZLLC3aAFr1YToMs98dbCdhootQ1hZIvZU28hAQ= 164 | github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51/go.mod h1:RYmqHbhWwIz3z9eVmQ2rx82rulEMG0t+Q1bzfc9DYN4= 165 | github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f/go.mod h1:8heskWJ5c0v5J9WH89ADhyal1DOZcayll8fSbhB+/9A= 166 | github.com/marten-seemann/qpack v0.1.0 h1:/0M7lkda/6mus9B8u34Asqm8ZhHAAt9Ho0vniNuVSVg= 167 | github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= 168 | github.com/marten-seemann/qtls v0.3.2 h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9sYamI= 169 | github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= 170 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 171 | github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 172 | github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 173 | github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= 174 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 175 | github.com/mholt/certmagic v0.8.3 h1:JOUiX9IAZbbgyjNP2GY6v/6lorH+9GkZsc7ktMpGCSo= 176 | github.com/mholt/certmagic v0.8.3/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= 177 | github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 178 | github.com/miekg/dns v1.1.16 h1:iMEQ/IVHxPTtx2Q07JP/k4CKRvSjiAZjZ0hnhgYEDmE= 179 | github.com/miekg/dns v1.1.16/go.mod h1:YNV562EiewvSmpCB6/W4c6yqjK7Z+M/aIS1JHsIVeg8= 180 | github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= 181 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 182 | github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= 183 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 184 | github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 185 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 186 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 187 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 188 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 189 | github.com/muhammadmuzzammil1998/jsonc v0.0.0-20190906142622-1265e9b150c6/go.mod h1:saF2fIVw4banK0H4+/EuqfFLpRnoy5S+ECwTOCcRcSU= 190 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 191 | github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= 192 | github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= 193 | github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw= 194 | github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ= 195 | github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= 196 | github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 197 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 198 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 199 | github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= 200 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 201 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 202 | github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= 203 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 204 | github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= 205 | github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= 206 | github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= 207 | github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= 208 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 209 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 210 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 211 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 212 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 213 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 214 | github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= 215 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 216 | github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= 217 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 218 | github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 219 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 220 | github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 221 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 222 | github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= 223 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 224 | github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 225 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 226 | github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= 227 | github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= 228 | github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= 229 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 230 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 231 | github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ= 232 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 233 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 234 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 235 | github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= 236 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 237 | github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= 238 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 239 | github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 240 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 241 | github.com/starlight-go/starlight v0.0.0-20181207205707-b06f321544f3 h1:/fBh1Ot84ILt/ociFHO98wJ9LxIMA3UG8B0unUJPFpY= 242 | github.com/starlight-go/starlight v0.0.0-20181207205707-b06f321544f3/go.mod h1:pxOc2ZuBV+CNlQgzq/HJ9Z9G/eoEMHFeuGohOvva4Co= 243 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 244 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 245 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 246 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 247 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 248 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 249 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 250 | github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= 251 | github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= 252 | github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= 253 | github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 254 | github.com/vulcand/oxy v1.0.0 h1:7vL5/pjDFzHGbtBEhmlHITUi6KLH4xXTDF33/wrdRKw= 255 | github.com/vulcand/oxy v1.0.0/go.mod h1:6EXgOAl6CRa46/2ZGcDJKf3ywJUp5WtT7vSlGSkvecI= 256 | github.com/vulcand/predicate v1.1.0/go.mod h1:mlccC5IRBoc2cIFmCB8ZM62I3VDb6p2GXESMHa3CnZg= 257 | github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA= 258 | github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= 259 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= 260 | github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= 261 | go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 262 | go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 263 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 264 | go.starlark.net v0.0.0-20190919145610-979af19b165c h1:WR7X1xgXJlXhQBdorVc9Db3RhwG+J/kp6bLuMyJjfVw= 265 | go.starlark.net v0.0.0-20190919145610-979af19b165c/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg= 266 | go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= 267 | go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 268 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 269 | go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4= 270 | go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 271 | go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= 272 | go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 273 | go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= 274 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 275 | golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 276 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 277 | golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 278 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 279 | golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 280 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= 281 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 282 | golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= 283 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 284 | golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 285 | golang.org/x/crypto v0.0.0-20191010185427-af544f31c8ac h1:/b4NMZurYfBIQyRMqaPGMDeUrSW6gU7/7Hv6owY1Vjk= 286 | golang.org/x/crypto v0.0.0-20191010185427-af544f31c8ac/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 287 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 288 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 289 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 290 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 291 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 292 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 293 | golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 294 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 295 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 296 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 297 | golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 298 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 299 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 300 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 301 | golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 302 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 303 | golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 304 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 305 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 306 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 307 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 308 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 309 | golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 310 | golang.org/x/net v0.0.0-20191009170851-d66e71096ffb h1:TR699M2v0qoKTOHxeLgp6zPqaQNs74f01a/ob9W0qko= 311 | golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 312 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 313 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 314 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 315 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 316 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 317 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= 318 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 319 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 320 | golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= 321 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 322 | golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 323 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 324 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 325 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 326 | golang.org/x/sys v0.0.0-20180928133829-e4b3c5e90611/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 327 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 328 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 329 | golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 330 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 331 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 332 | golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e h1:ZytStCyV048ZqDsWHiYDdoI2Vd4msMcrDECFxS+tL9c= 333 | golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 334 | golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 335 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 336 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 337 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 338 | golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 339 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0= 340 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 341 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 342 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 343 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 344 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 345 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 346 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 347 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 348 | golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 349 | golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 350 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 351 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 352 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 353 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 354 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 355 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 356 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 357 | google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= 358 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 359 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 360 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 361 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 362 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 363 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 364 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 365 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 366 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 367 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 368 | google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= 369 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 370 | google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 371 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 372 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 373 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 374 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 375 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 376 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 377 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 378 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 379 | gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= 380 | gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 381 | gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 382 | gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= 383 | gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= 384 | gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw= 385 | gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= 386 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 387 | gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= 388 | gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 389 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 390 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 391 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 392 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 393 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 394 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 395 | honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 396 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 397 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 398 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 399 | -------------------------------------------------------------------------------- /response.go: -------------------------------------------------------------------------------- 1 | package torproxy 2 | 3 | import ( 4 | "bytes" 5 | "compress/gzip" 6 | "io" 7 | "net/http" 8 | "sync" 9 | 10 | "golang.org/x/net/proxy" 11 | ) 12 | 13 | type TorResponse struct { 14 | headers http.Header 15 | body []byte 16 | bodyReader bytes.Buffer 17 | bodyWriter bytes.Buffer 18 | status int 19 | 20 | request *http.Request 21 | dialer proxy.Dialer 22 | } 23 | 24 | var bufferPool = sync.Pool{New: createBuffer} 25 | 26 | func createBuffer() interface{} { 27 | return make([]byte, 0, 32*1024) 28 | } 29 | 30 | // Header returns response headers 31 | func (t *TorResponse) Header() http.Header { 32 | return t.headers 33 | } 34 | 35 | func (t *TorResponse) Write(body []byte) (int, error) { 36 | reader := bytes.NewReader(body) 37 | pooledIoCopy(&t.bodyReader, reader) 38 | t.body = body 39 | return len(body), nil 40 | } 41 | 42 | // Body returns response's body. This method should only get called after WriteBody() 43 | func (t *TorResponse) Body() []byte { 44 | return t.bodyWriter.Bytes() 45 | } 46 | 47 | // WriteHeader Writes the given status code to response 48 | func (t *TorResponse) WriteHeader(status int) { 49 | t.status = status 50 | } 51 | 52 | func (t *TorResponse) ReplaceBody(scheme, to, host string) error { 53 | replacedBody := bytes.Replace(t.bodyWriter.Bytes(), []byte(scheme+"://"+to), []byte(scheme+"://"+host), -1) 54 | t.bodyWriter.Reset() 55 | if _, err := t.bodyWriter.Write(replacedBody); err != nil { 56 | return err 57 | } 58 | return nil 59 | } 60 | 61 | func (t *TorResponse) WriteBody() error { 62 | switch t.Header().Get("Content-Encoding") { 63 | case "gzip": 64 | reader, err := gzip.NewReader(&t.bodyReader) 65 | if err != nil { 66 | return err 67 | } 68 | defer reader.Close() 69 | _, err = io.Copy(&t.bodyWriter, reader) 70 | if err != nil { 71 | return err 72 | } 73 | t.Header().Del("Content-Encoding") 74 | default: 75 | _, err := io.Copy(&t.bodyWriter, &t.bodyReader) 76 | if err != nil { 77 | return err 78 | } 79 | } 80 | return nil 81 | } 82 | 83 | var skipHeaders = map[string]struct{}{ 84 | "Content-Type": {}, 85 | "Content-Disposition": {}, 86 | "Accept-Ranges": {}, 87 | "Set-Cookie": {}, 88 | "Cache-Control": {}, 89 | "Expires": {}, 90 | } 91 | 92 | func copyHeader(dst, src http.Header) { 93 | for k, vv := range src { 94 | if _, ok := dst[k]; ok { 95 | if _, shouldSkip := skipHeaders[k]; shouldSkip { 96 | continue 97 | } 98 | if k != "Server" { 99 | dst.Del(k) 100 | } 101 | } 102 | for _, v := range vv { 103 | dst.Add(k, v) 104 | } 105 | } 106 | } 107 | 108 | func pooledIoCopy(dst io.Writer, src io.Reader) { 109 | buf := bufferPool.Get().([]byte) 110 | defer bufferPool.Put(buf) 111 | 112 | bufCap := cap(buf) 113 | io.CopyBuffer(dst, src, buf[0:bufCap:bufCap]) 114 | } 115 | -------------------------------------------------------------------------------- /setup.go: -------------------------------------------------------------------------------- 1 | package torproxy 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "net/url" 8 | 9 | "github.com/caddyserver/caddy/v2" 10 | "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 11 | "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile" 12 | "github.com/caddyserver/caddy/v2/modules/caddyhttp" 13 | ) 14 | 15 | func init() { 16 | caddy.RegisterModule(TorProxy{}) 17 | httpcaddyfile.RegisterHandlerDirective("torproxy", parse) 18 | } 19 | 20 | func parse(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) { 21 | var t TorProxy 22 | err := t.UnmarshalCaddyfile(h.Dispenser) 23 | return t, err 24 | } 25 | 26 | // UnmarshalCaddyfile implements caddyfile.Unmarshaler. 27 | func (t *TorProxy) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { 28 | var config Config 29 | var client Tor 30 | to := make(map[string]string) 31 | 32 | config_handler: 33 | for d.Next() { 34 | if d.Val() == "torproxy" { 35 | d.Next() // skip directive name 36 | } 37 | 38 | // Parse the Tor client's config 39 | if d.Val() == "{" { 40 | for d.Next() { 41 | if d.Val() == "}" { 42 | continue config_handler 43 | } 44 | if err := client.ParseTor(d); err != nil { 45 | return fmt.Errorf("Couldn't parse the Tor client config: %s", err.Error()) 46 | } 47 | } 48 | } 49 | 50 | // Parse the Config.From and Config.To URIs 51 | fromURI, err := url.Parse(d.Val()) 52 | if err != nil { 53 | return fmt.Errorf("Couldn't parse the `from` URI %s", err.Error()) 54 | } 55 | toURI, err := url.Parse(d.RemainingArgs()[0]) 56 | if err != nil { 57 | return fmt.Errorf("Couldn't parse the `from` URI: %s", err.Error()) 58 | } 59 | 60 | if toURI.Scheme == "" { 61 | toURI.Scheme = "http" 62 | } 63 | 64 | // Fill the config instance 65 | to[fromURI.String()] = toURI.String() 66 | } 67 | 68 | config.To = to 69 | config.Client = &client 70 | config.Client.SetDefaults() 71 | t.Config = config 72 | 73 | if t.Config.Client.Host == "" && !t.testing { 74 | t.Config.Client.Start() 75 | } 76 | 77 | return nil 78 | } 79 | 80 | // CaddyModule returns the Caddy module information. 81 | func (TorProxy) CaddyModule() caddy.ModuleInfo { 82 | t := &TorProxy{Config: Config{Client: &Tor{}}} 83 | pool := caddy.NewUsagePool() 84 | pool.LoadOrNew("torclient", TorConstructor) 85 | 86 | if t.Config.Client.Host == "" && !t.testing { 87 | if err := t.Config.Client.IsInstalled(); err != nil { 88 | log.Fatalf(err.Error()) 89 | } 90 | } 91 | 92 | return caddy.ModuleInfo{ 93 | Name: "http.handlers.torproxy", 94 | New: func() caddy.Module { 95 | return t 96 | }, 97 | } 98 | } 99 | 100 | type TorProxy struct { 101 | Config Config 102 | // Set "testing" to true in tests to skip Tor client's auto start 103 | testing bool 104 | } 105 | 106 | func (t TorProxy) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { 107 | return t.Config.Proxy(w, r) 108 | } 109 | -------------------------------------------------------------------------------- /setup_test.go: -------------------------------------------------------------------------------- 1 | package torproxy 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" 8 | ) 9 | 10 | func Test_parse(t *testing.T) { 11 | tests := []struct { 12 | configFile string 13 | config Config 14 | }{ 15 | { 16 | ` 17 | torproxy from.com to.onion 18 | `, 19 | Config{ 20 | To: map[string]string{"from.com": "http://to.onion"}, 21 | }, 22 | }, 23 | { 24 | ` 25 | torproxy from.com to.onion 26 | torproxy from2.com to2.onion 27 | `, 28 | Config{ 29 | To: map[string]string{"from.com": "http://to.onion", "from2.com": "http://to2.onion"}, 30 | }, 31 | }, 32 | { 33 | ` 34 | torproxy from.com to.onion 35 | torproxy from2.com to2.onion { 36 | port 4200 37 | } 38 | `, 39 | Config{ 40 | To: map[string]string{"from.com": "http://to.onion", "from2.com": "http://to2.onion"}, 41 | Client: &Tor{ 42 | Host: "127.0.0.1", 43 | Port: 4200, 44 | }, 45 | }, 46 | }, 47 | { 48 | ` 49 | torproxy from.com to.onion 50 | torproxy from2.com to2.onion { 51 | host 172.168.1.1 52 | port 4200 53 | datadir /data/dir 54 | torrc /etc/tor/torrc 55 | debug_mode true 56 | logfile /var/logs/stdout 57 | } 58 | `, 59 | Config{ 60 | To: map[string]string{"from.com": "http://to.onion", "from2.com": "http://to2.onion"}, 61 | Client: &Tor{ 62 | Host: "172.168.1.1", 63 | Port: 4200, 64 | DataDir: "/data/dir", 65 | Torrc: "/etc/tor/torrc", 66 | DebugMode: true, 67 | LogFile: "/var/logs/stdout", 68 | }, 69 | }, 70 | }, 71 | } 72 | for i, test := range tests { 73 | buf := bytes.NewBuffer([]byte(test.configFile)) 74 | block, err := caddyfile.Parse("Caddyfile", buf) 75 | if err != nil { 76 | t.Errorf("Couldn't read the config: %s", err.Error()) 77 | } 78 | 79 | // Extract the config tokens from the server blocks 80 | var tokens []caddyfile.Token 81 | for _, segment := range block[0].Segments { 82 | for _, token := range segment { 83 | tokens = append(tokens, token) 84 | } 85 | } 86 | 87 | d := caddyfile.NewDispenser(tokens) 88 | g := &TorProxy{Config: Config{Client: &Tor{}}, testing: true} 89 | 90 | if err := g.UnmarshalCaddyfile(d); err != nil { 91 | t.Errorf("Couldn't parse the config: %s", err.Error()) 92 | } 93 | 94 | for from, to := range g.Config.To { 95 | if test.config.To[from] != to { 96 | t.Errorf("Expected %+v, Got %+v", test.config.To, g.Config.To) 97 | } 98 | } 99 | 100 | if test.config.Client != nil { 101 | if g.Config.Client.Host != test.config.Client.Host { 102 | t.Errorf("[%d]: Expected %s, but got %s", i, test.config.Client.Host, g.Config.Client.Host) 103 | } 104 | if g.Config.Client.Port != test.config.Client.Port { 105 | t.Errorf("[%d]: Expected %d, but got %d", i, test.config.Client.Port, g.Config.Client.Port) 106 | } 107 | if g.Config.Client.DataDir != test.config.Client.DataDir { 108 | t.Errorf("[%d]: Expected %s, but got %s", i, test.config.Client.DataDir, g.Config.Client.DataDir) 109 | } 110 | if g.Config.Client.Torrc != test.config.Client.Torrc { 111 | t.Errorf("[%d]: Expected %s, but got %s", i, test.config.Client.Torrc, g.Config.Client.Torrc) 112 | } 113 | if g.Config.Client.DebugMode != test.config.Client.DebugMode { 114 | t.Errorf("[%d]: Expected %t, but got %t", i, test.config.Client.DebugMode, g.Config.Client.DebugMode) 115 | } 116 | if g.Config.Client.LogFile != test.config.Client.LogFile { 117 | t.Errorf("[%d]: Expected %s, but got %s", i, test.config.Client.LogFile, g.Config.Client.LogFile) 118 | } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /torproxy.go: -------------------------------------------------------------------------------- 1 | package torproxy 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "net/http" 7 | "net/http/httputil" 8 | "net/url" 9 | 10 | "golang.org/x/net/proxy" 11 | ) 12 | 13 | // Proxy redirects the request to the local onion service and the actual proxying 14 | // happens inside onion service's http handler 15 | func (c Config) Proxy(w http.ResponseWriter, r *http.Request) error { 16 | u, err := url.Parse(c.To[r.Host]) 17 | if err != nil { 18 | return err 19 | } 20 | 21 | if u.Port() == "" { 22 | toPort := "80" 23 | if u.Scheme == "https" { 24 | toPort = "443" 25 | } 26 | u.Host = net.JoinHostPort(u.Host, toPort) 27 | } 28 | 29 | // Use proxied Host 30 | r.Host = u.Host 31 | 32 | // Create a socks5 dialer 33 | dialer, err := proxy.SOCKS5("tcp", fmt.Sprintf("%s:%d", c.Client.Host, c.Client.Port), nil, proxy.Direct) 34 | if err != nil { 35 | return fmt.Errorf("Couldn't connect to socks proxy: %s", err.Error()) 36 | } 37 | 38 | proxy := httputil.NewSingleHostReverseProxy(u) 39 | proxy.Transport = &http.Transport{ 40 | Dial: dialer.Dial, 41 | } 42 | 43 | // Create a temporary response writer to save response's body and headers 44 | tmpResponse := TorResponse{ 45 | headers: make(http.Header), 46 | dialer: dialer, 47 | request: r, 48 | } 49 | 50 | // Proxy the request and write the response to the temporary response writer 51 | proxy.ServeHTTP(&tmpResponse, r) 52 | 53 | // If the received response is a redirect, proxy the request to the response's Location header 54 | // Do this until the final response isn't a redirect response 55 | for { 56 | if tmpResponse.status == http.StatusFound || tmpResponse.status == http.StatusMovedPermanently { 57 | if err = tmpResponse.Redirect(); err != nil { 58 | return fmt.Errorf("[torproxy]: Couldn't redirect the request to the response's \"Location\" header: %s", err) 59 | } 60 | continue 61 | } 62 | break 63 | } 64 | 65 | // Decompress the body based on "Content-Encoding" header and write to a writer buffer 66 | if err := tmpResponse.WriteBody(); err != nil { 67 | return fmt.Errorf("[torproxy]: Couldn't write the response body: %s", err.Error()) 68 | } 69 | 70 | // Replace the URL hosts with the request's host 71 | if err := tmpResponse.ReplaceBody(u.Scheme, u.Host, r.Host); err != nil { 72 | return fmt.Errorf("[torproxy]: Couldn't replace urls inside the response body: %s", err.Error()) 73 | } 74 | 75 | copyHeader(w.Header(), tmpResponse.Header()) 76 | 77 | // Write the status from the temporary ResponseWriter to the main ResponseWriter 78 | w.WriteHeader(tmpResponse.status) 79 | 80 | // Write the final response from the temporary ResponseWriter to the main ResponseWriter 81 | if _, err := w.Write(tmpResponse.Body()); err != nil { 82 | return fmt.Errorf("[torproxy]: Couldn't write the temporary response to main response body: %s", err.Error()) 83 | } 84 | 85 | return nil 86 | } 87 | 88 | // Redirect redirects the request to the previous response's Location header. 89 | func (t *TorResponse) Redirect() error { 90 | u, err := url.Parse(t.Header().Get("Location")) 91 | if err != nil { 92 | return fmt.Errorf("[torproxy]: Couldn't parse the URI from Redirect response: %s", err) 93 | } 94 | 95 | proxy := httputil.NewSingleHostReverseProxy(u) 96 | proxy.Transport = &http.Transport{ 97 | Dial: t.dialer.Dial, 98 | } 99 | 100 | proxy.ServeHTTP(t, t.request) 101 | 102 | return nil 103 | } 104 | --------------------------------------------------------------------------------