├── .github └── workflows │ ├── stale.yml │ └── trigger.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── assets ├── icons │ └── logo.svg └── scss │ ├── _styles_project.scss │ ├── _variables_project.scss │ └── _variables_project_after_bs.scss ├── config.toml ├── content ├── en │ ├── _index.html │ ├── docs │ │ ├── Concepts │ │ │ └── _index.md │ │ ├── Examples │ │ │ └── _index.md │ │ ├── FAQ │ │ │ └── _index.md │ │ ├── Features │ │ │ └── _index.md │ │ ├── Overview │ │ │ └── _index.md │ │ ├── Reference │ │ │ └── _index.md │ │ ├── Setup │ │ │ └── _index.md │ │ └── _index.md │ ├── search-index.md │ └── search.md └── zh-cn │ ├── _index.html │ ├── docs │ ├── Concepts │ │ └── _index.md │ ├── Examples │ │ ├── _index.md │ │ ├── dns.md │ │ ├── https2http.md │ │ ├── multiple-ssh-over-same-port.md │ │ ├── ssh.md │ │ ├── static-file.md │ │ ├── stcp.md │ │ ├── unix-domain-socket.md │ │ ├── vhost-http.md │ │ ├── virtualnet.md │ │ └── xtcp.md │ ├── FAQ │ │ └── _index.md │ ├── Features │ │ ├── _index.md │ │ ├── common │ │ │ ├── _index.md │ │ │ ├── authentication.md │ │ │ ├── client-plugin.md │ │ │ ├── client.md │ │ │ ├── configure.md │ │ │ ├── load-balancer.md │ │ │ ├── monitor.md │ │ │ ├── network │ │ │ │ ├── _index.md │ │ │ │ ├── network-tls.md │ │ │ │ └── network.md │ │ │ ├── range.md │ │ │ ├── realip.md │ │ │ ├── server-manage.md │ │ │ ├── server-plugin.md │ │ │ ├── ssh.md │ │ │ ├── ui.md │ │ │ └── virtualnet.md │ │ ├── http-https │ │ │ ├── _index.md │ │ │ ├── auth.md │ │ │ ├── header.md │ │ │ ├── route.md │ │ │ └── subdomain.md │ │ ├── stcp-sudp │ │ │ └── _index.md │ │ ├── tcp-udp │ │ │ └── _index.md │ │ ├── tcpmux │ │ │ └── _index.md │ │ └── xtcp │ │ │ └── _index.md │ ├── Overview │ │ └── _index.md │ ├── Reference │ │ ├── _index.md │ │ ├── client-configures.md │ │ ├── client-plugin.md │ │ ├── common.md │ │ ├── proxy.md │ │ ├── server-configures.md │ │ ├── visitor-plugin.md │ │ └── visitor.md │ ├── Setup │ │ ├── _index.md │ │ └── systemd.md │ └── _index.md │ ├── release │ └── _index.md │ ├── search-index.md │ └── search.md ├── go.mod ├── go.sum ├── layouts ├── 404.html └── partials │ ├── head.html │ └── toc.html ├── package-lock.json ├── package.json └── static ├── favicons ├── apple-touch-icon-114x114.png ├── apple-touch-icon-120x120.png ├── apple-touch-icon-144x144.png ├── apple-touch-icon-152x152.png ├── apple-touch-icon-57x57.png ├── apple-touch-icon-60x60.png ├── apple-touch-icon-72x72.png ├── apple-touch-icon-76x76.png ├── apple-touch-icon-precomposed.png ├── apple-touch-icon.png ├── favicon-160x160.png ├── favicon-16x16.png ├── favicon-196x196.png ├── favicon-32x32.png ├── favicon-96x96.png ├── mstile-144x144.png ├── mstile-150x150.png ├── mstile-310x310.png └── mstile-70x70.png └── js ├── jquery-3.7.1.min.js └── lunr-2.3.9.min.js /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: "Close stale issues and PRs" 2 | on: 3 | schedule: 4 | - cron: "20 0 * * *" 5 | workflow_dispatch: 6 | inputs: 7 | debug-only: 8 | description: 'In debug mod' 9 | required: false 10 | default: 'false' 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | stale: 16 | permissions: 17 | issues: write # for actions/stale to close stale issues 18 | pull-requests: write # for actions/stale to close stale PRs 19 | actions: write 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/stale@v9 23 | with: 24 | stale-issue-message: 'Issues go stale after 14d of inactivity. Stale issues rot after an additional 3d of inactivity and eventually close.' 25 | stale-pr-message: "PRs go stale after 14d of inactivity. Stale PRs rot after an additional 3d of inactivity and eventually close." 26 | stale-issue-label: 'lifecycle/stale' 27 | exempt-issue-labels: 'bug,doc,enhancement,future,proposal,question,testing,todo,easy,help wanted,assigned' 28 | stale-pr-label: 'lifecycle/stale' 29 | exempt-pr-labels: 'bug,doc,enhancement,future,proposal,question,testing,todo,easy,help wanted,assigned' 30 | days-before-stale: 14 31 | days-before-close: 3 32 | debug-only: ${{ github.event.inputs.debug-only }} 33 | exempt-all-pr-milestones: true 34 | exempt-all-pr-assignees: true 35 | operations-per-run: 200 -------------------------------------------------------------------------------- /.github/workflows/trigger.yml: -------------------------------------------------------------------------------- 1 | name: trigger 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | trigger: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: trigger 13 | run: | 14 | curl \ 15 | -X POST \ 16 | -H "Accept: application/vnd.github+json" \ 17 | -H "Authorization: Bearer ${{ secrets.TRIGGER_TOKEN }}"\ 18 | -H "X-GitHub-Api-Version: 2022-11-28" \ 19 | https://api.github.com/repos/gofrp/frp-site/actions/workflows/build.yml/dispatches \ 20 | -d '{"ref":"master"}' 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | public/ 2 | resources/ 3 | node_modules/ 4 | .hugo_build.lock 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/.gitmodules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution 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 4.0 International Public License 58 | 59 | By exercising the Licensed Rights (defined below), You accept and agree 60 | to be bound by the terms and conditions of this Creative Commons 61 | Attribution 4.0 International Public License ("Public License"). To the 62 | extent this Public License may be interpreted as a contract, You are 63 | granted the Licensed Rights in consideration of Your acceptance of 64 | these terms and conditions, and the Licensor grants You such rights in 65 | consideration of benefits the Licensor receives from making the 66 | Licensed Material available under these terms and conditions. 67 | 68 | 69 | Section 1 -- Definitions. 70 | 71 | a. Adapted Material means material subject to Copyright and Similar 72 | Rights that is derived from or based upon the Licensed Material 73 | and in which the Licensed Material is translated, altered, 74 | arranged, transformed, or otherwise modified in a manner requiring 75 | permission under the Copyright and Similar Rights held by the 76 | Licensor. For purposes of this Public License, where the Licensed 77 | Material is a musical work, performance, or sound recording, 78 | Adapted Material is always produced where the Licensed Material is 79 | synched in timed relation with a moving image. 80 | 81 | b. Adapter's License means the license You apply to Your Copyright 82 | and Similar Rights in Your contributions to Adapted Material in 83 | accordance with the terms and conditions of this Public License. 84 | 85 | c. Copyright and Similar Rights means copyright and/or similar rights 86 | closely related to copyright including, without limitation, 87 | performance, broadcast, sound recording, and Sui Generis Database 88 | Rights, without regard to how the rights are labeled or 89 | categorized. For purposes of this Public License, the rights 90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 91 | Rights. 92 | 93 | d. Effective Technological Measures means those measures that, in the 94 | absence of proper authority, may not be circumvented under laws 95 | fulfilling obligations under Article 11 of the WIPO Copyright 96 | Treaty adopted on December 20, 1996, and/or similar international 97 | agreements. 98 | 99 | e. Exceptions and Limitations means fair use, fair dealing, and/or 100 | any other exception or limitation to Copyright and Similar Rights 101 | that applies to Your use of the Licensed Material. 102 | 103 | f. Licensed Material means the artistic or literary work, database, 104 | or other material to which the Licensor applied this Public 105 | License. 106 | 107 | g. Licensed Rights means the rights granted to You subject to the 108 | terms and conditions of this Public License, which are limited to 109 | all Copyright and Similar Rights that apply to Your use of the 110 | Licensed Material and that the Licensor has authority to license. 111 | 112 | h. Licensor means the individual(s) or entity(ies) granting rights 113 | under this Public License. 114 | 115 | i. Share means to provide material to the public by any means or 116 | process that requires permission under the Licensed Rights, such 117 | as reproduction, public display, public performance, distribution, 118 | dissemination, communication, or importation, and to make material 119 | available to the public including in ways that members of the 120 | public may access the material from a place and at a time 121 | individually chosen by them. 122 | 123 | j. Sui Generis Database Rights means rights other than copyright 124 | resulting from Directive 96/9/EC of the European Parliament and of 125 | the Council of 11 March 1996 on the legal protection of databases, 126 | as amended and/or succeeded, as well as other essentially 127 | equivalent rights anywhere in the world. 128 | 129 | k. You means the individual or entity exercising the Licensed Rights 130 | under this Public License. Your has a corresponding meaning. 131 | 132 | 133 | Section 2 -- Scope. 134 | 135 | a. License grant. 136 | 137 | 1. Subject to the terms and conditions of this Public License, 138 | the Licensor hereby grants You a worldwide, royalty-free, 139 | non-sublicensable, non-exclusive, irrevocable license to 140 | exercise the Licensed Rights in the Licensed Material to: 141 | 142 | a. reproduce and Share the Licensed Material, in whole or 143 | in part; and 144 | 145 | b. produce, reproduce, and Share Adapted Material. 146 | 147 | 2. Exceptions and Limitations. For the avoidance of doubt, where 148 | Exceptions and Limitations apply to Your use, this Public 149 | License does not apply, and You do not need to comply with 150 | its terms and conditions. 151 | 152 | 3. Term. The term of this Public License is specified in Section 153 | 6(a). 154 | 155 | 4. Media and formats; technical modifications allowed. The 156 | Licensor authorizes You to exercise the Licensed Rights in 157 | all media and formats whether now known or hereafter created, 158 | and to make technical modifications necessary to do so. The 159 | Licensor waives and/or agrees not to assert any right or 160 | authority to forbid You from making technical modifications 161 | necessary to exercise the Licensed Rights, including 162 | technical modifications necessary to circumvent Effective 163 | Technological Measures. For purposes of this Public License, 164 | simply making modifications authorized by this Section 2(a) 165 | (4) never produces Adapted Material. 166 | 167 | 5. Downstream recipients. 168 | 169 | a. Offer from the Licensor -- Licensed Material. Every 170 | recipient of the Licensed Material automatically 171 | receives an offer from the Licensor to exercise the 172 | Licensed Rights under the terms and conditions of this 173 | Public License. 174 | 175 | b. No downstream restrictions. You may not offer or impose 176 | any additional or different terms or conditions on, or 177 | apply any Effective Technological Measures to, the 178 | Licensed Material if doing so restricts exercise of the 179 | Licensed Rights by any recipient of the Licensed 180 | Material. 181 | 182 | 6. No endorsement. Nothing in this Public License constitutes or 183 | may be construed as permission to assert or imply that You 184 | are, or that Your use of the Licensed Material is, connected 185 | with, or sponsored, endorsed, or granted official status by, 186 | the Licensor or others designated to receive attribution as 187 | provided in Section 3(a)(1)(A)(i). 188 | 189 | b. Other rights. 190 | 191 | 1. Moral rights, such as the right of integrity, are not 192 | licensed under this Public License, nor are publicity, 193 | privacy, and/or other similar personality rights; however, to 194 | the extent possible, the Licensor waives and/or agrees not to 195 | assert any such rights held by the Licensor to the limited 196 | extent necessary to allow You to exercise the Licensed 197 | Rights, but not otherwise. 198 | 199 | 2. Patent and trademark rights are not licensed under this 200 | Public License. 201 | 202 | 3. To the extent possible, the Licensor waives any right to 203 | collect royalties from You for the exercise of the Licensed 204 | Rights, whether directly or through a collecting society 205 | under any voluntary or waivable statutory or compulsory 206 | licensing scheme. In all other cases the Licensor expressly 207 | reserves any right to collect such royalties. 208 | 209 | 210 | Section 3 -- License Conditions. 211 | 212 | Your exercise of the Licensed Rights is expressly made subject to the 213 | following conditions. 214 | 215 | a. Attribution. 216 | 217 | 1. If You Share the Licensed Material (including in modified 218 | form), You must: 219 | 220 | a. retain the following if it is supplied by the Licensor 221 | with the Licensed Material: 222 | 223 | i. identification of the creator(s) of the Licensed 224 | Material and any others designated to receive 225 | attribution, in any reasonable manner requested by 226 | the Licensor (including by pseudonym if 227 | designated); 228 | 229 | ii. a copyright notice; 230 | 231 | iii. a notice that refers to this Public License; 232 | 233 | iv. a notice that refers to the disclaimer of 234 | warranties; 235 | 236 | v. a URI or hyperlink to the Licensed Material to the 237 | extent reasonably practicable; 238 | 239 | b. indicate if You modified the Licensed Material and 240 | retain an indication of any previous modifications; and 241 | 242 | c. indicate the Licensed Material is licensed under this 243 | Public License, and include the text of, or the URI or 244 | hyperlink to, this Public License. 245 | 246 | 2. You may satisfy the conditions in Section 3(a)(1) in any 247 | reasonable manner based on the medium, means, and context in 248 | which You Share the Licensed Material. For example, it may be 249 | reasonable to satisfy the conditions by providing a URI or 250 | hyperlink to a resource that includes the required 251 | information. 252 | 253 | 3. If requested by the Licensor, You must remove any of the 254 | information required by Section 3(a)(1)(A) to the extent 255 | reasonably practicable. 256 | 257 | 4. If You Share Adapted Material You produce, the Adapter's 258 | License You apply must not prevent recipients of the Adapted 259 | Material from complying with this Public License. 260 | 261 | 262 | Section 4 -- Sui Generis Database Rights. 263 | 264 | Where the Licensed Rights include Sui Generis Database Rights that 265 | apply to Your use of the Licensed Material: 266 | 267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 268 | to extract, reuse, reproduce, and Share all or a substantial 269 | portion of the contents of the database; 270 | 271 | b. if You include all or a substantial portion of the database 272 | contents in a database in which You have Sui Generis Database 273 | Rights, then the database in which You have Sui Generis Database 274 | Rights (but not its individual contents) is Adapted Material; and 275 | 276 | c. You must comply with the conditions in Section 3(a) if You Share 277 | all or a substantial portion of the contents of the database. 278 | 279 | For the avoidance of doubt, this Section 4 supplements and does not 280 | replace Your obligations under this Public License where the Licensed 281 | Rights include other Copyright and Similar Rights. 282 | 283 | 284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 285 | 286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 296 | 297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 306 | 307 | c. The disclaimer of warranties and limitation of liability provided 308 | above shall be interpreted in a manner that, to the extent 309 | possible, most closely approximates an absolute disclaimer and 310 | waiver of all liability. 311 | 312 | 313 | Section 6 -- Term and Termination. 314 | 315 | a. This Public License applies for the term of the Copyright and 316 | Similar Rights licensed here. However, if You fail to comply with 317 | this Public License, then Your rights under this Public License 318 | terminate automatically. 319 | 320 | b. Where Your right to use the Licensed Material has terminated under 321 | Section 6(a), it reinstates: 322 | 323 | 1. automatically as of the date the violation is cured, provided 324 | it is cured within 30 days of Your discovery of the 325 | violation; or 326 | 327 | 2. upon express reinstatement by the Licensor. 328 | 329 | For the avoidance of doubt, this Section 6(b) does not affect any 330 | right the Licensor may have to seek remedies for Your violations 331 | of this Public License. 332 | 333 | c. For the avoidance of doubt, the Licensor may also offer the 334 | Licensed Material under separate terms or conditions or stop 335 | distributing the Licensed Material at any time; however, doing so 336 | will not terminate this Public License. 337 | 338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 339 | License. 340 | 341 | 342 | Section 7 -- Other Terms and Conditions. 343 | 344 | a. The Licensor shall not be bound by any additional or different 345 | terms or conditions communicated by You unless expressly agreed. 346 | 347 | b. Any arrangements, understandings, or agreements regarding the 348 | Licensed Material not stated herein are separate from and 349 | independent of the terms and conditions of this Public License. 350 | 351 | 352 | Section 8 -- Interpretation. 353 | 354 | a. For the avoidance of doubt, this Public License does not, and 355 | shall not be interpreted to, reduce, limit, restrict, or impose 356 | conditions on any use of the Licensed Material that could lawfully 357 | be made without permission under this Public License. 358 | 359 | b. To the extent possible, if any provision of this Public License is 360 | deemed unenforceable, it shall be automatically reformed to the 361 | minimum extent necessary to make it enforceable. If the provision 362 | cannot be reformed, it shall be severed from this Public License 363 | without affecting the enforceability of the remaining terms and 364 | conditions. 365 | 366 | c. No term or condition of this Public License will be waived and no 367 | failure to comply consented to unless expressly agreed to by the 368 | Licensor. 369 | 370 | d. Nothing in this Public License constitutes or may be interpreted 371 | as a limitation upon, or waiver of, any privileges and immunities 372 | that apply to the Licensor or You, including from the legal 373 | processes of any jurisdiction or authority. 374 | 375 | 376 | ======================================================================= 377 | 378 | Creative Commons is not a party to its public 379 | licenses. Notwithstanding, Creative Commons may elect to apply one of 380 | its public licenses to material it publishes and in those instances 381 | will be considered the "Licensor." The text of the Creative Commons 382 | public licenses is dedicated to the public domain under the CC0 Public 383 | Domain Dedication. Except for the limited purpose of indicating that 384 | material is shared under a Creative Commons public license or as 385 | otherwise permitted by the Creative Commons policies published at 386 | creativecommons.org/policies, Creative Commons does not authorize the 387 | use of the trademark "Creative Commons" or any other trademark or logo 388 | of Creative Commons without its prior written consent including, 389 | without limitation, in connection with any unauthorized modifications 390 | to any of its public licenses or any other arrangements, 391 | understandings, or agreements concerning use of licensed material. For 392 | the avoidance of doubt, this paragraph does not form part of the 393 | public licenses. 394 | 395 | Creative Commons may be contacted at creativecommons.org. 396 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # frp-doc 2 | 3 | Documentation(https://gofrp.org) for frp. 4 | 5 | ``` 6 | git clone --recurse-submodules --depth 1 https://github.com/fatedier/frp-doc.git 7 | cd frp-doc 8 | npm install 9 | hugo server 10 | ``` 11 | 12 | Notice that non-extended hugo can't build that doc, see [execute-as-template-of-sass-files-not-working](https://discourse.gohugo.io/t/execute-as-template-of-sass-files-not-working/17627/2). 13 | 14 | If you have any build problems, please check your [hugo](https://github.com/gohugoio/hugo/releases) version, we are using [hugo_extended_0.133.1_Linux-64bit](https://github.com/gohugoio/hugo/releases/download/v0.133.1/hugo_extended_0.133.1_Linux-64bit.tar.gz). 15 | -------------------------------------------------------------------------------- /assets/icons/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /assets/scss/_styles_project.scss: -------------------------------------------------------------------------------- 1 | @import 'td/code-dark' 2 | -------------------------------------------------------------------------------- /assets/scss/_variables_project.scss: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Add styles or override variables from the theme here. 4 | 5 | */ 6 | 7 | .td-page-meta--issue { display: none !important; } 8 | -------------------------------------------------------------------------------- /assets/scss/_variables_project_after_bs.scss: -------------------------------------------------------------------------------- 1 | a { 2 | text-decoration: none; 3 | } 4 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | baseURL = "/" 2 | title = "frp" 3 | 4 | # Language settings 5 | contentDir = "content/zh-cn" 6 | defaultContentLanguage = "zh-cn" 7 | defaultContentLanguageInSubdir = true 8 | # Useful when translating. 9 | enableMissingTranslationPlaceholders = true 10 | 11 | enableRobotsTXT = true 12 | 13 | # Will give values to .Lastmod etc. 14 | enableGitInfo = true 15 | 16 | # Comment out to enable taxonomies in Docsy 17 | disableKinds = ["taxonomy"] 18 | 19 | [taxonomies] 20 | tag = "tags" 21 | category = "categories" 22 | 23 | [params.taxonomy] 24 | # set taxonomyCloud = [] to hide taxonomy clouds 25 | taxonomyCloud = ["tags", "categories"] 26 | # If used, must have same length as taxonomyCloud 27 | taxonomyCloudTitle = ["Tag Cloud", "Categories"] 28 | # set taxonomyPageHeader = [] to hide taxonomies on the page headers 29 | taxonomyPageHeader = ["tags", "categories"] 30 | 31 | # Highlighting config 32 | pygmentsCodeFences = true 33 | pygmentsUseClasses = false 34 | # Use the new Chroma Go highlighter in Hugo. 35 | pygmentsUseClassic = false 36 | #pygmentsOptions = "linenos=table" 37 | # See https://help.farbox.com/pygments.html 38 | pygmentsStyle = "tango" 39 | 40 | # Configure how URLs look like per section. 41 | [permalinks] 42 | blog = "/:section/:year/:month/:day/:slug/" 43 | 44 | ## Configuration for BlackFriday markdown parser: https://github.com/russross/blackfriday 45 | [blackfriday] 46 | plainIDAnchors = true 47 | hrefTargetBlank = true 48 | angledQuotes = false 49 | latexDashes = true 50 | 51 | # Image processing configuration. 52 | [imaging] 53 | resampleFilter = "CatmullRom" 54 | quality = 75 55 | anchor = "smart" 56 | 57 | # Additional menu items 58 | [[menu.main]] 59 | name = "Github" 60 | weight = 50 61 | url = "https://github.com/fatedier/frp" 62 | pre = "" 63 | 64 | [services] 65 | [services.googleAnalytics] 66 | # Comment out the next line to disable GA tracking. Also disables the feature described in [params.ui.feedback]. 67 | # id = "UA-00000000-0" 68 | 69 | # Language configuration 70 | 71 | [languages] 72 | [languages.en] 73 | title = "frp" 74 | languageName ="English" 75 | # Weight used for sorting. 76 | weight = 1 77 | contentDir = "content/en" 78 | params.description = "frp official website" 79 | [languages.zh-cn] 80 | title = "frp" 81 | languageName ="中文" 82 | weight = 2 83 | contentDir = "content/zh-cn" 84 | params.description = "frp official website" 85 | 86 | [markup] 87 | [markup.goldmark] 88 | [markup.goldmark.parser.attribute] 89 | block = true 90 | [markup.goldmark.renderer] 91 | unsafe = true 92 | [markup.highlight] 93 | # See a complete list of available styles at https://xyproto.github.io/splash/docs/all.html 94 | style = "tango" 95 | noClasses = false 96 | # Uncomment if you want your chosen highlight style used for code blocks without a specified language 97 | # guessSyntax = "true" 98 | 99 | # Everything below this are Site Params 100 | # [outputs] 101 | # section = ["HTML", "print", "RSS"] 102 | 103 | [params] 104 | copyright = "The frp Authors" 105 | # privacy_policy = "https://policies.google.com/privacy" 106 | 107 | # First one is picked as the Twitter card image if not set on page. 108 | # images = ["images/project-illustration.png"] 109 | 110 | # Menu title if your navbar has a versions selector to access old versions of your site. 111 | # This menu appears only if you have at least one [params.versions] set. 112 | version_menu = "Releases" 113 | 114 | # Flag used in the "version-banner" partial to decide whether to display a 115 | # banner on every page indicating that this is an archived version of the docs. 116 | # Set this flag to "true" if you want to display the banner. 117 | archived_version = false 118 | 119 | # The version number for the version of the docs represented in this doc set. 120 | # Used in the "version-banner" partial to display a version number for the 121 | # current doc set. 122 | version = "0.0" 123 | 124 | # A link to latest version of the docs. Used in the "version-banner" partial to 125 | # point people to the main doc site. 126 | url_latest_version = "https://example.com" 127 | 128 | # Repository configuration (URLs for in-page links to opening issues and suggesting changes) 129 | github_repo = "https://github.com/gofrp/frp-doc" 130 | # An optional link to a related project repo. For example, the sibling repository where your product code lives. 131 | github_project_repo = "https://github.com/fatedier/frp" 132 | 133 | # Specify a value here if your content directory is not in your repo's root directory 134 | # github_subdir = "" 135 | 136 | # Uncomment this if you have a newer GitHub repo with "main" as the default branch, 137 | # or specify a new value if you want to reference another branch in your GitHub links 138 | github_branch= "master" 139 | 140 | # Google Custom Search Engine ID. Remove or comment out to disable search. 141 | # gcs_engine_id = "011737558837375720776:fsdu1nryfng" 142 | 143 | # Enable Lunr.js offline search 144 | offlineSearch = true 145 | 146 | # Enable syntax highlighting and copy buttons on code blocks with Prism 147 | prism_syntax_highlighting = false 148 | 149 | # User interface configuration 150 | [params.ui] 151 | # Set to true to disable breadcrumb navigation. 152 | breadcrumb_disable = false 153 | # Set to true to enable the About link in the site footer 154 | footer_about_enable = true 155 | # Set to false if you don't want to display a logo (/assets/icons/logo.svg) in the top nav bar 156 | navbar_logo = true 157 | # Set to true if you don't want the top navbar to be translucent when over a `block/cover`, like on the homepage. 158 | navbar_translucent_over_cover_disable = false 159 | # Enable to show the side bar menu in its compact state. 160 | sidebar_menu_compact = true 161 | # Set to true to hide the sidebar search box (the top nav search box will still be displayed if search is enabled) 162 | sidebar_search_disable = false 163 | # As well as the completely expanded and compact menu options, you can also create a foldable menu by setting the site parameter. 164 | sidebar_menu_foldable = true 165 | # On large sites (default: > 2000 pages) the section menu is not generated for each page, 166 | # but cached for the whole section. The HTML classes for marking the active menu item (and menu path) are then set using JS. 167 | sidebar_cache_limit = 2000 168 | # Set a desired menu depth to always be visible 169 | ul_show = 1 170 | showLightDarkModeMenu = true 171 | 172 | # Adds a H2 section titled "Feedback" to the bottom of each doc. The responses are sent to Google Analytics as events. 173 | # This feature depends on [services.googleAnalytics] and will be disabled if "services.googleAnalytics.id" is not set. 174 | # If you want this feature, but occasionally need to remove the "Feedback" section from a single page, 175 | # add "hide_feedback: true" to the page's front matter. 176 | [params.ui.feedback] 177 | enable = false 178 | # The responses that the user sees after clicking "yes" (the page was helpful) or "no" (the page was not helpful). 179 | yes = 'Glad to hear it! Please tell us how we can improve.' 180 | no = 'Sorry to hear that. Please tell us how we can improve.' 181 | 182 | # Adds a reading time to the top of each doc. 183 | # If you want this feature, but occasionally need to remove the Reading time from a single page, 184 | # add "hide_readingtime: true" to the page's front matter 185 | [params.ui.readingtime] 186 | enable = false 187 | 188 | [params.links] 189 | # End user relevant links. These will show up on left side of footer and in the community page if you have one. 190 | #[[params.links.user]] 191 | # name = "Stack Overflow" 192 | # url = "https://example.org/stack" 193 | # icon = "fab fa-stack-overflow" 194 | # desc = "Practical questions and curated answers" 195 | 196 | # Developer relevant links. These will show up on right side of footer and in the community page if you have one. 197 | [[params.links.developer]] 198 | name = "GitHub" 199 | url = "https://github.com/fatedier/frp" 200 | icon = "fab fa-github" 201 | desc = "Development takes place here!" 202 | #[[params.links.developer]] 203 | # name = "Developer mailing list" 204 | # url = "https://example.org/mail" 205 | # icon = "fa fa-envelope" 206 | # desc = "Discuss development issues around the project" 207 | 208 | [module] 209 | proxy = "direct" 210 | [module.hugoVersion] 211 | extended = true 212 | min = "0.119.0" 213 | max = "0.133.1" 214 | [[module.imports]] 215 | path = "github.com/google/docsy" 216 | [[module.imports]] 217 | path = "github.com/google/docsy/dependencies" 218 | -------------------------------------------------------------------------------- /content/en/_index.html: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Goldydocs" 3 | linkTitle = "Goldydocs" 4 | 5 | +++ 6 | 7 | {{< blocks/cover title="Welcome to FRP: A Fast Reverse Proxy!" height="full">}} 8 |
9 | }}"> 10 | Learn More 11 | 12 | 13 | GITHUB 14 | 15 |

frp helps you expose your service behind a firewall or NAT to the public internet.

16 | {{< blocks/link-down color="info" >}} 17 |
18 | {{< /blocks/cover >}} 19 | 20 | 21 | {{% blocks/lead color="primary" %}} 22 | frp supports multiple proxy types like TCP, UDP, HTTP, HTTPS, STCP, SUDP, XTCP, TCPMUX. 23 | {{% /blocks/lead %}} 24 | 25 | {{< blocks/section color="white">}} 26 | {{% blocks/feature icon="fab fa-app-store-ios" title="Download" %}} 27 | Download from Github [Release](https://github.com/fatedier/frp/releases). 28 | {{% /blocks/feature %}} 29 | 30 | {{% blocks/feature icon="fab fa-github" title="Contributions welcome!" url="https://github.com/fatedier/frp" %}} 31 | We do a [Issue](https://github.com/fatedier/frp/issues) and [Pull Request](https://github.com/fatedier/frp/pulls) contributions workflow on **GitHub**. New users are always welcome! 32 | {{% /blocks/feature %}} 33 | 34 | {{< /blocks/section >}} 35 | -------------------------------------------------------------------------------- /content/en/docs/Concepts/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Concepts" 3 | weight: 3 4 | description: > 5 | Learn these concepts can help you use frp in a better way. 6 | --- 7 | -------------------------------------------------------------------------------- /content/en/docs/Examples/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Examples" 3 | weight: 3 4 | --- 5 | -------------------------------------------------------------------------------- /content/en/docs/FAQ/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "FAQ" 3 | weight: 7 4 | --- 5 | -------------------------------------------------------------------------------- /content/en/docs/Features/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Features" 3 | weight: 5 4 | --- 5 | -------------------------------------------------------------------------------- /content/en/docs/Overview/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Overview" 3 | weight: 1 4 | --- 5 | -------------------------------------------------------------------------------- /content/en/docs/Reference/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Reference" 3 | weight: 6 4 | --- 5 | -------------------------------------------------------------------------------- /content/en/docs/Setup/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Setup" 3 | weight: 2 4 | --- 5 | -------------------------------------------------------------------------------- /content/en/docs/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Documentation" 3 | linkTitle: "Documentation" 4 | weight: 20 5 | menu: 6 | main: 7 | weight: 20 8 | --- 9 | -------------------------------------------------------------------------------- /content/en/search-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | type: "search-index" 3 | url: "index.json" 4 | --- 5 | -------------------------------------------------------------------------------- /content/en/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Search Results 3 | layout: search 4 | 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /content/zh-cn/_index.html: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "frp" 3 | linkTitle = "frp" 4 | 5 | +++ 6 | 7 | {{< blocks/cover title="简单、高效的内网穿透工具" height="full">}} 8 |
9 | }}"> 10 |    起步 11 | 12 | 13 | GITHUB 14 | 15 |

frp 支持多种代理类型以及 P2P 通信,为不同场景下的需求提供丰富的解决方案。

16 | {{< blocks/link-down color="info" >}} 17 |
18 | {{< /blocks/cover >}} 19 | 20 | 21 | {{% blocks/lead color="primary" %}} 22 | frp 采用 C/S 模式,将服务端部署在具有公网 IP 的机器上,客户端部署在内网或防火墙内的机器上,通过访问暴露在服务器上的端口,反向代理到处于内网的服务。 23 | 在此基础上,frp 支持 TCP, UDP, HTTP, HTTPS 等多种协议,提供了加密、压缩,身份认证,代理限速,负载均衡等众多能力。此外,还可以通过 xtcp 实现 P2P 通信。 24 | {{% /blocks/lead %}} 25 | 26 | {{< blocks/section color="white" type="row" >}} 27 | {{% blocks/feature icon="fab fa-app-store-ios" title="下载" %}} 28 | 从 Github [Release](https://github.com/fatedier/frp/releases) 页面下载最新版本。 29 | {{% /blocks/feature %}} 30 | 31 | 32 | {{% blocks/feature icon="fab fa-github" title="欢迎参与贡献!" url="https://github.com/fatedier/frp" %}} 33 | 在 Github 上提交 [Issue](https://github.com/fatedier/frp/issues) 和 [Pull Request](https://github.com/fatedier/frp/pulls)。 34 | {{% /blocks/feature %}} 35 | 36 | 37 | {{% blocks/feature icon="fab fa-weixin" title="交流" url="https://t.zsxq.com/eUvBMrZ" %}} 38 | 付费加入知识星球兴趣圈 [frp](https://t.zsxq.com/eUvBMrZ) 寻求更多帮助。 39 | {{% /blocks/feature %}} 40 | {{< /blocks/section >}} 41 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Concepts/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "概念" 3 | weight: 3 4 | description: > 5 | 了解以下概念有助于更好地理解和使用 frp。 6 | --- 7 | 8 | ## 工作原理 9 | 10 | frp 主要由两个组件组成:客户端(frpc) 和 服务端(frps)。通常情况下,服务端部署在具有公网 IP 地址的机器上,而客户端部署在需要穿透的内网服务所在的机器上。 11 | 12 | 由于内网服务缺乏公网 IP 地址,因此无法直接被非局域网内的用户访问。用户通过访问服务端的 frps,frp 负责根据请求的端口或其他信息将请求路由到相应的内网机器,从而实现通信。 13 | 14 | ## 代理 15 | 16 | 在 frp 中,一个代理对应一个需要公开访问的内网服务。一个客户端可以同时配置多个代理,以满足不同的需求。 17 | 18 | ## 代理类型 19 | 20 | frp 支持多种代理类型,以适应不同的使用场景。以下是一些常见的代理类型: 21 | 22 | - **TCP**:提供纯粹的 TCP 端口映射,使服务端能够根据不同的端口将请求路由到不同的内网服务。 23 | - **UDP**:提供纯粹的 UDP 端口映射,与 TCP 代理类似,但用于 UDP 流量。 24 | - **HTTP**:专为 HTTP 应用设计,支持修改 Host Header 和增加鉴权等额外功能。 25 | - **HTTPS**:类似于 HTTP 代理,但专门用于处理 HTTPS 流量。 26 | - **STCP**:提供安全的 TCP 内网代理,要求在被访问者和访问者的机器上都部署 frpc,不需要在服务端暴露端口。 27 | - **SUDP**:提供安全的 UDP 内网代理,与 STCP 类似,需要在被访问者和访问者的机器上都部署 frpc,不需要在服务端暴露端口。 28 | - **XTCP**:点对点内网穿透代理,与 STCP 类似,但流量不需要经过服务器中转。 29 | - **TCPMUX**:支持服务端 TCP 端口的多路复用,允许通过同一端口访问不同的内网服务。 30 | 31 | 每种代理类型适用于不同的使用情境,您可以根据需求选择合适的代理类型来配置 frp。 32 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "示例" 3 | weight: 4 4 | description: > 5 | 在这里,您将找到多个常见的使用场景和配置示例,可供您用来亲自部署和体验这些示例。 6 | --- 7 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/dns.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "转发 DNS 查询请求" 3 | weight: 20 4 | description: > 5 | 本示例演示如何通过简单配置 UDP 类型的代理来实现 DNS 查询请求的转发。 6 | --- 7 | 8 | DNS 查询请求通常使用 UDP 协议,而 frp 支持对内网 UDP 服务的穿透,配置方式与 TCP 类似。 9 | 10 | ### 步骤 11 | 12 | 1. **配置 frps.toml** 13 | 14 | 在 frps.toml 文件中添加以下内容: 15 | 16 | ```toml 17 | bindPort = 7000 18 | ``` 19 | 20 | 2. **配置 frpc.toml** 21 | 22 | 在 frpc.toml 文件中添加以下内容: 23 | 24 | ```toml 25 | serverAddr = "x.x.x.x" 26 | serverPort = 7000 27 | 28 | [[proxies]] 29 | name = "dns" 30 | type = "udp" 31 | localIP = "8.8.8.8" 32 | localPort = 53 33 | remotePort = 6000 34 | ``` 35 | 36 | 请注意,这里示例中反代了 Google 的 DNS 查询服务器的地址,仅用于测试 UDP 代理,并没有实际意义。 37 | 38 | 3. **启动 frps 和 frpc** 39 | 40 | 分别启动 frps 和 frpc。 41 | 42 | 4. **测试 DNS 查询请求** 43 | 44 | 使用以下命令通过 `dig` 工具测试 UDP 包转发是否成功,预期会返回 `www.baidu.com` 域名的解析结果: 45 | 46 | ```bash 47 | dig @x.x.x.x -p 6000 www.baidu.com 48 | ``` 49 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/https2http.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "为本地 HTTP 服务启用 HTTPS" 3 | weight: 35 4 | description: > 5 | 使用 `https2http` 插件将本地 HTTP 服务转换为 HTTPS 服务,以供外部访问。 6 | --- 7 | 8 | ### 步骤 9 | 10 | 1. **配置 frps.toml** 11 | 12 | ```toml 13 | bindPort = 7000 14 | vhostHTTPSPort = 443 15 | ``` 16 | 17 | 2. **配置 frpc.toml** 18 | 19 | ```toml 20 | serverAddr = "x.x.x.x" 21 | serverPort = 7000 22 | 23 | [[proxies]] 24 | name = "test_htts2http" 25 | type = "https" 26 | customDomains = ["test.yourdomain.com"] 27 | 28 | [proxies.plugin] 29 | type = "https2http" 30 | localAddr = "127.0.0.1:80" 31 | 32 | # HTTPS 证书相关的配置 33 | crtPath = "./server.crt" 34 | keyPath = "./server.key" 35 | hostHeaderRewrite = "127.0.0.1" 36 | requestHeaders.set.x-from-where = "frp" 37 | ``` 38 | 39 | 请注意,您需要根据您的域名和证书路径自行更改上述配置。 40 | 41 | 3. **启动 frps 和 frpc** 42 | 43 | 4. **访问 HTTPS 服务** 44 | 45 | 打开您的 Web 浏览器,访问 `https://test.yourdomain.com`。 46 | 47 | 通过按照以上步骤进行配置,您将能够为本地 HTTP 服务启用 HTTPS,以实现安全的外部访问。 48 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/multiple-ssh-over-same-port.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "多个 SSH 服务复用同一端口" 3 | weight: 10 4 | description: > 5 | 通过使用 tcpmux 类型的代理,您可以实现多个 SSH 服务通过同一端口进行暴露。这种方法还适用于任何支持 HTTP Connect 代理连接方式的客户端,以实现端口的复用。 6 | --- 7 | 8 | ### 步骤 9 | 10 | 1. **在具有公网 IP 的机器上部署 frps** 11 | 12 | 修改 frps.toml 文件以包含以下内容(这里使用了最简化的配置): 13 | 14 | ```toml 15 | bindPort = 7000 16 | tcpmuxHTTPConnectPort = 5002 17 | ``` 18 | 19 | 2. **在内网机器 A 上部署 frpc** 20 | 21 | 创建 frpc 配置文件,例如 frpc.toml,然后将以下内容添加到配置文件中: 22 | 23 | ```toml 24 | serverAddr = "x.x.x.x" 25 | serverPort = 7000 26 | 27 | [[proxies]] 28 | name = "ssh1" 29 | type = "tcpmux" 30 | multiplexer = "httpconnect" 31 | customDomains = ["machine-a.example.com"] 32 | localIP = "127.0.0.1" 33 | localPort = 22 34 | ``` 35 | 36 | 3. **在内网机器 B 上部署另一个 frpc** 37 | 38 | 创建 frpc 配置文件,例如 frpc.toml,然后将以下内容添加到配置文件中: 39 | 40 | ```toml 41 | serverAddr = "x.x.x.x" 42 | serverPort = 7000 43 | 44 | [[proxies]] 45 | name = "ssh2" 46 | type = "tcpmux" 47 | multiplexer = "httpconnect" 48 | customDomains = ["machine-b.example.com"] 49 | localIP = "127.0.0.1" 50 | localPort = 22 51 | ``` 52 | 53 | 4. **通过 SSH ProxyCommand 访问内网机器 A** 54 | 55 | 使用 SSH ProxyCommand 访问内网机器 A,假设用户名为 test。使用以下命令: 56 | 57 | ```bash 58 | ssh -o 'proxycommand socat - PROXY:x.x.x.x:%h:%p,proxyport=5002' test@machine-a.example.com 59 | ``` 60 | 61 | 要访问内网机器 B,只需更改域名,假设用户名仍然为 test: 62 | 63 | ```bash 64 | ssh -o 'proxycommand socat - PROXY:x.x.x.x:%h:%p,proxyport=5002' test@machine-b.example.com 65 | ``` 66 | 67 | 通过按照以上步骤进行配置,您可以实现多个 SSH 服务复用同一端口,以便在具有公网 IP 的机器上进行访问。 68 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/ssh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "通过 SSH 访问内网机器" 3 | weight: 5 4 | description: > 5 | 通过简单配置 TCP 类型的代理,使用户能够访问内网服务器。 6 | --- 7 | 8 | ### 步骤 9 | 10 | 1. **在具有公网 IP 的机器上部署 frps** 11 | 12 | 部署 frps 并编辑 frps.toml 文件。以下是简化的配置,其中设置了 frp 服务器用于接收客户端连接的端口: 13 | 14 | ```toml 15 | bindPort = 7000 16 | ``` 17 | 18 | 2. **在需要被访问的内网机器上部署 frpc** 19 | 20 | 部署 frpc 并编辑 frpc.toml 文件,假设 frps 所在服务器的公网 IP 地址为 x.x.x.x。以下是示例配置: 21 | 22 | ```toml 23 | serverAddr = "x.x.x.x" 24 | serverPort = 7000 25 | 26 | [[proxies]] 27 | name = "ssh" 28 | type = "tcp" 29 | localIP = "127.0.0.1" 30 | localPort = 22 31 | remotePort = 6000 32 | ``` 33 | 34 | * `localIP` 和 `localPort` 配置为需要从公网访问的内网服务的地址和端口。 35 | * `remotePort` 表示在 frp 服务端监听的端口,访问此端口的流量将被转发到本地服务的相应端口。 36 | 37 | 3. **启动 frps 和 frpc** 38 | 39 | 4. **通过 SSH 访问内网机器** 40 | 41 | 使用以下命令通过 SSH 访问内网机器,假设用户名为 test: 42 | 43 | ```bash 44 | ssh -o Port=6000 test@x.x.x.x 45 | ``` 46 | 47 | frp 将请求发送到 `x.x.x.x:6000` 的流量转发到内网机器的 22 端口。 48 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/static-file.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "对外提供简单的文件访问服务" 3 | weight: 30 4 | description: > 5 | 通过配置 `static_file` 客户端插件,您可以将本地文件暴露在公网上,以供其他人访问。 6 | --- 7 | 8 | 通过使用 `static_file` 插件,您可以轻松地提供一个基于 HTTP 的文件访问服务,让其他人可以访问您指定的文件。 9 | 10 | ### 步骤 11 | 12 | 1. **配置 frps.toml** 13 | 14 | 在 frps.toml 文件中添加以下内容: 15 | 16 | ```toml 17 | bindPort = 7000 18 | ``` 19 | 20 | 2. **配置 frpc.toml** 21 | 22 | 在 frpc.toml 文件中添加以下内容,确保设置合适的文件路径、用户名和密码: 23 | 24 | ```toml 25 | serverAddr = "x.x.x.x" 26 | serverPort = 7000 27 | 28 | [[proxies]] 29 | name = "test_static_file" 30 | type = "tcp" 31 | remotePort = 6000 32 | [proxies.plugin] 33 | type = "static_file" 34 | # 本地文件目录,对外提供访问 35 | localPath = "/tmp/file" 36 | # URL 中的前缀,将被去除,保留的内容即为要访问的文件路径 37 | stripPrefix = "static" 38 | httpUser = "abc" 39 | httpPassword = "abc" 40 | ``` 41 | 42 | 请根据实际情况修改 `localPath`、`stripPrefix`、`httpUser` 和 `httpPassword`。 43 | 44 | 3. **启动 frps 和 frpc** 45 | 46 | 4. **通过浏览器访问文件** 47 | 48 | 使用浏览器访问 `http://x.x.x.x:6000/static/`,以查看位于 `/tmp/file` 目录下的文件。系统会要求输入您设置的用户名和密码。 49 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/stcp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "安全地暴露内网服务" 3 | weight: 40 4 | description: > 5 | 通过创建一个只有授权用户能够访问的 SSH 服务代理,实现内网服务的安全暴露。 6 | --- 7 | 8 | 某些内网服务,如果直接暴露在公网上,可能存在安全风险。使用 `stcp(secret tcp)` 类型的代理可以让您安全地将内网服务暴露给经过授权的用户,这需要访问者也部署 frpc 客户端。 9 | 10 | ### 步骤 11 | 12 | 1. **配置 frps.toml** 13 | 14 | 在 frps.toml 文件中添加以下内容: 15 | 16 | ```toml 17 | bindPort = 7000 18 | ``` 19 | 20 | 2. **部署 frpc 客户端并配置** 21 | 22 | 在需要将内网服务暴露到公网的机器上部署 frpc,并创建如下配置: 23 | 24 | ```toml 25 | serverAddr = "x.x.x.x" 26 | serverPort = 7000 27 | 28 | [[proxies]] 29 | name = "secret_ssh" 30 | type = "stcp" 31 | # 只有与此处设置的 secretKey 一致的用户才能访问此服务 32 | secretKey = "abcdefg" 33 | localIP = "127.0.0.1" 34 | localPort = 22 35 | ``` 36 | 37 | 3. **在访问者机器上部署并配置 frpc** 38 | 39 | 在想要访问内网服务的机器上也部署 frpc,并创建如下配置: 40 | 41 | ```toml 42 | serverAddr = "x.x.x.x" 43 | serverPort = 7000 44 | 45 | [[visitors]] 46 | name = "secret_ssh_visitor" 47 | type = "stcp" 48 | # 要访问的 stcp 代理的名字 49 | serverName = "secret_ssh" 50 | secretKey = "abcdefg" 51 | # 绑定本地端口以访问 SSH 服务 52 | bindAddr = "127.0.0.1" 53 | bindPort = 6000 54 | ``` 55 | 56 | 4. **通过 SSH 访问内网机器** 57 | 58 | 使用以下命令通过 SSH 访问内网机器,假设用户名为 test: 59 | 60 | ```bash 61 | ssh -o Port=6000 test@127.0.0.1 62 | ``` 63 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/unix-domain-socket.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "转发 Unix 域套接字" 3 | weight: 25 4 | description: > 5 | 通过配置 Unix 域套接字客户端插件,您可以使用 TCP 端口访问内网的 Unix 域套接字服务,例如 Docker Daemon。 6 | --- 7 | 8 | ### 步骤 9 | 10 | 1. **配置 frps.toml** 11 | 12 | 在 frps.toml 文件中添加以下内容: 13 | 14 | ```toml 15 | bindPort = 7000 16 | ``` 17 | 18 | 2. **配置 frpc.toml** 19 | 20 | 在 frpc.toml 文件中添加以下内容,确保设置正确的 Unix 域套接字路径: 21 | 22 | ```toml 23 | serverAddr = "x.x.x.x" 24 | serverPort = 7000 25 | 26 | [[proxies]] 27 | name = "unix_domain_socket" 28 | type = "tcp" 29 | remotePort = 6000 30 | [proxies.plugin] 31 | type = "unix_domain_socket" 32 | # Unix 域套接字路径 33 | unixPath = "/var/run/docker.sock" 34 | ``` 35 | 36 | 3. **启动 frps 和 frpc** 37 | 38 | 4. **使用 curl 查看 Docker 版本信息** 39 | 40 | ```bash 41 | curl http://x.x.x.x:6000/version 42 | ``` 43 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/vhost-http.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "通过自定义域名访问内网的 Web 服务" 3 | weight: 15 4 | description: > 5 | 通过简单配置 HTTP 类型的代理,您可以让用户通过自定义域名访问内网的 Web 服务。 6 | --- 7 | 8 | HTTP 类型的代理非常适合将内网的 Web 服务通过自定义域名提供给外部用户。相比于 TCP 类型代理,HTTP 代理不仅可以复用端口,还提供了基于 HTTP 协议的许多功能。 9 | 10 | HTTPS 与此类似,但是需要注意,frp 的 https 代理需要本地服务是 HTTPS 服务,frps 端不会做 TLS 终止。也可以结合 https2http 插件来实现将本地的 HTTP 服务以 HTTPS 协议暴露出去。 11 | 12 | ### 步骤 13 | 14 | 1. **配置 frps.toml** 15 | 16 | 在 frps.toml 文件中添加以下内容,以指定 HTTP 请求的监听端口为 8080: 17 | 18 | ```toml 19 | bindPort = 7000 20 | vhostHTTPPort = 8080 21 | ``` 22 | 23 | 如果需要配置 HTTPS 代理,还需要设置 `vhostHTTPSPort`。 24 | 25 | 2. **配置 frpc.toml** 26 | 27 | 在 frpc.toml 文件中添加以下内容,确保设置了正确的服务器 IP 地址、本地 Web 服务监听端口和自定义域名: 28 | 29 | ```toml 30 | serverAddr = "x.x.x.x" 31 | serverPort = 7000 32 | 33 | [[proxies]] 34 | name = "web" 35 | type = "http" 36 | localPort = 80 37 | customDomains = ["www.yourdomain.com"] 38 | 39 | [[proxies]] 40 | name = "web2" 41 | type = "http" 42 | localPort = 8080 43 | customDomains = ["www.yourdomain2.com"] 44 | ``` 45 | 46 | 3. **启动 frps 和 frpc** 47 | 48 | 4. **域名解析** 49 | 50 | 将 `www.yourdomain.com` 和 `www.yourdomain2.com` 的域名 A 记录解析到服务器的 IP 地址 `x.x.x.x`。如果服务器已经有对应的域名,您还可以将 CNAME 记录解析到原始域名。另外,通过修改 HTTP 请求的 Host 字段也可以实现相同的效果。 51 | 52 | 53 | 5. **通过浏览器访问** 54 | 55 | 使用浏览器访问 `http://www.yourdomain.com:8080` 即可访问内网机器上的 80 端口服务,访问 `http://www.yourdomain2.com:8080` 可以访问内网机器上的 8080 端口服务。 56 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/virtualnet.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "虚拟网络 (VirtualNet)" 3 | weight: 50 4 | description: > 5 | 使用 `virtual_net` 插件创建虚拟网络连接,实现客户端之间的 IP 层通信。 6 | --- 7 | 8 | > **注意**:VirtualNet 是一个 Alpha 阶段的特性,目前不稳定,其配置方式和功能可能会在后续版本中随时调整变更。请勿在生产环境中使用此功能,仅建议用于测试和评估目的。 9 | 10 | ### 概述 11 | 12 | 虚拟网络(VirtualNet)功能是 frp v0.62.0 中引入的 Alpha 特性,它允许 frp 通过 TUN 接口创建和管理客户端与访问者之间的虚拟网络连接,实现设备间的完整网络连通性。 13 | 14 | 本示例将展示如何配置和使用 VirtualNet 功能。更多详细信息和工作原理,请参考 [虚拟网络 (VirtualNet)](/docs/Features/common/virtualnet) 特性文档。 15 | 16 | ### 启用 VirtualNet 17 | 18 | 首先,由于 VirtualNet 目前是一个 Alpha 特性,您需要在配置中通过特性门控来启用它: 19 | 20 | ```toml 21 | # frpc.toml 22 | featureGates = { VirtualNet = true } 23 | ``` 24 | 25 | ### 示例配置 26 | 27 | 以下示例展示如何在两台机器之间建立虚拟网络连接: 28 | 29 | #### 服务端配置 (机器 A) 30 | 31 | 1. **在 frpc.toml 中配置虚拟网络地址** 32 | 33 | ```toml 34 | # frpc.toml (服务端) 35 | serverAddr = "x.x.x.x" 36 | serverPort = 7000 37 | featureGates = { VirtualNet = true } 38 | 39 | # 配置虚拟网络接口 40 | virtualNet.address = "100.86.0.1/24" 41 | 42 | [[proxies]] 43 | name = "vnet-server" 44 | type = "stcp" 45 | secretKey = "your-secret-key" 46 | [proxies.plugin] 47 | type = "virtual_net" 48 | ``` 49 | 50 | 2. **启动 frpc** 51 | 52 | ```bash 53 | sudo frpc -c frpc.toml 54 | ``` 55 | 56 | 注意:创建 TUN 接口需要 root 权限 57 | 58 | #### 客户端配置 (机器 B) 59 | 60 | 1. **在 frpc.toml 中配置访问者** 61 | 62 | ```toml 63 | # frpc.toml (客户端) 64 | serverAddr = "x.x.x.x" 65 | serverPort = 7000 66 | featureGates = { VirtualNet = true } 67 | 68 | # 配置虚拟网络接口 69 | virtualNet.address = "100.86.0.2/24" 70 | 71 | [[visitors]] 72 | name = "vnet-visitor" 73 | type = "stcp" 74 | serverName = "vnet-server" 75 | secretKey = "your-secret-key" 76 | bindPort = -1 77 | [visitors.plugin] 78 | type = "virtual_net" 79 | destinationIP = "100.86.0.1" 80 | ``` 81 | 82 | 2. **启动 frpc** 83 | 84 | ```bash 85 | sudo frpc -c frpc.toml 86 | ``` 87 | 88 | ### 测试连接 89 | 90 | 成功配置后,您可以从机器 B 通过虚拟 IP 地址访问机器 A: 91 | 92 | ```bash 93 | # 在机器 B 上执行 94 | ping 100.86.0.1 95 | ``` 96 | 97 | 如果连接正常,您将看到来自 100.86.0.1 的响应。 98 | 99 | ### 限制和要求 100 | 101 | - **Alpha 阶段特性**:VirtualNet 是实验性功能,配置和 API 可能在未来版本中变化,不建议在生产环境中使用 102 | - **权限要求**:创建 TUN 接口需要提升的权限(root/管理员) 103 | - **平台支持**:目前仅支持 Linux 和 macOS 104 | - **默认状态**:作为 Alpha 特性,VirtualNet 默认是禁用的 -------------------------------------------------------------------------------- /content/zh-cn/docs/Examples/xtcp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "点对点内网穿透" 3 | weight: 45 4 | description: > 5 | 这个示例将演示如何通过点对点 (P2P) 连接来访问内网服务,流量不会通过服务器中转。 6 | --- 7 | 8 | frp 提供了一种新的代理类型 `xtcp`,用于在需要传输大量数据且不希望流量经过服务器的情况下实现内网穿透。 9 | 10 | 与 `stcp` 类似,使用 `xtcp` 需要在两端都部署 frpc 以建立直接连接。 11 | 12 | 需要注意的是,`xtcp` 并不适用于所有类型的 NAT 设备,如果穿透失败,可以尝试使用 `stcp` 代理。 13 | 14 | ### 步骤 15 | 16 | 1. **配置需要暴露到外网的机器上的 frpc.toml 文件** 17 | 18 | 在 frpc.toml 文件中添加以下内容,确保设置了正确的服务器地址和端口以及共享密钥 (`secretKey`),以及本地服务的 IP 地址和端口: 19 | 20 | ```toml 21 | serverAddr = "x.x.x.x" 22 | serverPort = 7000 23 | # 如果默认的 STUN 服务器不可用,可以配置一个新的 STUN 服务器 24 | # natHoleStunServer = "xxx" 25 | 26 | [[proxies]] 27 | name = "p2p_ssh" 28 | type = "xtcp" 29 | # 只有共享密钥 (secretKey) 与服务器端一致的用户才能访问该服务 30 | secretKey = "abcdefg" 31 | localIP = "127.0.0.1" 32 | localPort = 22 33 | ``` 34 | 35 | 2. **在想要访问内网服务的机器上部署 frpc** 36 | 37 | 在 frpc.toml 文件中添加以下内容,确保设置了正确的服务器地址和端口,共享密钥 (`secretKey`) 以及要访问的 P2P 代理的名称: 38 | 39 | ```toml 40 | serverAddr = "x.x.x.x" 41 | serverPort = 7000 42 | # 如果默认的 STUN 服务器不可用,可以配置一个新的 STUN 服务器 43 | # natHoleStunServer = "xxx" 44 | 45 | [[visitors]] 46 | name = "p2p_ssh_visitor" 47 | type = "xtcp" 48 | # 要访问的 P2P 代理的名称 49 | serverName = "p2p_ssh" 50 | secretKey = "abcdefg" 51 | # 绑定本地端口以访问 SSH 服务 52 | bindAddr = "127.0.0.1" 53 | bindPort = 6000 54 | # 如果需要自动保持隧道打开,将其设置为 true 55 | # keepTunnelOpen = false 56 | 57 | 58 | 3. **通过 SSH 访问内网机器** 59 | 60 | 使用 SSH 命令访问内网机器,假设用户名为 `test`: 61 | 62 | ``` 63 | ssh -oPort=6000 test@127.0.0.1 64 | ``` 65 | -------------------------------------------------------------------------------- /content/zh-cn/docs/FAQ/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "FAQ" 3 | weight: 7 4 | --- 5 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "功能特性" 3 | weight: 5 4 | description: > 5 | 了解 frp 支持的各种功能特性。 6 | --- 7 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "通用功能" 3 | weight: 1 4 | description: > 5 | 了解 frp 的一些通用功能。 6 | --- 7 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/authentication.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "身份认证" 3 | weight: 30 4 | --- 5 | 6 | 目前 frpc 和 frps 之间支持两种身份验证方式,`token` 和 `oidc`,默认为 `token`。这些认证方式允许您验证客户端与服务端之间的通信,并确保只有授权用户能够建立连接。 7 | 8 | ## Token 9 | 10 | Token 身份认证是一种简单的身份认证方式,只需要在 frp 的客户端 frpc 和服务端 frps 配置文件中配置相同的 token 即可。 11 | 12 | ### 配置示例 13 | 14 | ```toml 15 | # frps.toml 16 | bindPort = 7000 17 | auth.token = "abc" 18 | ``` 19 | 20 | ```toml 21 | # frpc.toml 22 | auth.token = "abc" 23 | ``` 24 | 25 | ## OIDC (OpenID Connect) 身份认证 26 | 27 | OIDC 身份认证是一种基于开放标准的身份认证方式,它通过使用 OIDC 提供者进行身份验证。 28 | 29 | 验证流程参考 [Client Credentials Grant](https://tools.ietf.org/html/rfc6749#section-4.4)。 30 | 31 | ### 配置示例 32 | 33 | ```toml 34 | # frps.toml 35 | auth.method = "oidc" 36 | auth.oidc.issuer = "https://example-oidc-issuer.com/" 37 | auth.oidc.audience = "https://oidc-audience.com/.default" 38 | ``` 39 | 40 | ```toml 41 | # frpc.toml 42 | auth.method = "oidc" 43 | auth.oidc.clientID = "98692467-37de-409a-9fac-bb2585826f18" 44 | auth.oidc.clientSecret = "oidc_secret" 45 | auth.oidc.audience = "https://oidc-audience.com/.default" 46 | auth.oidc.tokenEndpointURL = "https://example-oidc-endpoint.com/oauth2/v2.0/token" 47 | ``` 48 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/client-plugin.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "客户端插件" 3 | weight: 110 4 | --- 5 | 6 | 默认情况下,frpc 仅会将请求转发到本地 TCP 或 UDP 端口,即通过 `localIP` 和 `localPort` 指定的本地服务地址。 7 | 8 | 通过启用客户端插件功能,可以在仅启动 frpc 的情况下内置一些简单的本地服务,从而实现通常需要额外启动其他服务才能实现的功能。 9 | 10 | 在每个代理的配置中,你可以通过 `plugin` 来配置要使用的插件和相关参数。启用客户端插件后,无需再配置 `localIP` 和 `localPort`。 11 | 12 | 客户端插件可用于各种类型的代理,前提是插件本身支持的协议。例如,静态文件访问插件可以通过 TCP 或 HTTP 代理进行暴露。 13 | 14 | 以下是使用 `http_proxy` 插件的示例: 15 | 16 | ```toml 17 | [[proxies]] 18 | name = "http_proxy" 19 | type = "tcp" 20 | remotePort = 6000 21 | [proxies.plugin] 22 | type = "http_proxy" 23 | httpUser = "abc" 24 | httpPassword = "abc" 25 | ``` 26 | 27 | `httpUser` 和 `httpPassword` 即为 `http_proxy` 插件可选的配置参数。 28 | 29 | 其他插件和相关配置请参考 [Reference](../../../reference/) 中的内容。 30 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/client.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "客户端" 3 | weight: 90 4 | --- 5 | 6 | ## 动态配置更新 7 | 8 | 当你需要修改 frpc 的代理配置时,你可以使用 `frpc reload` 命令来实现动态加载配置文件,通常在数秒内完成代理的更新。 9 | 10 | 要启用此功能,需要在 frpc 中启用 webServer,以提供 API 服务。配置如下: 11 | 12 | ```toml 13 | webServer.addr = "127.0.0.1" 14 | webServer.port = 7400 15 | ``` 16 | 17 | 然后执行以下命令来重载配置: 18 | 19 | `frpc reload -c ./frpc.toml` 20 | 21 | 等待一段时间后,客户端将根据新的配置文件创建、更新或删除代理。需要注意的是,非代理相关的公共部分的参数除了 start 外目前无法被修改。 22 | 23 | ## 命令行查看代理状态 24 | 25 | frpc 支持通过 `frpc status -c ./frpc.toml` 命令查看代理的状态信息,此功能需要在 frpc 中启用 webServer。 26 | 27 | ## 使用代理连接 frps 28 | 29 | 在只能通过代理访问外部网络的环境中,frpc 支持通过 HTTP 或 SOCKS5 代理与 frps 建立连接。 30 | 31 | 你可以通过设置系统环境变量 `HTTP_PROXY` 或在 frpc 的配置文件中设置 `transport.proxyURL` 参数来使用此功能。 32 | 33 | 仅在 `transport.protocol = "tcp"` 时生效。 34 | 35 | ```toml 36 | serverAddr = "x.x.x.x" 37 | serverPort = 7000 38 | transport.proxyURL = "http://user:pwd@192.168.1.128:8080" 39 | ``` 40 | 41 | 将 `transport.proxyURL` 设置为 `socks5://user:pwd@192.168.1.128:8080` 也可以连接到 SOCKS5 代理。 42 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/configure.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "配置文件" 3 | weight: 10 4 | --- 5 | 6 | 从 v0.52.0 版本开始,frp 开始支持 TOML、YAML 和 JSON 作为配置文件格式。 7 | 8 | 请注意,INI 已被弃用,并将在未来的发布中移除。新功能只能在TOML、YAML 或 JSON 中使用。希望使用这些新功能的用户应相应地切换其配置格式。 9 | 10 | ## 格式 11 | 12 | 可使用 TOML/YAML/JSON 任何一个您喜欢的格式来编写配置文件,frp 会自动适配进行解析。 13 | 14 | 文档示例主要通过 TOML 编写,如下的示例配置将本地 SSH 服务穿透到公网。 15 | 16 | frps 配置: 17 | 18 | ```toml 19 | bindPort = 7000 20 | ``` 21 | 22 | frpc 配置: 23 | 24 | ```toml 25 | serverAddr = "x.x.x.x" 26 | serverPort = 7000 27 | 28 | [[proxies]] 29 | name = "ssh" 30 | type = "tcp" 31 | localIP = "127.0.0.1" 32 | localPort = 22 33 | remotePort = 6000 34 | ``` 35 | 36 | 同一个客户端可以配置多个代理,但是 name 必须确保唯一。 37 | 38 | 不同的客户端之间,可以通过配置不同的 user 来确保代理名称唯一。 39 | 40 | ## 模版渲染 41 | 42 | 配置文件支持使用环境变量进行模版渲染,模版格式采用 Go 的标准格式。 43 | 44 | 示例配置如下: 45 | 46 | ```toml 47 | serverAddr = "{{ .Envs.FRP_SERVER_ADDR }}" 48 | serverPort = 7000 49 | 50 | [[proxies]] 51 | name = "ssh" 52 | type = "tcp" 53 | localIP = "127.0.0.1" 54 | localPort = 22 55 | remotePort = {{ .Envs.FRP_SSH_REMOTE_PORT }} 56 | ``` 57 | 58 | 启动 frpc 程序: 59 | 60 | ``` 61 | export FRP_SERVER_ADDR="x.x.x.x" 62 | export FRP_SSH_REMOTE_PORT="6000" 63 | ./frpc -c ./frpc.toml 64 | ``` 65 | 66 | frpc 会自动使用环境变量渲染配置文件模版,所有环境变量需要以 `.Envs` 为前缀。 67 | 68 | ## 配置校验 69 | 70 | 通过执行 `frpc verify -c ./frpc.toml` 或 `frps verify -c ./frps.toml` 可以对配置文件中的参数进行预先校验。 71 | 72 | ``` 73 | frpc: the configuration file ./frpc.toml syntax is ok 74 | ``` 75 | 76 | 如果出现此结果,则说明新的配置文件没有错误,否则会输出具体的错误信息。 77 | 78 | ## 配置拆分 79 | 80 | 通过 `includes` 参数可以在主配置中包含其他配置文件,从而实现将代理配置拆分到多个文件中管理。 81 | 82 | ```toml 83 | # frpc.toml 84 | serverAddr = "x.x.x.x" 85 | serverPort = 7000 86 | includes = ["./confd/*.toml"] 87 | ``` 88 | 89 | ```toml 90 | # ./confd/test.toml 91 | [[proxies]] 92 | name = "ssh" 93 | type = "tcp" 94 | localIP = "127.0.0.1" 95 | localPort = 22 96 | remotePort = 6000 97 | ``` 98 | 99 | 上述配置在 frpc.toml 中通过 includes 额外包含了 `./confd` 目录下所有的 toml 文件的代理配置内容,效果等价于将这两个文件合并成一个文件。 100 | 101 | 需要注意的是 includes 指定的文件中只能包含代理配置,通用参数的配置只能放在主配置文件中。 102 | 103 | ## 完整配置参数 104 | 105 | 由于 frp 目前支持的功能和配置项较多,未在文档中列出的功能参数可以在 [参考](../../../reference) 中查看。 106 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/load-balancer.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "负载均衡与健康检查" 3 | weight: 60 4 | --- 5 | 6 | ## 负载均衡 7 | 8 | 你可以将多个相同类型的代理加入到同一个 `group` 中,以实现负载均衡的能力。 9 | 10 | 目前支持的代理类型包括:`tcp`, `http`, `tcpmux`。 11 | 12 | ```toml 13 | # frpc.toml 14 | [[proxies]] 15 | name = "test1" 16 | type = "tcp" 17 | localPort = 8080 18 | remotePort = 80 19 | loadBalancer.group = "web" 20 | loadBalancer.groupKey = "123" 21 | 22 | [[proxies]] 23 | name = "test2" 24 | type = "tcp" 25 | localPort = 8081 26 | remotePort = 80 27 | loadBalancer.group = "web" 28 | loadBalancer.groupKey = "123" 29 | ``` 30 | 31 | 当用户连接 frps 服务器的 80 端口时,frps 会将接收到的用户连接随机分发给其中一个存活的代理。这可以确保即使一台 frpc 机器挂掉,仍然有其他节点能够提供服务。 32 | 33 | 对于 tcp 类型代理,需要确保 `groupKey` 相同以进行权限验证,同时 `remotePort` 也需一致。 34 | 35 | 对于 http 类型代理,需要保证 `groupKey`, `customDomains`(自定义域名),`subdomain` 和 `locations` 相同。 36 | 37 | ## 健康检查 38 | 39 | 通过给代理配置健康检查参数,可以在要反向代理的服务出现故障时,将该服务从 frps 中摘除。结合负载均衡的功能,这可用于实现高可用架构,避免服务单点故障。 40 | 41 | 要启用健康检查功能,需要在每个代理的配置中添加 `healthCheck.type = {type}`。 42 | 43 | 目前支持的类型有 `tcp` 和 `http`。 44 | 45 | * 对于 `tcp`,只要能够建立连接,即认为服务正常。 46 | * 对于 `http`,会发送一个 HTTP 请求,服务需要返回状态码 2xx 才会被视为正常。 47 | 48 | 以下是 `tcp` 示例配置: 49 | 50 | ```toml 51 | [[proxies]] 52 | name = "test1" 53 | type = "tcp" 54 | localPort = 22 55 | remotePort = 6000 56 | # 启用健康检查,类型为 tcp 57 | healthCheck.type = "tcp" 58 | # 建立连接超时时间为 3 秒 59 | healthCheck.timeoutSeconds = 3 60 | # 连续 3 次检查失败,此 proxy 会被摘除 61 | healthCheck.maxFailed = 3 62 | # 每隔 10 秒进行一次健康检查 63 | healthCheck.intervalSeconds = 10 64 | ``` 65 | 66 | 以下是 http 示例配置: 67 | 68 | ```toml 69 | [[proxies]] 70 | name = "web" 71 | type = "http" 72 | localIP = "127.0.0.1" 73 | localPort = 80 74 | customDomains = ["test.yourdomain.com"] 75 | # 启用健康检查,类型为 http 76 | healthCheck.type = "http" 77 | # 健康检查发送 http 请求的 path,后端服务需要返回 2xx 的 http 状态码 78 | healthCheck.path = "/status" 79 | healthCheck.timeoutSeconds = 3 80 | healthCheck.maxFailed = 3 81 | healthCheck.intervalSeconds = 10 82 | ``` 83 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/monitor.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "监控" 3 | weight: 20 4 | --- 5 | 6 | 目前,frps 服务端支持两种监控系统:内存监控和 Prometheus 监控。 7 | 8 | ## 内存监控 9 | 10 | 内存中存储的监控数据主要用于 Dashboard 展示。当在 frps 配置中开启 Dashboard 功能后,内存监控默认启用。 11 | 12 | 请注意,内存中的监控数据在每次重启进程后会被清空,或者保留 7 天。监控数据可以通过 Dashboard 的地址发送 HTTP 请求获取,但目前此 API 尚不规范,不建议直接使用。 13 | 14 | ## Prometheus 监控 15 | 16 | 由于设计问题,Prometheus 对外提供的查询接口与 Dashboard 的地址重用,因此要使用 Prometheus 监控,必须首先启用 Dashboard。 17 | 18 | 在 frps.ini 中启用 Dashboard 并设置 `enablePrometheus = true`,然后你可以通过访问 `http://{dashboard_addr}/metrics` 来获取 Prometheus 的监控数据。 19 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/network/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "通信安全及优化" 3 | weight: 50 4 | description: > 5 | 提供丰富的通信协议和安全性。 6 | --- 7 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/network/network-tls.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "自定义 TLS 协议加密" 3 | weight: 2 4 | --- 5 | 6 | `transport.useEncryption` 和 `STCP` 等功能能有效防止流量内容在通信过程中被盗取,但是无法判断对方的身份是否合法,存在被中间人攻击的风险。为此 frp 支持 frpc 和 frps 之间的流量通过 TLS 协议加密,并且支持客户端或服务端单向验证,双向验证等功能。 7 | 8 | 当 `frps.toml` 中 `transport.tls.force = true` 时,表示 server 端只接受 TLS 连接的客户端,这也是 frps 验证 frpc 身份的前提条件。如果 `frps.toml` 中 `transport.tls.trustedCaFile` 内容是有效的话,那么默认就会开启 `transport.tls.force = true`。 9 | 10 | **注意:启用此功能后除 xtcp ,可以不用再设置 use_encryption 重复加密** 11 | 12 | ## TLS 默认开启方式 13 | 14 | 从 v0.50.0 开始,`transport.tls.enable` 的默认值将会为 true,默认开启 TLS 协议加密。 15 | 16 | 如果 frps 端没有配置证书,则会使用随机生成的证书来加密流量。 17 | 18 | 默认情况下,frpc 开启 TLS 加密功能,但是不校验 frps 的证书。 19 | 20 | ## frpc 单向校验 frps 身份 21 | 22 | ```toml 23 | # frpc.toml 24 | transport.tls.trustedCaFile = "/to/ca/path/ca.crt" 25 | 26 | # frps.toml 27 | transport.tls.certFile = "/to/cert/path/server.crt" 28 | transport.tls.keyFile = "/to/key/path/server.key" 29 | ``` 30 | 31 | frpc 需要额外加载 ca 证书,frps 需要额外指定 TLS 配置。frpc 通过 ca 证书单向验证 frps 的身份。这就要求 frps 的 `server.crt` 对 frpc 的 ca 是合法的。 32 | 33 | 合法: 如果证书是 ca 签发的,或者证书是在 ca 的信任链中,那即认为: 该证书对 ca 而言是合法的。 34 | 35 | ## frps 单向验证 frpc 的身份 36 | 37 | ```toml 38 | # frpc.toml 39 | transport.tls.certFile = "/to/cert/path/client.crt" 40 | transport.tls.keyFile = "/to/key/path/client.key" 41 | 42 | # frps.toml 43 | transport.tls.trustedCaFile = "/to/ca/path/ca.crt" 44 | ``` 45 | 46 | frpc 需要额外加载 TLS 配置,frps 需要额外加载 ca 证书。frps 通过 ca 证书单向验证 frpc 的身份。这就要求 frpc 的 `client.crt` 对 frps 的 ca 是合法的。 47 | 48 | ## 双向验证 49 | 50 | ```toml 51 | # frpc.toml 52 | transport.tls.certFile = "/to/cert/path/client.crt" 53 | transport.tls.keyFile = "/to/key/path/client.key" 54 | transport.tls.trustedCaFile = "/to/ca/path/ca.crt" 55 | 56 | # frps.toml 57 | transport.tls.certFile = "/to/cert/path/server.crt" 58 | transport.tls.keyFile = "/to/key/path/server.key" 59 | transport.tls.trustedCaFile = "/to/ca/path/ca.crt" 60 | ``` 61 | 62 | 双向验证即 frpc 和 frps 通过本地 ca 证书去验证对方的身份。理论上 frpc 和 frps 的 ca 证书可以不同,只要能验证对方身份即可。 63 | 64 | ## OpenSSL 生成证书示例 65 | 66 | `x509: certificate relies on legacy Common Name field, use SANs or temporarily 67 | enable Common Name matching with GODEBUG=x509ignoreCN=0` 68 | 69 | 如果出现上述报错,是因为 go 1.15 版本开始[废弃 CommonName](https://golang.org/doc/go1.15#commonname),因此推荐使用 SAN 证书。 70 | 71 | 下面简单示例如何用 openssl 生成 ca 和双方 SAN 证书。 72 | 73 | 准备默认 OpenSSL 配置文件于当前目录。此配置文件在 linux 系统下通常位于 `/etc/pki/tls/openssl.cnf`,在 mac 系统下通常位于 `/System/Library/OpenSSL/openssl.cnf`。 74 | 75 | 如果存在,则直接拷贝到当前目录,例如 `cp /etc/pki/tls/openssl.cnf ./my-openssl.cnf`。如果不存在可以使用下面的命令来创建。 76 | 77 | ``` 78 | cat > my-openssl.cnf << EOF 79 | [ ca ] 80 | default_ca = CA_default 81 | [ CA_default ] 82 | x509_extensions = usr_cert 83 | [ req ] 84 | default_bits = 2048 85 | default_md = sha256 86 | default_keyfile = privkey.pem 87 | distinguished_name = req_distinguished_name 88 | attributes = req_attributes 89 | x509_extensions = v3_ca 90 | string_mask = utf8only 91 | [ req_distinguished_name ] 92 | [ req_attributes ] 93 | [ usr_cert ] 94 | basicConstraints = CA:FALSE 95 | nsComment = "OpenSSL Generated Certificate" 96 | subjectKeyIdentifier = hash 97 | authorityKeyIdentifier = keyid,issuer 98 | [ v3_ca ] 99 | subjectKeyIdentifier = hash 100 | authorityKeyIdentifier = keyid:always,issuer 101 | basicConstraints = CA:true 102 | EOF 103 | ``` 104 | 105 | 生成默认 ca: 106 | ``` 107 | openssl genrsa -out ca.key 2048 108 | openssl req -x509 -new -nodes -key ca.key -subj "/CN=example.ca.com" -days 5000 -out ca.crt 109 | ``` 110 | 111 | 生成 frps 证书: 112 | ``` 113 | openssl genrsa -out server.key 2048 114 | 115 | openssl req -new -sha256 -key server.key \ 116 | -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=server.com" \ 117 | -reqexts SAN \ 118 | -config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com")) \ 119 | -out server.csr 120 | 121 | openssl x509 -req -days 365 -sha256 \ 122 | -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ 123 | -extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com") \ 124 | -out server.crt 125 | ``` 126 | 127 | 生成 frpc 的证书: 128 | ``` 129 | openssl genrsa -out client.key 2048 130 | openssl req -new -sha256 -key client.key \ 131 | -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=client.com" \ 132 | -reqexts SAN \ 133 | -config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,DNS:example.client.com")) \ 134 | -out client.csr 135 | 136 | openssl x509 -req -days 365 -sha256 \ 137 | -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ 138 | -extfile <(printf "subjectAltName=DNS:client.com,DNS:example.client.com") \ 139 | -out client.crt 140 | ``` 141 | 142 | 在本例中,server.crt 和 client.crt 都是由默认 ca 签发的,因此他们对默认 ca 是合法的。 143 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/network/network.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "通信安全及优化" 3 | weight: 1 4 | --- 5 | 6 | ## 加密与压缩 7 | 8 | **注: 当 frpc 和 frps 之间启用了 TLS 之后,流量会被全局加密,不再需要配置单个代理上的加密,新版本中已经默认启用。** 9 | 10 | 每一个代理都可以选择是否启用加密和压缩的功能。 11 | 12 | 加密算法采用 aes-128-cfb,压缩算法采用 snappy。 13 | 14 | 在每一个代理的配置中使用如下参数指定: 15 | 16 | ```toml 17 | [[proxies]] 18 | name = "ssh" 19 | type = "tcp" 20 | localPort = 22 21 | remotePort = 6000 22 | transport.useEncryption = true 23 | transport.useCompression = true 24 | ``` 25 | 26 | 通过设置 `transport.useEncryption = true`,将 frpc 与 frps 之间的通信内容加密传输,将会有效防止传输内容被截取。 27 | 28 | 如果传输的报文长度较长,通过设置 `transport.useCompression = true` 对传输内容进行压缩,可以有效减小 frpc 与 frps 之间的网络流量,加快流量转发速度,但是会额外消耗一些 CPU 资源。 29 | 30 | ## TCP 多路复用 31 | 32 | 客户端和服务器端之间的连接支持多路复用,不再需要为每一个用户请求创建一个连接,使连接建立的延迟降低,并且避免了大量文件描述符的占用,使 frp 可以承载更高的并发数。 33 | 34 | 该功能默认启用,如需关闭,可以在 frps.toml 和 frpc.toml 中配置,该配置项在服务端和客户端必须一致: 35 | 36 | ```toml 37 | # frps.toml 和 frpc.toml 中 38 | transport.tcpMux = false 39 | ``` 40 | 41 | ## 连接池 42 | 43 | 默认情况下,当用户请求建立连接后,frps 才会请求 frpc 主动与后端服务建立一个连接。当为指定的代理启用连接池后,frp 会预先和后端服务建立起指定数量的连接,每次接收到用户请求后,会从连接池中取出一个连接和用户连接关联起来,避免了等待与后端服务建立连接以及 frpc 和 frps 之间传递控制信息的时间。 44 | 45 | 这一功能适合有大量短连接请求时开启。 46 | 47 | **注: 当 TCP 多路复用启用后,连接池的提升有限,一般场景下无需关心。** 48 | 49 | 1. 首先可以在 frps.toml 中设置每个代理可以创建的连接池上限,避免大量资源占用,客户端设置超过此配置后会被调整到当前值: 50 | 51 | ```toml 52 | # frps.toml 53 | transport.maxPoolCount = 5 54 | ``` 55 | 56 | 2. 在 frpc.toml 中为客户端启用连接池,指定预创建连接的数量: 57 | 58 | ```toml 59 | # frpc.toml 60 | transport.poolCount = 1 61 | ``` 62 | 63 | ## 支持 KCP 协议 64 | 65 | 底层通信协议支持选择 KCP 协议,相比于 TCP,在弱网环境下传输效率提升明显,但是会有一些额外的流量消耗。 66 | 67 | 开启 KCP 协议支持: 68 | 69 | 1. 在 frps.toml 中启用 KCP 协议支持,指定一个 UDP 端口用于接收客户端请求: 70 | 71 | ```toml 72 | # frps.toml 73 | bindPort = 7000 74 | # kcp 绑定的是 UDP 端口,可以和 bindPort 一样 75 | kcpBindPort = 7000 76 | ``` 77 | 78 | 2. 在 frpc.toml 指定需要使用的协议类型,其他代理配置不需要变更: 79 | 80 | ```toml 81 | # frpc.toml 82 | serverAddr = "x.x.x.x" 83 | # serverPort 指定为 frps 的 kcpBindPort 84 | serverPort = 7000 85 | transport.protocol = "kcp" 86 | ``` 87 | 88 | ## 支持 QUIC 协议 89 | 90 | 底层通信协议支持选择 QUIC 协议,底层采用 UDP 传输,解决了 TCP 上的一些问题,传输效率更高,连接延迟低。 91 | 92 | 开启 QUIC 协议支持: 93 | 94 | 1. 在 frps.toml 中启用 QUIC 协议支持,指定一个 UDP 端口用于接收客户端请求: 95 | 96 | ```toml 97 | # frps.toml 98 | bindPort = 7000 99 | # QUIC 绑定的是 UDP 端口,可以和 bindPort 一样 100 | quicBindPort = 7000 101 | ``` 102 | 103 | 2. 在 frpc.toml 指定需要使用的协议类型,其他代理配置不需要变更: 104 | 105 | ```toml 106 | # frpc.toml 107 | serverAddr = "x.x.x.x" 108 | # serverPort 指定为 frps 的 quicBindPort 109 | serverPort = 7000 110 | transport.protocol = "quic" 111 | ``` 112 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/range.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "端口范围映射" 3 | weight: 80 4 | --- 5 | 6 | *Added in v0.56.0* 7 | 8 | 我们可以利用 Go template 的 range 语法结合内置的 `parseNumberRangePair` 函数来实现端口范围映射。 9 | 10 | 下面的示例,应用运行后会创建 8 个代理,名称为 `test-6000, test-6001 ... test-6007`,分别将远端的端口映射到本地。 11 | 12 | ``` 13 | {{- range $_, $v := parseNumberRangePair "6000-6006,6007" "6000-6006,6007" }} 14 | [[proxies]] 15 | name = "tcp-{{ $v.First }}" 16 | type = "tcp" 17 | localPort = {{ $v.First }} 18 | remotePort = {{ $v.Second }} 19 | {{- end }} 20 | ``` 21 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/realip.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "获取用户真实 IP" 3 | weight: 70 4 | --- 5 | 6 | ## HTTP X-Forwarded-For 7 | 8 | 目前只有 `http` 类型的代理或者启用了 `https2http` 或 `https2https` 插件的代理支持这一功能。 9 | 10 | 可以通过 HTTP/HTTPS 请求 header 中的 `X-Forwarded-For` 来获取用户真实 IP,默认启用。 11 | 12 | ## Proxy Protocol 13 | 14 | frp 支持通过 `Proxy Protocol` 协议来传递经过 frp 代理的请求的真实 IP。 15 | 16 | `Proxy Protocol` 功能启用后,frpc 在和本地服务建立连接后,会先发送一段 `Proxy Protocol` 的协议内容给本地服务,本地服务通过解析这一内容可以获得访问用户的真实 IP。所以不仅仅是 HTTP 服务,任何的 TCP 服务,只要支持这一协议,都可以获得用户的真实 IP 地址。 17 | 18 | 需要注意的是,在代理配置中如果要启用此功能,需要本地的服务能够支持 `Proxy Protocol` 这一协议,目前 nginx 和 haproxy 都能够很好的支持。 19 | 20 | 这里以 `HTTPS` 类型为例: 21 | 22 | ```toml 23 | # frpc.toml 24 | [[proxies]] 25 | name = "web" 26 | type = "https" 27 | localPort = 443 28 | customDomains = ["test.yourdomain.com"] 29 | 30 | # 目前支持 v1 和 v2 两个版本的 proxy protocol 协议。 31 | transport.proxyProtocolVersion = "v2" 32 | ``` 33 | 34 | 只需要在代理配置中增加一行 `transport.proxyProtocolVersion = "v2"` 即可开启此功能。 35 | 36 | 本地的 HTTPS 服务可以通过在 nginx 的配置中启用 `Proxy Protocol` 的解析并将结果设置在 `X-Real-IP` 这个 Header 中就可以在自己的 Web 服务中通过 `X-Real-IP` 获取到用户的真实 IP。 37 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/server-manage.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "服务端管理" 3 | weight: 100 4 | --- 5 | 6 | ## 端口白名单 7 | 8 | 为了防止端口被滥用,可以手动指定允许哪些端口被使用,在服务端配置中通过 `allowPorts` 来指定: 9 | 10 | ```toml 11 | # frps.ini 12 | allowPorts = [ 13 | { start = 2000, end = 3000 }, 14 | { single = 3001 }, 15 | { single = 3003 }, 16 | { start = 4000, end = 50000 } 17 | ] 18 | ``` 19 | 20 | `allowPorts` 可以配置允许使用的某个指定端口或者是一个范围内的所有端口。 21 | 22 | ## 端口复用 23 | 24 | 目前 frps 中的 `vhostHTTPPort` 和 `vhostHTTPSPort` 支持配置成和 `bindPort` 为同一个端口,frps 会对连接的协议进行分析,之后进行不同的处理。 25 | 26 | 例如在某些限制较严格的网络环境中,可以将 `bindPort` 和 `vhostHTTPSPort` 都设置为 443。 27 | 28 | 需要注意的是,如果你想将 `vhostHTTPSPort` 和 `bindPort` 配置为相同的端口,需要首先将 `transport.tls.disableCustomTLSFirstByte` 设置为false。 29 | 30 | ## 限速 31 | 32 | ### 代理限速 33 | 34 | 目前支持在客户端的代理配置中设置代理级别的限速,限制单个 proxy 可以占用的带宽。 35 | 36 | ```toml 37 | # frpc.toml 38 | [[proxies]] 39 | name = "ssh" 40 | type = "tcp" 41 | localPort = 22 42 | remotePort = 6000 43 | transport.bandwidthLimit = "1MB" 44 | ``` 45 | 46 | 在代理配置中增加 `transport.bandwidthLimit` 字段启用此功能,目前仅支持 `MB` 和 `KB` 单位。 47 | 48 | 限速能力默认在客户端实现,如果希望启用服务端限速,需要额外配置 `transport.bandwidthLimitMode = "server"`。 49 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/server-plugin.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "服务端插件" 3 | weight: 120 4 | --- 5 | 6 | frp 服务端插件的作用是在不侵入自身代码的前提下,扩展 frp 服务端的能力。 7 | 8 | frp 服务端插件会以单独进程的形式运行,并且监听在一个端口上,对外提供 RPC 接口,响应 frps 的请求。 9 | 10 | frps 在执行某些操作前,会根据配置向服务端插件发送 RPC 请求,根据插件的响应来执行相应的操作。 11 | 12 | ## RPC 请求 13 | 14 | 服务端插件接收到操作请求后,可以给出三种回应。 15 | 16 | * 拒绝操作,需要返回拒绝操作的原因。 17 | * 允许操作,不需要修改操作内容。 18 | * 允许操作,对操作请求进行修改后,返回修改后的内容。 19 | 20 | ## 接口 21 | 22 | 接口路径可以在 frps 配置中为每个插件单独配置,这里以 `/handler` 为例。 23 | 24 | Request 25 | 26 | ``` 27 | POST /handler?version=0.1.0&op=Login 28 | { 29 | "content": { 30 | ... // 具体的操作信息 31 | } 32 | } 33 | 34 | 请求 Header 35 | X-Frp-Reqid: 用于追踪请求 36 | ``` 37 | 38 | Response 39 | 40 | 非 200 的返回都认为是请求异常。 41 | 42 | 拒绝执行操作 43 | 44 | ``` 45 | { 46 | "reject": true, 47 | "reject_reason": "invalid user" 48 | } 49 | ``` 50 | 51 | 允许且内容不需要变动 52 | 53 | ``` 54 | { 55 | "reject": false, 56 | "unchange": true 57 | } 58 | ``` 59 | 60 | 允许且需要替换操作内容 61 | 62 | ``` 63 | { 64 | "unchange": false, 65 | "content": { 66 | ... // 替换后的操作信息,格式必须和请求时的一致 67 | } 68 | } 69 | ``` 70 | 71 | ## 操作类型 72 | 73 | 目前插件支持管理的操作类型有 `Login`、`NewProxy`、`CloseProxy`、`Ping`、`NewWorkConn` 和 `NewUserConn`。 74 | 75 | ### Login 76 | 77 | 用户登录操作信息 78 | 79 | ``` 80 | { 81 | "content": { 82 | "version": , 83 | "hostname": , 84 | "os": , 85 | "arch": , 86 | "user": , 87 | "timestamp": , 88 | "privilege_key": , 89 | "run_id": , 90 | "pool_count": , 91 | "metas": mapstring, 92 | "client_address": 93 | } 94 | } 95 | ``` 96 | 97 | ### NewProxy 98 | 99 | 创建代理的相关信息 100 | 101 | ``` 102 | { 103 | "content": { 104 | "user": { 105 | "user": , 106 | "metas": mapstring 107 | "run_id": 108 | }, 109 | "proxy_name": , 110 | "proxy_type": , 111 | "use_encryption": , 112 | "use_compression": , 113 | "bandwidth_limit": , 114 | "bandwidth_limit_mode": , 115 | "group": , 116 | "group_key": , 117 | 118 | // tcp and udp only 119 | "remote_port": , 120 | 121 | // http and https only 122 | "custom_domains": [], 123 | "subdomain": , 124 | "locations": [], 125 | "http_user": , 126 | "http_pwd": , 127 | "host_header_rewrite": , 128 | "headers": mapstring, 129 | 130 | // stcp only 131 | "sk": , 132 | 133 | // tcpmux only 134 | "multiplexer": 135 | 136 | "metas": mapstring 137 | } 138 | } 139 | ``` 140 | 141 | ### CloseProxy 142 | 143 | 代理关闭。(仅用于通知) 144 | 145 | 注意: 当单个 frpc 会注册大量 proxy 时,慎重使用此接口,可能会由于连接数超限而影响服务的可用性。 146 | 147 | ``` 148 | { 149 | "content": { 150 | "user": { 151 | "user": , 152 | "metas": mapstring 153 | "run_id": 154 | }, 155 | "proxy_name": 156 | } 157 | } 158 | ``` 159 | 160 | ### Ping 161 | 162 | 心跳相关信息 163 | 164 | ``` 165 | { 166 | "content": { 167 | "user": { 168 | "user": , 169 | "metas": mapstring 170 | "run_id": 171 | }, 172 | "timestamp": , 173 | "privilege_key": 174 | } 175 | } 176 | ``` 177 | 178 | ### NewWorkConn 179 | 180 | 创建工作连接 181 | 182 | ``` 183 | { 184 | "content": { 185 | "user": { 186 | "user": , 187 | "metas": mapstring 188 | "run_id": 189 | }, 190 | "run_id": 191 | "timestamp": , 192 | "privilege_key": 193 | } 194 | } 195 | ``` 196 | 197 | ### NewUserConn 198 | 199 | 创建用户连接 (支持 `tcp`、`stcp`、`https` 和 `tcpmux` 协议)。 200 | 201 | ``` 202 | { 203 | "content": { 204 | "user": { 205 | "user": , 206 | "metas": mapstring 207 | "run_id": 208 | }, 209 | "proxy_name": , 210 | "proxy_type": , 211 | "remote_addr": 212 | } 213 | } 214 | ``` 215 | 216 | 217 | ## frps 中插件配置 218 | 219 | ```toml 220 | bindPort = 7000 221 | 222 | [[httpPlugins]] 223 | name = "user-manager" 224 | addr = "127.0.0.1:9000" 225 | path = "/handler" 226 | ops = ["Login"] 227 | 228 | [[httpPlugins]] 229 | name = "port-manager" 230 | addr = "127.0.0.1:9001" 231 | path = "/handler" 232 | ops = ["NewProxy"] 233 | ``` 234 | 235 | * addr: 插件监听的网络地址,支持 HTTP 和 HTTPS,默认为 HTTP。 236 | * path: 插件监听的请求路径。 237 | * ops: 插件需要处理的操作列表,多个 op 以英文逗号分隔。 238 | * tls_verify: 如果是 HTTPS 协议,支持忽略 TLS 身份验证。 239 | 240 | ## 元数据 241 | 242 | 为了减少 frps 的代码修改,同时提高管理插件的扩展能力,在 frpc 的配置文件中引入自定义元数据的概念。元数据会在调用 RPC 请求时发送给插件。 243 | 244 | 有两种类型的元数据条目,全局条目和每个代理配置下的条目。全局元数据将在客户端登录时附加在 Login 请求中,并在其他 RPC 请求中附加在 `user.metas` 中。 245 | 246 | 每个代理配置下的元数据条目仅会在 NewProxy 操作中通过 metas 传递。 247 | 248 | ``` 249 | # frpc.toml 250 | serverAddr = "127.0.0.1" 251 | serverPort = 7000 252 | user = "fake" 253 | metadatas.token = "fake" 254 | metadatas.version = "1.0.0" 255 | 256 | [[proxies]] 257 | name = "ssh" 258 | type = "tcp" 259 | localPort = 22 260 | remotePort = 6000 261 | metadatas.id = "123" 262 | ``` 263 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/ssh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SSH Tunnel Gateway" 3 | weight: 130 4 | --- 5 | 6 | *Added in v0.53.0* 7 | 8 | ## 概念 9 | 10 | SSH 支持反向代理能力 [rfc](https://www.rfc-editor.org/rfc/rfc4254#page-16)。 11 | 12 | frp 支持在 frps 端监听一个 ssh 端口,通过走 ssh -R 协议来完成 TCP 协议代理,该模式下不需要依赖 frpc。 13 | 14 | SSH 反向隧道代理和通过 frp 代理 SSH 端口是不同的 2 个概念。SSH 反向隧道代理本质上是在你不想使用 frpc 的时候,通过 ssh client 连接 frps 来完成基本的反向代理。 15 | 16 | ## 参数 17 | 18 | ```toml 19 | # frps.toml 20 | 21 | sshTunnelGateway.bindPort = 0 22 | sshTunnelGateway.privateKeyFile = "" 23 | sshTunnelGateway.autoGenPrivateKeyPath = "" 24 | sshTunnelGateway.authorizedKeysFile = "" 25 | ``` 26 | 27 | | Field | Type | Description | Required | 28 | | :--- | :--- | :--- | :--- | 29 | | bindPort| int | frps 监听的 ssh server 端口。| YES | 30 | | privateKeyFile | string | 默认为空。ssh server 使用的私钥文件,为空frps会读取 autoGenPrivateKeyPath 路径下的私钥文件。可复用本地 /home/user/.ssh/id_rsa 文件或自定义路径。| No | 31 | | autoGenPrivateKeyPath | string |默认为 ./.autogen_ssh_key。文件不存在或内容为空,frps会自动生成 RSA 私钥文件内容存入该文件。|No| 32 | | authorizedKeysFile | string |默认为空。空不对ssh客户端进行鉴权认证。不空可实现ssh免密登录认证,可复用本地 /home/user/.ssh/authorized_keys 文件或自定义路径。| No | 33 | 34 | ## 基本使用 35 | 36 | ### 服务端 frps 37 | 38 | 最简配置 39 | 40 | ```toml 41 | sshTunnelGateway.bindPort = 2200 42 | ``` 43 | 44 | 将上述配置放入 frps.toml, 运行 `./frps -c frps.toml`,此时会在 2200 的端口监听,接受 ssh 反向代理的请求。 45 | 46 | 注意: 47 | 1. 使用最简配置,会在当前运行目录自动创建一个 `.autogen_ssh_key` 的私钥文件,frps 的 ssh server 会使用到该私钥文件,用来加解密数据。也可以复用本地已有的私钥文件,如 `/home/user/.ssh/id_rsa`。 48 | 2. 最简配置模式下运行的frps,通过 ssh 连接 frps 是不鉴权的,强烈建议 frps 配置 token,在 ssh 命令行指定 token。 49 | 50 | ### 客户端 ssh 51 | 52 | 命令格式为 53 | 54 | ```bash 55 | ssh -R :80:{local_ip:port} v0@{frps address} -p {frps ssh listen port} {tcp|http|https|stcp|tcpmux} --remote_port {real remote port} --proxy_name {proxy_name} --token {frp token} 56 | 57 | ``` 58 | 59 | 1. `--proxy_name` 非必填,为空会随机生成一个。 60 | 2. 登录 frps 的用户名统一为 v0,目前没有任何含义,即 `v0@{frps address}`。 61 | 3. server 端的 proxy 监听的端口由 `--remote_port` 决定。 62 | 4. `{tcp|http|https|stcp|tcpmux}` 支持的完整命令参数可通过 --help 获取。 如: `ssh -R :80::8080 v0@127.0.0.1 -p 2200 http --help` 63 | 5. token 非必填,为了安全强烈建议在frps配置上token。 64 | 65 | #### TCP 代理 66 | 67 | ```bash 68 | ssh -R :80:127.0.0.1:8080 v0@{frp address} -p 2200 tcp --proxy_name "test-tcp" --remote_port 9090 69 | ``` 70 | 71 | 在 frps 启动一个 9090 的端口代理本地的 8080 服务。 72 | 73 | ```bash 74 | frp (via SSH) (Ctrl+C to quit) 75 | 76 | User: 77 | ProxyName: test-tcp 78 | Type: tcp 79 | RemoteAddress: :9090 80 | ``` 81 | 82 | 等同于: 83 | 84 | ```bash 85 | frpc tcp --proxy_name "test-tcp" --local_ip 127.0.0.1 --local_port 8080 --remote_port 9090 86 | ``` 87 | 88 | 更多参数可执行 --help 获取。 89 | 90 | #### HTTP 代理 91 | 92 | ```bash 93 | ssh -R :80:127.0.0.1:8080 v0@{frp address} -p 2200 http --proxy_name "test-http" --custom_domain test-http.frps.com 94 | ``` 95 | 96 | 等同于 97 | 98 | ```bash 99 | frpc http --proxy_name "test-http" --custom_domain test-http.frps.com 100 | ``` 101 | 102 | 可以通过以下命令访问 http 服务: 103 | 104 | `curl 'http://test-http.frps.com'` 105 | 106 | 更多参数可执行 `--help` 获取。 107 | 108 | #### HTTPS/STCP/TCPMUX 代理 109 | 110 | 通过如下命令获取使用方式: 111 | 112 | `ssh -R :80:127.0.0.1:8080 v0@{frp address} -p 2200 {https|stcp|tcpmux} --help` 113 | 114 | ## 高级使用 115 | 116 | ### 复用本机的 id_rsa 文件 117 | 118 | ```toml 119 | # frps.toml 120 | 121 | sshTunnelGateway.bindPort = 2200 122 | sshTunnelGateway.privateKeyFile = "/home/user/.ssh/id_rsa" 123 | ``` 124 | 125 | ssh 协议握手阶段需要交换公钥用来加密数据,所以 frps 端的 ssh server 需要指定一个私钥文件,可以复用本机已存在的;如果为空,frps会自动创建一个 rsa 私钥文件。 126 | 127 | ### 指定自动生成私钥文件地址 128 | 129 | ```toml 130 | # frps.toml 131 | 132 | sshTunnelGateway.bindPort = 2200 133 | sshTunnelGateway.autoGenPrivateKeyPath = "/var/frp/ssh-private-key-file" 134 | ``` 135 | 136 | frps自动创建私钥文件并指定路径存储。 137 | 138 | 注意:frps 更换私钥文件,会导致 ssh 客户端登录失败,如果需要成功登录,可以删除 `/home/user/.ssh/known_hosts` 文件中的旧的记录。 139 | 140 | 141 | ### 使用本机已存在的 authorized_keys 文件,实现 ssh 免密登录鉴权 142 | 143 | ```toml 144 | # frps.toml 145 | 146 | sshTunnelGateway.bindPort = 2200 147 | sshTunnelGateway.authorizedKeysFile = "/home/user/.ssh/authorized_keys" 148 | ``` 149 | 150 | authorizedKeysFile 是 ssh 免密登录使用的文件,存放用户公钥信息,一行一个。 151 | 152 | authorizedKeysFile 为空, frps 不对 ssh 客户端进行任何认证。frps 不支持 ssh 用户名+密码模式认证。 153 | 154 | 可复用本机已有的 `authorized_keys` 文件对客户端进行认证。 155 | 156 | 注意:authorizedKeysFile 是 ssh 登录阶段的用户认证,token 是 frps 已有的认证,2 者没有关联,ssh 认证在前,frps 认证 token 在后,强烈建议至少开启1个,如果 authorizedKeysFile 为空,强烈建议 frps 端开启 token 认证,否则有安全风险。 157 | 158 | ### 使用自定义的 authorized_keys 文件,实现 ssh 免密登录鉴权 159 | 160 | ```toml 161 | # frps.toml 162 | 163 | sshTunnelGateway.bindPort = 2200 164 | sshTunnelGateway.authorizedKeysFile = "/var/frps/custom_authorized_keys_file" 165 | ``` 166 | 167 | 自定义 `authorized_keys` 文件路径。 168 | 169 | authorizedKeysFile 文件变动可能会导致 ssh 登录认证失败,可能需要重新将公钥信息放入 authorizedKeysFile。 170 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/ui.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Web 界面" 3 | weight: 40 4 | --- 5 | 6 | 目前 frpc 和 frps 分别内置了相应的 Web 界面方便用户使用。 7 | 8 | ## 服务端 Dashboard 9 | 10 | 服务端 Dashboard 使用户可以通过浏览器查看 frp 的状态以及代理统计信息。 11 | 12 | **注:Dashboard 尚未针对大量的 proxy 数据展示做优化,如果出现 Dashboard 访问较慢的情况,请不要启用此功能。** 13 | 14 | 需要在 frps.toml 中指定 dashboard 服务使用的端口,即可开启此功能: 15 | 16 | ```toml 17 | # 默认为 127.0.0.1,如果需要公网访问,需要修改为 0.0.0.0。 18 | webServer.addr = "0.0.0.0" 19 | webServer.port = 7500 20 | # dashboard 用户名密码,可选,默认为空 21 | webServer.user = "admin" 22 | webServer.password = "admin" 23 | ``` 24 | 25 | 打开浏览器通过 `http://[server addr]:7500` 访问 Dashboard 界面,输入用户名密码 `admin`。 26 | 27 | 你也可以通过配置 TLS 证书来启用 HTTPS 接口: 28 | 29 | ```toml 30 | webServer.tls.certFile = "server.crt" 31 | webServer.tls.keyFile = "server.key" 32 | ``` 33 | 34 | ## 客户端管理界面 35 | 36 | frpc 内置的 Admin UI 可以帮助用户通过浏览器来查询和管理客户端的 proxy 状态和配置。 37 | 38 | 需要在 frpc.toml 中指定 admin 服务使用的端口,即可开启此功能: 39 | 40 | ```toml 41 | # frpc.toml 42 | webServer.addr = "127.0.0.1" 43 | webServer.port = 7400 44 | webServer.user = "admin" 45 | webServer.password = "admin" 46 | ``` 47 | 48 | 打开浏览器通过 `http://127.0.0.1:7400` 访问 Admin UI。 49 | 50 | 如果想要在外网环境访问 Admin UI,可以将 7400 端口通过 frp 映射出去即可,但需要重视安全风险。 51 | 52 | ```toml 53 | # frpc.toml 54 | [[proxies]] 55 | name = "admin_ui" 56 | type = "tcp" 57 | localPort = 7400 58 | remotePort = 7400 59 | ``` 60 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/common/virtualnet.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "虚拟网络 (VirtualNet)" 3 | weight: 140 4 | --- 5 | 6 | *Alpha feature, added in v0.62.0* 7 | 8 | > **注意**:VirtualNet 是一个 Alpha 阶段的特性,目前不稳定,其配置方式和功能可能会在后续版本中随时调整变更。请勿在生产环境中使用此功能,仅建议用于测试和评估目的。 9 | 10 | ## 概述 11 | 12 | 虚拟网络(VirtualNet)功能允许 frp 通过 TUN 接口创建和管理客户端之间的虚拟网络连接。这一功能将 frp 的能力扩展到了传统端口转发之外,实现了完整的网络层通信。 13 | 14 | 通过 VirtualNet 功能,你可以: 15 | 16 | - 在不同客户端之间建立 IP 层级的网络连接,不需要为每个服务单独配置端口转发 17 | - 使应用程序无需感知 frp 的存在,直接通过 IP 访问远程服务 18 | - 建立类似 VPN 的连接,但由 frp 负责管理 19 | 20 | ## 使用要求 21 | 22 | 使用 VirtualNet 功能需要满足以下条件: 23 | 24 | - **权限要求**:创建 TUN 接口需要 root/管理员权限 25 | - **平台支持**:目前仅支持 Linux 和 macOS 平台 26 | - **特性门控**:需要通过配置 `featureGates = { VirtualNet = true }` 显式启用 27 | - **地址分配**:每个端点必须配置唯一的 IP 地址/CIDR 28 | 29 | ## 配置方法 30 | 31 | ### 启用 VirtualNet 32 | 33 | 由于 VirtualNet 是 Alpha 特性,需要在配置中显式启用: 34 | 35 | ```toml 36 | # frpc.toml 37 | featureGates = { VirtualNet = true } 38 | ``` 39 | 40 | ### 服务端配置 41 | 42 | 首先,为 frpc 配置虚拟网络地址: 43 | 44 | ```toml 45 | # frpc.toml (服务端) 46 | serverAddr = "x.x.x.x" 47 | serverPort = 7000 48 | featureGates = { VirtualNet = true } 49 | 50 | # 配置虚拟网络接口 51 | virtualNet.address = "100.86.0.1/24" 52 | ``` 53 | 54 | 然后,为代理配置 `virtual_net` 插件: 55 | 56 | ```toml 57 | # frpc.toml (服务端) 58 | [[proxies]] 59 | name = "vnet-server" 60 | type = "stcp" 61 | secretKey = "your-secret-key" 62 | [proxies.plugin] 63 | type = "virtual_net" 64 | ``` 65 | 66 | ### 客户端配置 67 | 68 | 客户端需要配置访问者插件以连接到虚拟网络: 69 | 70 | ```toml 71 | # frpc.toml (客户端) 72 | serverAddr = "x.x.x.x" 73 | serverPort = 7000 74 | featureGates = { VirtualNet = true } 75 | 76 | # 配置虚拟网络接口 77 | virtualNet.address = "100.86.0.2/24" 78 | 79 | [[visitors]] 80 | name = "vnet-visitor" 81 | type = "stcp" 82 | serverName = "vnet-server" 83 | secretKey = "your-secret-key" 84 | bindPort = -1 85 | [visitors.plugin] 86 | type = "virtual_net" 87 | destinationIP = "100.86.0.1" # 目标虚拟 IP 地址 88 | ``` 89 | 90 | ## 工作原理 91 | 92 | VirtualNet 功能基于以下技术实现: 93 | 94 | 1. **TUN 虚拟接口**:在每个 frp 客户端创建一个 TUN 虚拟网络接口 95 | 2. **路由控制**:通过 VNet 控制器管理客户端间的路由表 96 | 3. **数据包转发**:在 frp 隧道内部封装和转发 IP 数据包 97 | 98 | 工作流程如下: 99 | 100 | 1. frp 创建 TUN 接口并分配 IP 地址 101 | 2. 服务端使用 `virtual_net` 插件注册连接到 VNet 控制器 102 | 3. 客户端使用 `virtual_net` 访问者插件将目标 IP 的流量路由到对应连接 103 | 4. 数据包在 frp 管理的虚拟网络中传输,实现不同机器之间的 IP 层连通性 -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/http-https/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "HTTP & HTTPS" 3 | weight: 3 4 | description: > 5 | 了解 frp `HTTP`, `HTTPS` 类型的代理。 6 | --- 7 | 8 | HTTP 和 HTTPS 是 frp 中针对这两种协议额外提供了一些特殊的能力。本质上目前这两种应用层协议的底层协议都是 TCP。 9 | 10 | 如果不需要用到相关的特殊功能,可以直接使用 TCP 类型的代理,更加简单方便。 11 | 12 | HTTP 和 HTTPS 协议的一个特点是发送的请求都具有 Host 字段,通过该字段描述要访问的服务。基于这个特点,frp 服务端只需要监听在一个端口(通过 `vhostHTTPPort` 和 `vhostHTTPSPort` 指定)。就可以根据请求的 Host 来决定需要路由给哪一个代理,而不需要像 TCP 类型那样为每一个服务绑定一个端口。 13 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/http-https/auth.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "设置 BasicAuth 鉴权" 3 | weight: 3 4 | --- 5 | 6 | 由于所有客户端共用一个 frps 的 HTTP 服务端口,任何知道你的域名和 URL 的人都能访问到你部署在内网的服务,但是在某些场景下需要确保只有限定的用户才能访问。 7 | 8 | frp 支持通过 HTTP Basic Auth 来保护你的 web 服务,使用户需要通过用户名和密码才能访问到你的服务。 9 | 10 | 该功能目前仅限于 HTTP 类型的代理,需要在 frpc 的代理配置中添加用户名和密码的设置。 11 | 12 | ```toml 13 | # frpc.toml 14 | [[proxies]] 15 | name = "web" 16 | type = "http" 17 | localPort = 80 18 | customDomains = ["test.yourdomain.com"] 19 | httpUser = "abc" 20 | httpPassword = "abc" 21 | ``` 22 | 23 | 通过浏览器访问 `http://test.yourdomain.com`,需要输入配置的用户名和密码才能访问。 24 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/http-https/header.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "修改 HTTP 请求 Header" 3 | weight: 2 4 | --- 5 | 6 | ## 修改 Host Header 7 | 8 | 通常情况下 frp 不会修改转发的任何数据。但有一些后端服务会根据 HTTP 请求 header 中的 Host 字段来展现不同的网站,例如 nginx 的虚拟主机服务,启用 Host Header 的修改功能可以动态修改 HTTP 请求中的 Host 字段。需要注意的是,该功能仅限于 HTTP 类型的代理。 9 | 10 | ```toml 11 | # frpc.toml 12 | [[proxies]] 13 | name = "web" 14 | type = "http" 15 | localPort = 80 16 | customDomains = ["test.yourdomain.com"] 17 | hostHeaderRewrite = "dev.yourdomain.com" 18 | ``` 19 | 20 | 原来 HTTP 请求中的 Host 字段 `test.yourdomain.com` 转发到后端服务时会被替换为 `dev.yourdomain.com`。 21 | 22 | ## 设置普通 Header 23 | 24 | 对于类型为 HTTP 的代理,可以设置在转发中动态添加的 Header 参数 25 | 26 | ```toml 27 | # frpc.toml 28 | [[proxies]] 29 | name = "web" 30 | type = "http" 31 | localPort = 80 32 | customDomains = ["test.yourdomain.com"] 33 | hostHeaderRewrite = "dev.yourdomain.com" 34 | requestHeaders.set.x-from-where = "frp" 35 | responseHeaders.set.foo = "bar" 36 | ``` 37 | 38 | 根据如上的配置,会在请求的 Header 中加上 `x-from-where: frp`,在响应的 Header 中加上 `foo: bar`。 39 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/http-https/route.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "路由" 3 | weight: 5 4 | --- 5 | 6 | ## URL 路由 7 | 8 | frp 支持根据请求的 URL 路径路由转发到不同的后端服务。 9 | 10 | 通过配置文件中的 locations 字段指定一个或多个 proxy 能够匹配的 URL 前缀(目前仅支持最大前缀匹配,之后会考虑正则匹配)。例如指定 `locations = "/news"`,则所有 URL 以 `/news` 开头的请求都会被转发到这个服务。 11 | 12 | ```toml 13 | # frpc.toml 14 | [[proxies]] 15 | name = "web01" 16 | type = "http" 17 | localPort = 80 18 | customDomains = ["web.yourdomain.com"] 19 | locations = ["/"] 20 | 21 | [[proxies]] 22 | name = "web02" 23 | type = "http" 24 | localPort = 81 25 | customDomains = ["web.yourdomain.com"] 26 | locations = ["/news", "/about"] 27 | ``` 28 | 29 | 按照上述的示例配置后,`web.yourdomain.com` 这个域名下所有以 `/news` 以及 `/about` 作为前缀的 URL 请求都会被转发到 web02,其余的请求会被转发到 web01。 30 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/http-https/subdomain.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "自定义二级域名" 3 | weight: 4 4 | --- 5 | 6 | 在多人同时使用一个 frps 时,通过自定义二级域名的方式来使用会更加方便。 7 | 8 | 通过在 frps 的配置文件中配置 `subdomainHost`,就可以启用该特性。之后在 frpc 的 http、https 类型的代理中可以不配置 `customDomains`,而是配置一个 `subdomain` 参数。 9 | 10 | 只需要将 `*.{subdomainHost}` 解析到 frps 所在服务器。之后用户可以通过 subdomain 自行指定自己的 web 服务所需要使用的二级域名,通过 `{subdomain}.{subdomainHost}` 来访问自己的 web 服务。 11 | 12 | ```toml 13 | # frps.toml 14 | subdomainHost = "frps.com" 15 | ``` 16 | 17 | 将泛域名 `*.frps.com` 解析到 frps 所在服务器的 IP 地址。 18 | 19 | ```toml 20 | # frpc.toml 21 | [[proxies]] 22 | name = "web" 23 | type = "http" 24 | localPort = 80 25 | subdomain = "test" 26 | ``` 27 | 28 | frps 和 frpc 都启动成功后,通过 `test.frps.com` 就可以访问到内网的 web 服务。 29 | 30 | **注:如果 frps 配置了 `subdomainHost`,则 `customDomains` 中不能是属于 `subdomainHost` 的子域名或者泛域名。** 31 | 32 | 同一个 HTTP 或 HTTPS 类型的代理中 `customDomains` 和 `subdomain` 可以同时配置。 33 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/stcp-sudp/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "STCP & SUDP" 3 | weight: 4 4 | description: > 5 | 了解 frp `STCP`, `SUDP` 类型的代理。 6 | --- 7 | 8 | STCP 和 SUDP 的 (S) 的含义是 Secret。其作用是为 TCP 和 UDP 类型的服务提供一种安全访问的能力,避免让端口直接暴露在公网上导致任何人都能访问到。 9 | 10 | 这两种代理要求在被访问服务的机器上以及要访问的用户的机器上都部署上 frp 的客户端。被访问的服务所在机器叫做服务端,另一端叫做访问端。 11 | 12 | frp 会在访问端监听一个端口和服务端的端口做映射。访问端的用户需要提供相同的密钥才能连接成功,从而保证安全性。 13 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/tcp-udp/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "TCP & UDP" 3 | weight: 2 4 | description: > 5 | 了解 frp `TCP`, `UDP` 类型的代理。 6 | --- 7 | 8 | TCP 和 UDP 是 frp 中两种最基础的代理类型,用于代理监听在 TCP 和 UDP 端口的服务。 9 | 10 | ```toml 11 | [[proxies]] 12 | name = "ssh" 13 | type = "tcp" 14 | localIP = "127.0.0.1" 15 | localPort = 22 16 | remotePort = 6000 17 | ``` 18 | 19 | 通过 type 指定代理类型。 20 | 21 | frp 会为本地服务的 22 端口,在 frps 所在的服务端监听 6000 端口,将 6000 端口接收到的连接和本地服务的 22 端口关联,透传流量,从而实现让用户在外部访问到内部服务。 22 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/tcpmux/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "TCPMUX" 3 | weight: 6 4 | description: > 5 | 了解 frp `TCPMUX` 类型的代理。 6 | --- 7 | 8 | frp 支持将单个端口收到的连接路由到不同的代理,类似 `vhostHTTPPort` 和 `vhostHTTPSPort`。 9 | 10 | 目前支持的复用器只有 `httpconnect`。 11 | 12 | 当在 `frps.toml` 中设置 `tcpmuxHTTPConnectPort`,frps 将会监听在这个端口,接收 HTTP CONNECT 请求。 13 | 14 | frps 会根据 HTTP CONNECT 请求中的 host 路由到不同的后端代理。 15 | 16 | 示例配置如下: 17 | 18 | ```toml 19 | # frps.toml 20 | bindPort = 7000 21 | tcpmuxHTTPConnectPort = 1337 22 | ``` 23 | 24 | ```toml 25 | # frpc.toml 26 | serverAddr = "x.x.x.x" 27 | serverPort = 7000 28 | 29 | [[proxies]] 30 | name = "proxy1" 31 | type = "tcpmux" 32 | multiplexer = "httpconnect" 33 | customDomains = ["test1"] 34 | localPort = 80 35 | 36 | [[proxies]] 37 | name = "proxy2" 38 | type = "tcpmux" 39 | multiplexer = "httpconnect" 40 | customDomains = ["test2"] 41 | localPort = 8080 42 | ``` 43 | 44 | 通过上面的配置,frps 如果接收到 HTTP CONNECT 请求内容: 45 | 46 | ``` 47 | CONNECT test1 HTTP/1.1\r\n\r\n 48 | ``` 49 | 50 | 该连接将会被路由到 proxy1 。 51 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Features/xtcp/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "XTCP" 3 | weight: 5 4 | description: > 5 | 了解 frp `XTCP` 类型的代理。 6 | --- 7 | 8 | XTCP 的配置方式和 STCP 很类似。但是会采用 P2P 的方式进行打洞穿透,如果成功,后续的流量将不会经过 frps,而是直接通信,不再受到 frps 所在服务器的带宽限制。 9 | 10 | 由于打洞成功率取决于所处网络的 NAT 类型,所以 XTCP 的可用性和稳定性无法保证。在需要可靠连接的情况下,建议使用 STCP 替代。 11 | 12 | 当 visitor 配置了 `keepTunnelOpen = true` 时,frpc 会定期检测隧道是否打开,如果没有,则会尝试打洞建立隧道,这样可以始终保持隧道打开,在需要连接对端服务时,可以避免延迟。 13 | 14 | 默认情况下,visitor 会在接收到用户连接后尝试打洞,如果打洞失败,可以尝试多次建立连接,程序会尝试其他的打洞策略,有可能在多次重试后成功打洞。一旦打洞成功,后续新增连接不必重复打洞,而是可以复用隧道。 15 | 16 | ## Fallback 机制 17 | 18 | 可以通过配置 fallback 到 stcp visitor 实现在打洞失败时,回退到 stcp 建立连接。 19 | 20 | 示例配置: 21 | 22 | ```toml 23 | [[visitors]] 24 | name = "stcp-visitor" 25 | type = "stcp" 26 | serverName = "stcp-test" 27 | secretKey = "abc" 28 | bindPort = -1 29 | 30 | [[visitors]] 31 | name = "xtcp-visitor" 32 | type = "xtcp" 33 | serverName = "xtcp-test" 34 | secretKey = "abc" 35 | bindAddr = "127.0.0.1" 36 | bindPort = 9002 37 | fallbackTo = "stcp-visitor" 38 | fallbackTimeoutMs = 200 39 | ``` 40 | 41 | 当连接 `127.0.0.1:9002` 超过 200ms p2p 打洞还未成功的话,会回退到使用 stcp-visitor 建立连接。fallback 后,之前触发的打洞操作仍然会继续,一般来说打洞完成需要的耗时会比较长。 42 | 43 | 如果打洞成功,下次建立新的连接时,将不需要再次打洞,会很快完成连接建立,不会触发 fallback。 44 | 45 | 需要注意根据访问端和被访问端的延迟情况来合理设置超时时间,以避免超时时间太短,即使打洞成功连接也来不及建立,而一直触发 fallback。 46 | 47 | stcp-visitor 的 `bindPort` 设置为 -1 表示不需要监听物理端口,只接受 fallback 的连接即可。 48 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Overview/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "概览" 3 | weight: 1 4 | description: > 5 | 一些概述,便于您快速的了解 frp。 6 | --- 7 | 8 | ## frp 是什么? 9 | 10 | frp 是一款高性能的反向代理应用,专注于内网穿透。它支持多种协议,包括 TCP、UDP、HTTP、HTTPS 等,并且具备 P2P 通信功能。使用 frp,您可以安全、便捷地将内网服务暴露到公网,通过拥有公网 IP 的节点进行中转。 11 | 12 | ## 为什么选择 frp? 13 | 14 | 通过在具有公网 IP 的节点上部署 frp 服务端,您可以轻松地将内网服务穿透到公网,并享受以下专业特性: 15 | 16 | * 多种协议支持:客户端服务端通信支持 TCP、QUIC、KCP 和 Websocket 等多种协议。 17 | * TCP 连接流式复用:在单个连接上承载多个请求,减少连接建立时间,降低请求延迟。 18 | * 代理组间的负载均衡。 19 | * 端口复用:多个服务可以通过同一个服务端端口暴露。 20 | * P2P 通信:流量不必经过服务器中转,充分利用带宽资源。 21 | * 客户端插件:提供多个原生支持的客户端插件,如静态文件查看、HTTPS/HTTP 协议转换、HTTP、SOCKS5 代理等,以便满足各种需求。 22 | * 服务端插件系统:高度可扩展的服务端插件系统,便于根据自身需求进行功能扩展。 23 | * 用户友好的 UI 页面:提供服务端和客户端的用户界面,使配置和监控变得更加方便。 24 | 25 | ## 下一步? 26 | 27 | * [安装](../setup/):了解如何安装 frp。 28 | * [示例](../examples/):通过简单示例了解 frp 的不同应用场景。 29 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Reference/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "参考" 3 | weight: 6 4 | --- 5 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Reference/client-configures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "客户端配置" 3 | weight: 3 4 | description: > 5 | frp 客户端的详细配置说明。 6 | --- 7 | 8 | ### ClientConfig 9 | 10 | | Field | Type | Description | Required | 11 | | :--- | :--- | :--- | :--- | 12 | | | [ClientCommonConfig](#clientcommonconfig) | 客户端通用配置。 | Yes | 13 | | proxies | [[]ProxyConfig](../proxy) | 代理配置,不同的代理类型对应不同的配置,例如 [TCPProxyConfig](../proxy#tcpproxyconfig) 或 [HTTPProxyConfig](../proxy#httpproxyconfig)。 | No | 14 | | visitors | [[]VisitorConfig](../visitor) | 访问者配置,不同的访问者类型对应不同的配置,例如 [STCPVisitorConfig](../visitor#stcpvisitorconfig)。 | No | 15 | 16 | ### ClientCommonConfig 17 | 18 | | Field | Type | Description | Required | 19 | | :--- | :--- | :--- | :--- | 20 | | auth | [AuthClientConfig](#authclientconfig) | 客户端鉴权配置。 | No | 21 | | user | string | 用户名,设置此参数后,代理名称会被修改为 {user}.{proxyName},避免代理名称和其他用户冲突。 | No | 22 | | serverAddr | string | 连接服务端的地址。 | No | 23 | | serverPort | int | 连接服务端的端口,默认为 7000。 | No | 24 | | natHoleStunServer | string | xtcp 打洞所需的 stun 服务器地址,默认为 stun.easyvoip.com:3478。 | No | 25 | | dnsServer | string | 使用 DNS 服务器地址,默认使用系统配置的 DNS 服务器,指定此参数可以强制替换为自定义的 DNS 服务器地址。 | No | 26 | | loginFailExit | bool | 第一次登陆失败后是否退出,默认为 true。 | No | 27 | | start | []string | 指定启用部分代理,当配置了较多代理,但是只希望启用其中部分时可以通过此参数指定,默认为全部启用。 | No | 28 | | log | [LogConfig](../common#logconfig) | 日志配置。 | No | 29 | | webServer | [WebServerConfig](../common#webserverconfig) | 客户端 AdminServer 配置。 | No | 30 | | transport | [ClientTransportConfig](#clienttransportconfig) | 客户端网络层配置。 | No | 31 | | virtualNet | [VirtualNetConfig](#virtualnetconfig) | 虚拟网络配置,Alpha 特性。 | No | 32 | | featureGates | map[string]bool | 特性门控,用于启用或禁用实验性功能。 | No | 33 | | udpPacketSize | int | 代理 UDP 服务时支持的最大包长度,默认为 1500,服务端和客户端需要保持配置一致。 | No | 34 | | metadatas | map[string]string | 附加元数据,会传递给服务端插件,提供附加能力。 | No | 35 | | includes | []string | 指定额外的配置文件目录,其中的 proxy 和 visitor 配置会被读取加载。 | No | 36 | 37 | ### ClientTransportConfig 38 | 39 | | Field | Type | Description | Required | 40 | | :--- | :--- | :--- | :--- | 41 | | protocol | string | 和 frps 之间的通信协议,可选值为 tcp, kcp, quic, websocket, wss。默认为 tcp。 | No | 42 | | dialServerTimeout | int | 连接服务端的超时时间,默认为 10s。 | No | 43 | | dialServerKeepalive | int | 和服务端底层 TCP 连接的 keepalive 间隔时间,单位秒。 | No | 44 | | connectServerLocalIP | string | 连接服务端时所绑定的本地 IP。 | No | 45 | | proxyURL | string | 连接服务端使用的代理地址,格式为 {protocol}://user:passwd@192.168.1.128:8080 protocol 目前支持 http、socks5、ntlm。 | No | 46 | | poolCount | int | 连接池大小。 | No | 47 | | tcpMux | bool | TCP 多路复用,默认启用。 | No | 48 | | tcpMuxKeepaliveInterval | int | `tcp_mux` 的心跳检查间隔时间。 | No | 49 | | quic | [QUICOptions](../common#quicoptions) | QUIC 协议配置参数。 | No | 50 | | heartbeatInterval | int | 向服务端发送心跳包的间隔时间,默认为 30s。建议启用 `tcp_mux_keepalive_interval`,将此值设置为 -1。 | No | 51 | | heartbeatTimeout | int | 和服务端心跳的超时时间,默认为 90s。 | No | 52 | | tls | [TLSClientConfig](#tlsclientconfig) | 客户端 TLS 协议配置。 | No | 53 | 54 | ### TLSClientConfig 55 | 56 | | Field | Type | Description | Required | 57 | | :--- | :--- | :--- | :--- | 58 | | enable | bool | 是否和服务端之间启用 TLS 连接,默认启用。 | No | 59 | | disableCustomTLSFirstByte | bool | 启用 TLS 连接时,不发送 0x17 特殊字节。默认为 true。当配置为 true 时,无法和 vhostHTTPSPort 端口复用。 | No | 60 | | | [TLSConfig](../common#tlsconfig) | TLS 协议配置,内嵌结构。 | No | 61 | 62 | ### AuthClientConfig 63 | 64 | | Field | Type | Description | Required | 65 | | :--- | :--- | :--- | :--- | 66 | | method | string | 鉴权方式,可选值为 token 或 oidc,默认为 token。 | No | 67 | | additionalScopes | []string | 鉴权信息附加范围,可选值为 HeartBeats 和 NewWorkConns | No | 68 | | token | string | 在 method 为 token 时生效,客户端需要设置一样的值才能鉴权通过。 | No | 69 | | oidc | [AuthOIDCClientConfig](#authoidcclientconfig) | oidc 鉴权配置。| No | 70 | 71 | ### AuthOIDCClientConfig 72 | 73 | | Field | Type | Description | Required | 74 | | :--- | :--- | :--- | :--- | 75 | | clientID | string | | No | 76 | | clientSecret | string | | No | 77 | | audience | string | | No | 78 | | scope | string | | No | 79 | | tokenEndpointURL | string | | No | 80 | | additionalEndpointParams | map[string]string | | No | 81 | 82 | ### VirtualNetConfig 83 | 84 | | Field | Type | Description | Required | 85 | | :--- | :--- | :--- | :--- | 86 | | address | string | 虚拟网络接口的 IP 地址和网段,格式为 CIDR (例如 "100.86.0.1/24")。 | Yes | 87 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Reference/client-plugin.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "客户端插件配置" 3 | weight: 6 4 | description: > 5 | frp 客户端插件的详细配置说明。 6 | --- 7 | 8 | ### HTTPProxyPluginOptions 9 | 10 | | Field | Type | Description | Required | 11 | | :--- | :--- | :--- | :--- | 12 | | type | string | 插件类型,设置为 "http_proxy"。 | Yes | 13 | | httpUser | string | HTTP 代理用户名。 | No | 14 | | httpPassword | string | HTTP 代理密码。 | No | 15 | 16 | ### Socks5PluginOptions 17 | 18 | | Field | Type | Description | Required | 19 | | :--- | :--- | :--- | :--- | 20 | | type | string | 插件类型,设置为 "socks5"。 | Yes | 21 | | username | string | 用户名。 | No | 22 | | password | string | 密码。 | No | 23 | 24 | ### StaticFilePluginOptions 25 | 26 | | Field | Type | Description | Required | 27 | | :--- | :--- | :--- | :--- | 28 | | type | string | 插件类型,设置为 "static_file"。 | Yes | 29 | | localPath | string | 静态文件所在本地路径。 | Yes | 30 | | stripPrefix | string | 去除用户 HTTP 请求 Path 的特定前缀。 | No | 31 | | httpUser | string | HTTP Basic Auth 用户名。 | No | 32 | | httpPassword | string | HTTP Basic Auth 密码。 | No | 33 | 34 | ### UnixDomainSocketPluginOptions 35 | 36 | | Field | Type | Description | Required | 37 | | :--- | :--- | :--- | :--- | 38 | | type | string | 插件类型,设置为 "unix_domain_socket"。 | Yes | 39 | | unixPath | string | UNIX 域套接字的地址。 | Yes | 40 | 41 | ### HTTP2HTTPSPluginOptions 42 | 43 | | Field | Type | Description | Required | 44 | | :--- | :--- | :--- | :--- | 45 | | type | string | 插件类型,设置为 "http2https"。 | Yes | 46 | | localAddr | string | 本地 HTTPS 服务地址。 | Yes | 47 | | hostHeaderRewrite | string | 替换 Host header。 | No | 48 | | requestHeaders | [HeaderOperations](../common#headeroperations) | 对请求 Header 的操作配置。 | No | 49 | 50 | ### HTTPS2HTTPPluginOptions 51 | 52 | | Field | Type | Description | Required | 53 | | :--- | :--- | :--- | :--- | 54 | | type | string | 插件类型,设置为 "https2http"。 | Yes | 55 | | localAddr | string | 本地 HTTPS 服务地址。 | Yes | 56 | | hostHeaderRewrite | string | 替换 Host header。 | No | 57 | | requestHeaders | [HeaderOperations](../common#headeroperations) | 对请求 Header 的操作配置。 | No | 58 | | enableHTTP2 | bool | 是否启用 HTTP/2,默认启用。 | No | 59 | | crtPath | string | TLS 证书文件路径。 | No | 60 | | keyPath | string | TLS 密钥文件路径。 | No | 61 | 62 | ### HTTPS2HTTPSPluginOptions 63 | 64 | | Field | Type | Description | Required | 65 | | :--- | :--- | :--- | :--- | 66 | | type | string | 插件类型,设置为 "https2https"。 | Yes | 67 | | localAddr | string | 本地 HTTPS 服务地址。 | Yes | 68 | | hostHeaderRewrite | string | 替换 Host header。 | No | 69 | | requestHeaders | [HeaderOperations](../common#headeroperations) | 对请求 Header 的操作配置。 | No | 70 | | enableHTTP2 | bool | 是否启用 HTTP/2,默认启用。 | No | 71 | | crtPath | string | TLS 证书文件路径。 | No | 72 | | keyPath | string | TLS 密钥文件路径。 | No | 73 | 74 | ### TLS2RawPluginOptions 75 | 76 | | Field | Type | Description | Required | 77 | | :--- | :--- | :--- | :--- | 78 | | type | string | 插件类型,设置为 "tls2raw"。 | Yes | 79 | | localAddr | string | 本地服务地址。 | Yes | 80 | | crtPath | string | TLS 证书文件路径。 | No | 81 | | keyPath | string | TLS 密钥文件路径。 | No | 82 | 83 | ### VirtualNetPluginOptions 84 | 85 | | Field | Type | Description | Required | 86 | | :--- | :--- | :--- | :--- | 87 | | type | string | 插件类型,设置为 "virtual_net"。 | Yes | -------------------------------------------------------------------------------- /content/zh-cn/docs/Reference/common.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "通用配置" 3 | weight: 1 4 | description: > 5 | 通用配置结构。 6 | --- 7 | 8 | ### LogConfig 9 | 10 | | Field | Type | Description | Required | 11 | | :--- | :--- | :--- | :--- | 12 | | to | string | 日志输出文件路径,如果为 console,则会将日志打印在标准输出中。 | No | 13 | | level | string | 日志级别,可选值为 trace, debug, info, warn, error,默认级别为 info。 | No | 14 | | maxDays | int | 日志文件最多保留天数,默认为 3 天。 | No | 15 | | disablePrintColor | bool | 禁用标准输出中的日志颜色。 | No | 16 | 17 | ### WebServerConfig 18 | 19 | | Field | Type | Description | Required | 20 | | :--- | :--- | :--- | :--- | 21 | | addr | string | webServer 监听地址,默认为 127.0.0.1。 | No | 22 | | port | int | webServer 监听端口。| Yes | 23 | | user | string | HTTP BasicAuth 用户名。| No | 24 | | password | string | HTTP BasicAuth 密码。 | No | 25 | | assetsDir | string | 静态资源目录,Dashboard 使用的资源默认打包在二进制文件中,通过指定此参数使用自定义的静态资源。 | No | 26 | | pprofEnable | bool | 启动 Go HTTP pprof,用于应用调试。 | No | 27 | | tls | [TLSConfig](#tlsconfig) | Dashboard 启用 HTTPS 的 TLS 相关配置。 | No | 28 | 29 | ### TLSConfig 30 | 31 | | Field | Type | Description | Required | 32 | | :--- | :--- | :--- | :--- | 33 | | certFile | string | TLS 证书文件路径。 | Yes | 34 | | keyFile | string | TLS 密钥文件路径。 | Yes | 35 | | trustedCaFile | string | CA 证书文件路径。 | No | 36 | | serverName | string | TLS Server 名称。 | No | 37 | 38 | ### QUICOptions 39 | 40 | | Field | Type | Description | Required | 41 | | :--- | :--- | :--- | :--- | 42 | | keepalivePeriod | int | 默认值为 10 秒。 | No | 43 | | maxIdleTimeout | int | 默认值为 30 秒。 | No | 44 | | maxIncomingStreams | int | 默认值为 100000。 | No | 45 | 46 | ### PortsRange 47 | 48 | | Field | Type | Description | Required | 49 | | :--- | :--- | :--- | :--- | 50 | | start | int | 起始端口。 | No | 51 | | end | int | 终止端口。 | No | 52 | | single | int | 单一端口。 | No | 53 | 54 | ### HeaderOperations 55 | 56 | | Field | Type | Description | Required | 57 | | :--- | :--- | :--- | :--- | 58 | | set | map[string]string | 在 Header 中设置指定的 KV 值。 | No | 59 | 60 | ### HTTPHeader 61 | 62 | | Field | Type | Description | Required | 63 | | :--- | :--- | :--- | :--- | 64 | | name | string | Header 名称。 | Yes | 65 | | value | string | Header 值。 | Yes | 66 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Reference/proxy.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "代理配置" 3 | weight: 4 4 | description: > 5 | frp 代理的详细配置说明。 6 | --- 7 | 8 | ### ProxyBaseConfig 9 | 10 | | Field | Type | Description | Required | 11 | | :--- | :--- | :--- | :--- | 12 | | name | string | 代理名称。 | Yes | 13 | | type | string | 代理类型,可选值为 tcp, udp, http, https, tcpmux, stcp, sudp, xtcp。 | Yes | 14 | | annotations | map[string]string | 代理的注释信息,会被展示在 server 的 dashboard 中。 | No | 15 | | transport | [ProxyTransport](#proxytransport) | 代理网络层配置。 | No | 16 | | metadatas | map[string]string | 附加元数据,会传递给服务端插件,提供附加能力。 | No | 17 | | loadBalancer | [LoadBalancerConfig](#loadbalancerconfig) | 负载均衡配置。 | No | 18 | | healthCheck | [HealthCheckConfig](#healthcheckconfig) | 健康检查配置。 | No | 19 | | | [ProxyBackend](#proxybackend) | 代理后端服务配置。 | Yes | 20 | 21 | ### ProxyTransport 22 | 23 | | Field | Type | Description | Required | 24 | | :--- | :--- | :--- | :--- | 25 | | useEncryption | bool | 是否启用加密功能,启用后该代理和服务端之间的通信内容都会被加密传输,如果 frpc 启用了全局 TLS,则不需要再启用此参数。 | No | 26 | | useCompression | bool | 是否启用压缩功能,启用后该代理和服务端之间的通信内容都会被压缩传输。 | No | 27 | | bandwidthLimit | string | 设置单个 proxy 的带宽限流,单位为 MB 或 KB,0 表示不限制,如果启用,默认会作用于对应的 frpc。 | No | 28 | | bandwidthLimitMode | string | 限流类型,客户端限流或服务端限流,可选值为 client 和 server,默认为客户端限流。 | No | 29 | | proxyProtocolVersion | string | 启用 proxy protocol 协议的版本,可选值为 v1 和 v2。如果启用,则 frpc 和本地服务建立连接后会发送 proxy protocol 的协议,包含了原请求的 IP 地址和端口等内容。 | No | 30 | 31 | ### ProxyBackend 32 | 33 | | Field | Type | Description | Required | 34 | | :--- | :--- | :--- | :--- | 35 | | localIP | string | 被代理的本地服务 IP,默认为 127.0.0.1。 | No | 36 | | localPort | int | 被代理的本地服务端口。 | No | 37 | | plugin | [ClientPluginOptions](../client-plugin) | 客户端插件配置,如果启用了客户端插件,则不需要配置 localIP 和 localPort,流量会由客户端插件接管。不同的插件类型对应不同的配置,例如 [HTTPProxyPluginOptions](../client-plugin#httpproxypluginoptions)。 | No | 38 | 39 | ### LoadBalancerConfig 40 | 41 | | Field | Type | Description | Required | 42 | | :--- | :--- | :--- | :--- | 43 | | group | string | 负载均衡分组名称,用户请求会以轮询的方式发送给同一个 group 中的代理。 | Yes | 44 | | groupKey | string | 负载均衡分组密钥,用于对负载均衡分组进行鉴权,groupKey 相同的代理才会被加入到同一个分组中。 | No | 45 | 46 | ### HealthCheckConfig 47 | 48 | | Field | Type | Description | Required | 49 | | :--- | :--- | :--- | :--- | 50 | | type | string | 健康检查类型,可选值为 tcp 和 http,配置后启用健康检查功能,tcp 是连接成功则认为服务健康,http 要求接口返回 2xx 的状态码则认为服务健康。 | Yes | 51 | | timeoutSeconds | int | 健康检查超时时间(秒),默认为 3s。 | No | 52 | | maxFailed | int | 健康检查连续错误次数,连续检查错误多少次认为服务不健康,默认为 1。 | No | 53 | | intervalSeconds | int | 健康检查周期(秒),每隔多长时间进行一次健康检查,默认为 10s。 | No | 54 | | path | string | 健康检查的 HTTP 接口,如果健康检查类型是 http,则需要配置此参数,指定发送 http 请求的 path,例如 `/health`。 | No | 55 | | httpHeaders | [[]HTTPHeader](../common#httpheader) | 健康检查的 HTTP 请求头,仅在健康检查类型是 http 时生效。 | No | 56 | 57 | ### DomainConfig 58 | 59 | | Field | Type | Description | Required | 60 | | :--- | :--- | :--- | :--- | 61 | | customDomains | []string | 自定义域名列表。 | No | 62 | | subdomain | string | 子域名。 | No | 63 | 64 | ### TCPProxyConfig 65 | 66 | | Field | Type | Description | Required | 67 | | :--- | :--- | :--- | :--- | 68 | | | [ProxyBaseConfig](#proxybaseconfig) | 基础配置。 | Yes | 69 | | remotePort | int | 服务端绑定的端口,用户访问服务端此端口的流量会被转发到对应的本地服务。 | No | 70 | 71 | ### UDPProxyConfig 72 | 73 | | Field | Type | Description | Required | 74 | | :--- | :--- | :--- | :--- | 75 | | | [ProxyBaseConfig](#proxybaseconfig) | 基础配置。 | Yes | 76 | | remotePort | int | 服务端绑定的端口,用户访问服务端此端口的流量会被转发到对应的本地服务。 | No | 77 | 78 | ### HTTPProxyConfig 79 | 80 | | Field | Type | Description | Required | 81 | | :--- | :--- | :--- | :--- | 82 | | | [ProxyBaseConfig](#proxybaseconfig) | 基础配置。 | Yes | 83 | | | [DomainConfig](#domainconfig) | 域名配置。 | Yes | 84 | | locations | []string | URL 路由配置。 | No | 85 | | httpUser | string | HTTP Basic Auth 用户名。 | No | 86 | | httpPassword | string | HTTP Basic Auth 密码。 | No | 87 | | hostHeaderRewrite | string | 替换 Host Header。 | No | 88 | | requestHeaders | [HeaderOperations](../common#headeroperations) | 对请求 Header 的操作配置。 | No | 89 | | responseHeaders | [HeaderOperations](../common#headeroperations) | 对响应 Header 的操作配置。 | No | 90 | | routeByHTTPUser | string | 根据 HTTP Basic Auth user 路由。 | No | 91 | 92 | ### HTTPSProxyConfig 93 | 94 | | Field | Type | Description | Required | 95 | | :--- | :--- | :--- | :--- | 96 | | | [ProxyBaseConfig](#proxybaseconfig) | 基础配置。 | Yes | 97 | | | [DomainConfig](#domainconfig) | 域名配置。 | Yes | 98 | 99 | ### TCPMuxProxyConfig 100 | 101 | | Field | Type | Description | Required | 102 | | :--- | :--- | :--- | :--- | 103 | | | [ProxyBaseConfig](#proxybaseconfig) | 基础配置。 | Yes | 104 | | | [DomainConfig](#domainconfig) | 域名配置。 | Yes | 105 | | httpUser | string | 用户名,如果配置此参数,通过 HTTP CONNECT 建立连接时需要通过 Proxy-Authorization 附加上正确的身份信息。 | No | 106 | | httpPassword | string | 密码。 | No | 107 | | routeByHTTPUser | string | 根据 HTTP Basic Auth user 路由。 | No | 108 | | multiplexer | string | 复用器类型,目前仅支持 httpconnect。 | No | 109 | 110 | ### STCPProxyConfig 111 | 112 | | Field | Type | Description | Required | 113 | | :--- | :--- | :--- | :--- | 114 | | | [ProxyBaseConfig](#proxybaseconfig) | 基础配置。 | Yes | 115 | | secretKey | string | 密钥,服务端和访问端的密钥需要一致,访问端才能访问到服务端。 | No | 116 | | allowUsers | []string | 允许访问的 visitor 用户列表,默认只允许同一用户下的 visitor 访问,配置为 * 则允许任何 visitor 访问。 | No | 117 | 118 | ### XTCPProxyConfig 119 | 120 | | Field | Type | Description | Required | 121 | | :--- | :--- | :--- | :--- | 122 | | | [ProxyBaseConfig](#proxybaseconfig) | 基础配置。 | Yes | 123 | | secretKey | string | 密钥,服务端和访问端的密钥需要一致,访问端才能访问到服务端。 | No | 124 | | allowUsers | []string | 允许访问的 visitor 用户列表,默认只允许同一用户下的 visitor 访问,配置为 * 则允许任何 visitor 访问。 | No | 125 | 126 | ### SUDPProxyConfig 127 | 128 | | Field | Type | Description | Required | 129 | | :--- | :--- | :--- | :--- | 130 | | | [ProxyBaseConfig](#proxybaseconfig) | 基础配置。 | Yes | 131 | | secretKey | string | 密钥,服务端和访问端的密钥需要一致,访问端才能访问到服务端。 | No | 132 | | allowUsers | []string | 允许访问的 visitor 用户列表,默认只允许同一用户下的 visitor 访问,配置为 * 则允许任何 visitor 访问。 | No | 133 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Reference/server-configures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "服务端配置" 3 | weight: 2 4 | description: > 5 | frp 服务端详细配置说明。 6 | --- 7 | 8 | ### ServerConfig 9 | 10 | | Field | Type | Description | Required | 11 | | :--- | :--- | :--- | :--- | 12 | | auth | [AuthServerConfig](#authserverconfig) | 鉴权配置。 | No | 13 | | bindAddr | string | 服务端监听地址,用于接收 frpc 的连接,默认监听 0.0.0.0。| No | 14 | | bindPort | int | 服务端监听端口,默认值为 7000。| No | 15 | | kcpBindPort | int | 服务端监听 KCP 协议端口,用于接收配置了使用 KCP 协议的 frpc 连接。| No | 16 | | quicBindPort | int | 服务端监听 QUIC 协议端口,用于接收配置了使用 QUIC 协议的 frpc 连接。| No | 17 | | proxyBindAddr | string | 代理监听地址,可以使代理监听在不同的网卡地址,默认情况下同 bindAddr。| No | 18 | | vhostHTTPPort | int | HTTP 类型代理监听的端口,启用后才能支持 HTTP 类型的代理。 | No | 19 | | vhostHTTPTimeout | int | HTTP 类型代理在服务端的 ResponseHeader 超时时间,默认为 60s。| No | 20 | | vhostHTTPSPort | int | HTTPS 类型代理监听的端口,启用后才能支持 HTTPS 类型的代理。 | No | 21 | | tcpmuxHTTPConnectPort | int | tcpmux 类型且复用器为 httpconnect 的代理监听的端口。 | No | 22 | | tcpmuxPassthrough | bool | 对于 tcpmux 类型的代理是否透传 CONNECT 请求。| No | 23 | | subDomainHost | string | 二级域名后缀。 | No | 24 | | custom404Page | string | 自定义 404 错误页面地址。 | No | 25 | | sshTunnelGateway| [SSHTunnelGateway](#sshtunnelgateway) | ssh 隧道网关配置。 | No | 26 | | webServer | [WebServerConfig](../common#webserverconfig) | 服务端 Dashboard 配置。 | No | 27 | | enablePrometheus | bool | 是否提供 Prometheus 监控接口,需要同时启用了 webServer 后才会生效。 | No | 28 | | log | [LogConfig](../common#logconfig) | 日志配置。 | No | 29 | | transport | [ServerTransportConfig](#servertransportconfig) | 网络层配置。 | No | 30 | | detailedErrorsToClient | bool | 服务端返回详细错误信息给客户端,默认为 true。 | No | 31 | | maxPortsPerClient | int | 限制单个客户端最大同时存在的代理数,默认无限制。 | No | 32 | | userConnTimeout | int | 用户建立连接后等待客户端响应的超时时间,单位秒,默认为 10 秒。 | No | 33 | | udpPacketSize | int | 代理 UDP 服务时支持的最大包长度,默认为 1500,服务端和客户端的值需要一致。 | No | 34 | | natholeAnalysisDataReserveHours | int | 打洞策略数据的保留时间,默认为 168 小时,即 7 天。 | No | 35 | | allowPorts | [[]PortsRange](../common#portsrange) | 允许代理绑定的服务端端口。 | No | 36 | | httpPlugins | [[]HTTPPluginOptions](#httppluginoptions) | 服务端 HTTP 插件配置。 | No | 37 | 38 | ### AuthServerConfig 39 | 40 | | Field | Type | Description | Required | 41 | | :--- | :--- | :--- | :--- | 42 | | method | string | 鉴权方式,可选值为 token 或 oidc,默认为 token。 | No | 43 | | additionalScopes | []string | 鉴权信息附加范围,可选值为 HeartBeats 和 NewWorkConns | No | 44 | | token | string | 在 method 为 token 时生效,客户端需要设置一样的值才能鉴权通过。 | No | 45 | | oidc | [AuthOIDCServerConfig](#authoidcserverconfig) | oidc 鉴权配置。| No | 46 | 47 | ### AuthOIDCServerConfig 48 | 49 | | Field | Type | Description | Required | 50 | | :--- | :--- | :--- | :--- | 51 | | issuer | string | | No | 52 | | audience | string | | No | 53 | | skipExpiryCheck | bool | | No | 54 | | skipIssuerCheck | bool | | No | 55 | 56 | ### ServerTransportConfig 57 | 58 | | Field | Type | Description | Required | 59 | | :--- | :--- | :--- | :--- | 60 | | tcpMuxKeepaliveInterval | int | tcp mux 的心跳检查间隔时间,单位秒。 | No | 61 | | tcpKeepalive | int | 和客户端底层 TCP 连接的 keepalive 间隔时间,单位秒,配置为负数表示不启用。 | No | 62 | | maxPoolCount | int | 允许客户端设置的最大连接池大小,如果客户端配置的值大于此值,会被强制修改为最大值,默认为 5。 | No | 63 | | heartbeatTimeout | int | 服务端和客户端心跳连接的超时时间,单位秒,默认为 90 秒。 | No | 64 | | quic | [QUICOptions](../common#quicoptions) | QUIC 协议配置参数。 | No | 65 | | tls | [TLSServerConfig](#tlsserverconfig) | 服务端 TLS 协议配置。 | No | 66 | 67 | ### TLSServerConfig 68 | 69 | | Field | Type | Description | Required | 70 | | :--- | :--- | :--- | :--- | 71 | | force | bool | 是否只接受启用了 TLS 的客户端连接。 | No | 72 | | | [TLSConfig](../common#tlsconfig) | TLS 协议配置,内嵌结构。 | No | 73 | 74 | ### HTTPPluginOptions 75 | 76 | | Field | Type | Description | Required | 77 | | :--- | :--- | :--- | :--- | 78 | | name | string | 插件名称。 | Yes | 79 | | addr | string | 插件接口的地址。 | Yes | 80 | | path | string | 插件接口的 Path。 | Yes | 81 | | ops | []string | 插件需要生效的操作列表,具体可选值请参考服务端插件的说明文档。 | Yes | 82 | | tlsVerify | bool | 当插件地址为 HTTPS 协议时,是否校验插件的 TLS 证书,默认为不校验。 | No | 83 | 84 | ### SSHTunnelGateway 85 | 86 | | Field | Type | Description | Required | 87 | | :--- | :--- | :--- | :--- | 88 | | bindPort| int | SSH 服务器监听端口。| YES | 89 | | privateKeyFile | string | SSH 服务器私钥文件路径。若为空,frps将读取autoGenPrivateKeyPath路径下的私钥文件。| No | 90 | | autoGenPrivateKeyPath | string |私钥文件自动生成路径,默认为./.autogen_ssh_key。若文件不存在或内容为空,frps将自动生成RSA私钥文件并存储到该路径。|No| 91 | | authorizedKeysFile | string |SSH 客户端授权密钥文件路径。若为空,则不进行SSH客户端鉴权认证。非空可实现SSH免密登录认证。| No | 92 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Reference/visitor-plugin.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "访问者插件配置" 3 | weight: 7 4 | description: > 5 | frp 访问者插件的详细配置说明。 6 | --- 7 | 8 | ### VirtualNetVisitorPluginOptions 9 | 10 | | Field | Type | Description | Required | 11 | | :--- | :--- | :--- | :--- | 12 | | type | string | 插件类型,设置为 "virtual_net"。 | Yes | 13 | | destinationIP | string | 要访问的目标虚拟 IP 地址。通常是服务端的虚拟网络地址。 | Yes | -------------------------------------------------------------------------------- /content/zh-cn/docs/Reference/visitor.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "访问者配置" 3 | weight: 5 4 | description: > 5 | frp 访问者的详细配置说明。 6 | --- 7 | 8 | ### VisitorBaseConfig 9 | 10 | | Field | Type | Description | Required | 11 | | :--- | :--- | :--- | :--- | 12 | | name | string | 访问者名称。 | Yes | 13 | | type | string | 访问者类型,可选值为 stcp, sudp, xtcp。 | Yes | 14 | | transport | [VisitorTransport](#visitortransport) | 访问者网络层配置。 | No | 15 | | secretKey | string | 密钥,服务端和访问端的密钥需要一致,访问端才能访问到服务端。 | No | 16 | | serverUser | string | 要访问的 proxy 所属的用户名,如果为空,则默认为当前用户。 | No | 17 | | serverName | string | 要访问的 proxy 名称。 | Yes | 18 | | bindAddr | string | visitor 监听的本地地址,通过访问监听的地址和端口,连接到远端代理的服务。 | No | 19 | | bindPort | int | visitor 监听的本地端口,如果为 -1,表示不需要监听物理端口,通常可以用于作为其他 visitor 的 fallback。 | Yes | 20 | | plugin | [VisitorPluginOptions](../visitor-plugin) | 访问者插件配置,用于扩展 visitor 功能。不同的插件类型对应不同的配置。 | No | 21 | 22 | ### VisitorTransport 23 | 24 | | Field | Type | Description | Required | 25 | | :--- | :--- | :--- | :--- | 26 | | useEncryption | bool | 是否启用加密功能,启用后该代理和服务端之间的通信内容都会被加密传输,如果 frpc 启用了全局 TLS,则不需要再启用此参数。 | No | 27 | | useCompression | bool | 是否启用压缩功能,启用后该代理和服务端之间的通信内容都会被压缩传输。 | No | 28 | 29 | ### STCPVisitorConfig 30 | 31 | | Field | Type | Description | Required | 32 | | :--- | :--- | :--- | :--- | 33 | | | [VisitorBaseConfig](#visitorbaseconfig) | 基础配置。 | Yes | 34 | 35 | ### SUDPVisitorConfig 36 | 37 | | Field | Type | Description | Required | 38 | | :--- | :--- | :--- | :--- | 39 | | | [VisitorBaseConfig](#visitorbaseconfig) | 基础配置。 | Yes | 40 | 41 | ### XTCPVisitorConfig 42 | 43 | | Field | Type | Description | Required | 44 | | :--- | :--- | :--- | :--- | 45 | | | [VisitorBaseConfig](#visitorbaseconfig) | 基础配置。 | Yes | 46 | | protocol | string | 隧道底层通信协议,可选 quic 和 kcp,默认为 quic。 | No | 47 | | keepTunnelOpen | bool | 是否保持隧道打开,如果开启,会定期检查隧道状态并尝试保持打开。 | No | 48 | | maxRetriesAnHour | int | 每小时尝试打开隧道的次数,默认值为 8。 | No | 49 | | minRetryInterval | int | 重试打开隧道的最小间隔时间,单位: 秒,默认为 90s。 | No | 50 | | fallbackTo | string | 回退到的其他 visitor 名称。 | No | 51 | | fallbackTimeoutMs | int | 连接建立超过多长时间(ms) 后回退到其他 visitor。 | No | 52 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Setup/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "安装" 3 | weight: 2 4 | description: > 5 | 关于如何安装 frp 的说明。 6 | --- 7 | 8 | {{% pageinfo %}} 9 | frp 采用 Go 语言编写,支持跨平台,只需下载适用于您平台的二进制文件即可执行,无需额外依赖。 10 | {{% /pageinfo %}} 11 | 12 | ## 系统需求 13 | 14 | 由于采用 Go 语言编写,因此系统需求与最新的 Go 语言对系统和平台的要求一致,具体请参考 [Golang System requirements](https://golang.org/doc/install#requirements)。 15 | 16 | ## 下载 17 | 18 | 您可以从 GitHub 的 [Release](https://github.com/fatedier/frp/releases) 页面中下载最新版本的客户端和服务器二进制文件。所有文件都打包在一个压缩包中,还包含了一份完整的配置参数说明。 19 | 20 | ## 部署 21 | 22 | 1. 解压下载的压缩包。 23 | 2. 将 `frpc` 复制到内网服务所在的机器上。 24 | 3. 将 `frps` 复制到拥有公网 IP 地址的机器上,并将它们放在任意目录。 25 | 26 | ## 开始使用! 27 | 28 | 1. 编写配置文件,目前支持的文件格式包括 TOML/YAML/JSON,旧的 INI 格式仍然支持,但已经不再推荐。 29 | 2. 使用以下命令启动服务器:`./frps -c ./frps.toml`。 30 | 3. 使用以下命令启动客户端:`./frpc -c ./frpc.toml`。 31 | 4. 如果需要在后台长期运行,建议结合其他工具,如 [systemd](systemd/) 和 `supervisor`。 32 | 33 | 如果您是 Windows 用户,需要在命令提示符中执行相同的命令。 34 | 35 | 有关如何编写配置文件,请参考 [示例](../examples/) 部分中的内容。 36 | 37 | 完整的配置项说明,请参考 [Reference](../reference/) 中的内容。 38 | -------------------------------------------------------------------------------- /content/zh-cn/docs/Setup/systemd.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "使用 systemd" 3 | weight: 1 4 | description: > 5 | 此示例演示如何在 Linux 系统下使用 systemd 来管理 frps 服务,包括启动、停止、配置后台运行和设置开机自启动。 6 | --- 7 | 8 | 在 Linux 系统下,使用 `systemd` 可以方便地控制 frps 服务端的启动、停止、配置后台运行以及开机自启动。 9 | 10 | 以下是具体的操作步骤: 11 | 12 | 1. **安装 systemd** 13 | 14 | 如果您的 Linux 服务器上尚未安装 systemd,可以使用包管理器如 `yum`(适用于 CentOS/RHEL)或 `apt`(适用于 Debian/Ubuntu)来安装它: 15 | 16 | ```bash 17 | # 使用 yum 安装 systemd(CentOS/RHEL) 18 | yum install systemd 19 | 20 | # 使用 apt 安装 systemd(Debian/Ubuntu) 21 | apt install systemd 22 | ``` 23 | 24 | 2. **创建 frps.service 文件** 25 | 26 | 使用文本编辑器 (如 vim) 在 `/etc/systemd/system` 目录下创建一个 `frps.service` 文件,用于配置 frps 服务。 27 | 28 | ```bash 29 | $ sudo vim /etc/systemd/system/frps.service 30 | ``` 31 | 32 | 写入内容 33 | ```ini 34 | [Unit] 35 | # 服务名称,可自定义 36 | Description = frp server 37 | After = network.target syslog.target 38 | Wants = network.target 39 | 40 | [Service] 41 | Type = simple 42 | # 启动frps的命令,需修改为您的frps的安装路径 43 | ExecStart = /path/to/frps -c /path/to/frps.toml 44 | 45 | [Install] 46 | WantedBy = multi-user.target 47 | ``` 48 | 49 | 3. **使用 systemd 命令管理 frps 服务** 50 | 51 | ```bash 52 | # 启动frp 53 | sudo systemctl start frps 54 | # 停止frp 55 | sudo systemctl stop frps 56 | # 重启frp 57 | sudo systemctl restart frps 58 | # 查看frp状态 59 | sudo systemctl status frps 60 | ``` 61 | 62 | 4. **设置 frps 开机自启动** 63 | 64 | ```bash 65 | sudo systemctl enable frps 66 | ``` 67 | 68 | 通过遵循上述步骤,您可以轻松地使用 systemd 来管理 frps 服务,实现启动、停止、自动运行和开机自启动。确保替换路径和配置文件名称以匹配您的实际安装。 69 | -------------------------------------------------------------------------------- /content/zh-cn/docs/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "文档" 3 | menu: 4 | main: 5 | weight: 20 6 | --- 7 | 8 | 了解如何部署、使用 frp。 9 | -------------------------------------------------------------------------------- /content/zh-cn/release/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "版本历史" 3 | linkTitle: "版本历史" 4 | menu: 5 | main: 6 | weight: 30 7 | cascade: 8 | - type: "docs" 9 | --- 10 | 11 | Github [Release](https://github.com/fatedier/frp/releases) 页面查看 12 | -------------------------------------------------------------------------------- /content/zh-cn/search-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | type: "search-index" 3 | url: "index.json" 4 | --- 5 | -------------------------------------------------------------------------------- /content/zh-cn/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Search Results 3 | layout: search 4 | 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofrp/frp-doc 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/google/docsy v0.10.0 // indirect 7 | github.com/google/docsy/dependencies v0.7.2 // indirect 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/FortAwesome/Font-Awesome v0.0.0-20230327165841-0698449d50f2/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= 2 | github.com/FortAwesome/Font-Awesome v0.0.0-20240402185447-c0f460dca7f7/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= 3 | github.com/google/docsy v0.10.0 h1:6tMDacPwAyRWNCfvsn/9qGOZDQ8b0aRzjRZvnZPY5dg= 4 | github.com/google/docsy v0.10.0/go.mod h1:c0nIAqmRTOuJ01F85U/wJPQtc3Zj9N58Kea9bOT2AJc= 5 | github.com/google/docsy/dependencies v0.7.2 h1:+t5ufoADQAj4XneFphz4A+UU0ICAxmNaRHVWtMYXPSI= 6 | github.com/google/docsy/dependencies v0.7.2/go.mod h1:gihhs5gmgeO+wuoay4FwOzob+jYJVyQbNaQOh788lD4= 7 | github.com/twbs/bootstrap v5.2.3+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= 8 | github.com/twbs/bootstrap v5.3.3+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= 9 | -------------------------------------------------------------------------------- /layouts/404.html: -------------------------------------------------------------------------------- 1 | {{ define "main"}} 2 |
3 |
4 |

Not found

5 |

Oops! This page doesn't exist. Try going back to our home page.

6 |
7 |
8 | {{ end }} 9 | -------------------------------------------------------------------------------- /layouts/partials/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ range .AlternativeOutputFormats -}} 4 | 5 | {{ end -}} 6 | 7 | {{ $outputFormat := partial "outputformat.html" . -}} 8 | {{ if and hugo.IsProduction (ne $outputFormat "print") -}} 9 | 10 | {{ else -}} 11 | 12 | {{ end -}} 13 | 14 | {{ partialCached "favicons.html" . }} 15 | 16 | {{- if .IsHome -}} 17 | {{ .Site.Title -}} 18 | {{ else -}} 19 | {{ with .Title }}{{ . }} | {{ end -}} 20 | {{ .Site.Title -}} 21 | {{ end -}} 22 | 23 | 24 | {{ template "_internal/opengraph.html" . -}} 25 | {{ template "_internal/schema.html" . -}} 26 | {{ template "_internal/twitter_cards.html" . -}} 27 | {{ partialCached "head-css.html" . "asdf" -}} 28 | 32 | {{ if .Site.Params.offlineSearch -}} 33 | 37 | {{ end -}} 38 | 39 | 48 | 49 | 50 | {{ if .Site.Params.prism_syntax_highlighting -}} 51 | 52 | {{ end -}} 53 | 54 | {{ template "algolia/head" . -}} 55 | 56 | {{ partial "hooks/head-end.html" . -}} 57 | 58 | {{/* To comply with GDPR, cookie consent scripts places in head-end must execute before Google Analytics is enabled */ -}} 59 | {{ if hugo.IsProduction -}} 60 | {{ $enableGtagForUniversalAnalytics := not .Site.Params.disableGtagForUniversalAnalytics -}} 61 | {{ if (or $enableGtagForUniversalAnalytics (hasPrefix .Site.Config.Services.GoogleAnalytics.ID "G-")) -}} 62 | {{ template "_internal/google_analytics_gtag.html" . -}} 63 | {{ else -}} 64 | {{ template "_internal/google_analytics.html" . -}} 65 | {{ end -}} 66 | {{ end -}} 67 | 68 | {{ define "algolia/head" -}} 69 | 70 | {{ if and .Site.Params.search (isset .Site.Params.search "algolia") -}} 71 | 74 | {{ end -}} 75 | 76 | {{ if ne .Site.Params.algolia_docsearch nil -}} 77 | {{ warnf `Config 'params.algolia_docsearch' is deprecated: use 'params.search.algolia' 78 | For details, see https://www.docsy.dev/docs/adding-content/search/#algolia-docsearch.` -}} 79 | {{ end -}} 80 | 81 | {{ end -}} 82 | -------------------------------------------------------------------------------- /layouts/partials/toc.html: -------------------------------------------------------------------------------- 1 | {{ if not .Params.notoc -}} 2 | {{ with .TableOfContents -}} 3 | {{ if ge (len .) 20 -}} 4 |
{{ . }}
5 | {{ end -}} 6 | {{ end -}} 7 | {{ end -}} 8 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frp-doc", 3 | "version": "0.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "frp-doc", 9 | "version": "0.0.1", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "autoprefixer": "^10.4.13", 13 | "postcss": "^8.4.21", 14 | "postcss-cli": "^9.1.0" 15 | } 16 | }, 17 | "node_modules/@nodelib/fs.scandir": { 18 | "version": "2.1.5", 19 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 20 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 21 | "dev": true, 22 | "dependencies": { 23 | "@nodelib/fs.stat": "2.0.5", 24 | "run-parallel": "^1.1.9" 25 | }, 26 | "engines": { 27 | "node": ">= 8" 28 | } 29 | }, 30 | "node_modules/@nodelib/fs.stat": { 31 | "version": "2.0.5", 32 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 33 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 34 | "dev": true, 35 | "engines": { 36 | "node": ">= 8" 37 | } 38 | }, 39 | "node_modules/@nodelib/fs.walk": { 40 | "version": "1.2.8", 41 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 42 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 43 | "dev": true, 44 | "dependencies": { 45 | "@nodelib/fs.scandir": "2.1.5", 46 | "fastq": "^1.6.0" 47 | }, 48 | "engines": { 49 | "node": ">= 8" 50 | } 51 | }, 52 | "node_modules/ansi-regex": { 53 | "version": "5.0.1", 54 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 55 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 56 | "dev": true, 57 | "engines": { 58 | "node": ">=8" 59 | } 60 | }, 61 | "node_modules/ansi-styles": { 62 | "version": "4.3.0", 63 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 64 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 65 | "dev": true, 66 | "dependencies": { 67 | "color-convert": "^2.0.1" 68 | }, 69 | "engines": { 70 | "node": ">=8" 71 | }, 72 | "funding": { 73 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 74 | } 75 | }, 76 | "node_modules/anymatch": { 77 | "version": "3.1.2", 78 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 79 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 80 | "dev": true, 81 | "dependencies": { 82 | "normalize-path": "^3.0.0", 83 | "picomatch": "^2.0.4" 84 | }, 85 | "engines": { 86 | "node": ">= 8" 87 | } 88 | }, 89 | "node_modules/array-union": { 90 | "version": "3.0.1", 91 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", 92 | "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", 93 | "dev": true, 94 | "engines": { 95 | "node": ">=12" 96 | }, 97 | "funding": { 98 | "url": "https://github.com/sponsors/sindresorhus" 99 | } 100 | }, 101 | "node_modules/autoprefixer": { 102 | "version": "10.4.13", 103 | "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", 104 | "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", 105 | "dev": true, 106 | "funding": [ 107 | { 108 | "type": "opencollective", 109 | "url": "https://opencollective.com/postcss/" 110 | }, 111 | { 112 | "type": "tidelift", 113 | "url": "https://tidelift.com/funding/github/npm/autoprefixer" 114 | } 115 | ], 116 | "dependencies": { 117 | "browserslist": "^4.21.4", 118 | "caniuse-lite": "^1.0.30001426", 119 | "fraction.js": "^4.2.0", 120 | "normalize-range": "^0.1.2", 121 | "picocolors": "^1.0.0", 122 | "postcss-value-parser": "^4.2.0" 123 | }, 124 | "bin": { 125 | "autoprefixer": "bin/autoprefixer" 126 | }, 127 | "engines": { 128 | "node": "^10 || ^12 || >=14" 129 | }, 130 | "peerDependencies": { 131 | "postcss": "^8.1.0" 132 | } 133 | }, 134 | "node_modules/binary-extensions": { 135 | "version": "2.2.0", 136 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 137 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 138 | "dev": true, 139 | "engines": { 140 | "node": ">=8" 141 | } 142 | }, 143 | "node_modules/braces": { 144 | "version": "3.0.2", 145 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 146 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 147 | "dev": true, 148 | "dependencies": { 149 | "fill-range": "^7.0.1" 150 | }, 151 | "engines": { 152 | "node": ">=8" 153 | } 154 | }, 155 | "node_modules/browserslist": { 156 | "version": "4.21.5", 157 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", 158 | "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", 159 | "dev": true, 160 | "funding": [ 161 | { 162 | "type": "opencollective", 163 | "url": "https://opencollective.com/browserslist" 164 | }, 165 | { 166 | "type": "tidelift", 167 | "url": "https://tidelift.com/funding/github/npm/browserslist" 168 | } 169 | ], 170 | "dependencies": { 171 | "caniuse-lite": "^1.0.30001449", 172 | "electron-to-chromium": "^1.4.284", 173 | "node-releases": "^2.0.8", 174 | "update-browserslist-db": "^1.0.10" 175 | }, 176 | "bin": { 177 | "browserslist": "cli.js" 178 | }, 179 | "engines": { 180 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 181 | } 182 | }, 183 | "node_modules/caniuse-lite": { 184 | "version": "1.0.30001451", 185 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz", 186 | "integrity": "sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w==", 187 | "dev": true, 188 | "funding": [ 189 | { 190 | "type": "opencollective", 191 | "url": "https://opencollective.com/browserslist" 192 | }, 193 | { 194 | "type": "tidelift", 195 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 196 | } 197 | ] 198 | }, 199 | "node_modules/chokidar": { 200 | "version": "3.5.3", 201 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 202 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 203 | "dev": true, 204 | "funding": [ 205 | { 206 | "type": "individual", 207 | "url": "https://paulmillr.com/funding/" 208 | } 209 | ], 210 | "dependencies": { 211 | "anymatch": "~3.1.2", 212 | "braces": "~3.0.2", 213 | "glob-parent": "~5.1.2", 214 | "is-binary-path": "~2.1.0", 215 | "is-glob": "~4.0.1", 216 | "normalize-path": "~3.0.0", 217 | "readdirp": "~3.6.0" 218 | }, 219 | "engines": { 220 | "node": ">= 8.10.0" 221 | }, 222 | "optionalDependencies": { 223 | "fsevents": "~2.3.2" 224 | } 225 | }, 226 | "node_modules/cliui": { 227 | "version": "7.0.4", 228 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 229 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 230 | "dev": true, 231 | "dependencies": { 232 | "string-width": "^4.2.0", 233 | "strip-ansi": "^6.0.0", 234 | "wrap-ansi": "^7.0.0" 235 | } 236 | }, 237 | "node_modules/color-convert": { 238 | "version": "2.0.1", 239 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 240 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 241 | "dev": true, 242 | "dependencies": { 243 | "color-name": "~1.1.4" 244 | }, 245 | "engines": { 246 | "node": ">=7.0.0" 247 | } 248 | }, 249 | "node_modules/color-name": { 250 | "version": "1.1.4", 251 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 252 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 253 | "dev": true 254 | }, 255 | "node_modules/dependency-graph": { 256 | "version": "0.11.0", 257 | "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", 258 | "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", 259 | "dev": true, 260 | "engines": { 261 | "node": ">= 0.6.0" 262 | } 263 | }, 264 | "node_modules/dir-glob": { 265 | "version": "3.0.1", 266 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 267 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 268 | "dev": true, 269 | "dependencies": { 270 | "path-type": "^4.0.0" 271 | }, 272 | "engines": { 273 | "node": ">=8" 274 | } 275 | }, 276 | "node_modules/electron-to-chromium": { 277 | "version": "1.4.292", 278 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.292.tgz", 279 | "integrity": "sha512-ESWOSyJy5odDlE8wvh5NNAMORv4r6assPwIPGHEMWrWD0SONXcG/xT+9aD9CQyeRwyYDPo6dJT4Bbeg5uevVQQ==", 280 | "dev": true 281 | }, 282 | "node_modules/emoji-regex": { 283 | "version": "8.0.0", 284 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 285 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 286 | "dev": true 287 | }, 288 | "node_modules/escalade": { 289 | "version": "3.1.1", 290 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 291 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 292 | "dev": true, 293 | "engines": { 294 | "node": ">=6" 295 | } 296 | }, 297 | "node_modules/fast-glob": { 298 | "version": "3.2.11", 299 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", 300 | "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", 301 | "dev": true, 302 | "dependencies": { 303 | "@nodelib/fs.stat": "^2.0.2", 304 | "@nodelib/fs.walk": "^1.2.3", 305 | "glob-parent": "^5.1.2", 306 | "merge2": "^1.3.0", 307 | "micromatch": "^4.0.4" 308 | }, 309 | "engines": { 310 | "node": ">=8.6.0" 311 | } 312 | }, 313 | "node_modules/fastq": { 314 | "version": "1.13.0", 315 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", 316 | "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", 317 | "dev": true, 318 | "dependencies": { 319 | "reusify": "^1.0.4" 320 | } 321 | }, 322 | "node_modules/fill-range": { 323 | "version": "7.0.1", 324 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 325 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 326 | "dev": true, 327 | "dependencies": { 328 | "to-regex-range": "^5.0.1" 329 | }, 330 | "engines": { 331 | "node": ">=8" 332 | } 333 | }, 334 | "node_modules/fraction.js": { 335 | "version": "4.2.0", 336 | "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", 337 | "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", 338 | "dev": true, 339 | "engines": { 340 | "node": "*" 341 | }, 342 | "funding": { 343 | "type": "patreon", 344 | "url": "https://www.patreon.com/infusion" 345 | } 346 | }, 347 | "node_modules/fs-extra": { 348 | "version": "10.0.1", 349 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", 350 | "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", 351 | "dev": true, 352 | "dependencies": { 353 | "graceful-fs": "^4.2.0", 354 | "jsonfile": "^6.0.1", 355 | "universalify": "^2.0.0" 356 | }, 357 | "engines": { 358 | "node": ">=12" 359 | } 360 | }, 361 | "node_modules/fsevents": { 362 | "version": "2.3.2", 363 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 364 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 365 | "dev": true, 366 | "hasInstallScript": true, 367 | "optional": true, 368 | "os": [ 369 | "darwin" 370 | ], 371 | "engines": { 372 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 373 | } 374 | }, 375 | "node_modules/get-caller-file": { 376 | "version": "2.0.5", 377 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 378 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 379 | "dev": true, 380 | "engines": { 381 | "node": "6.* || 8.* || >= 10.*" 382 | } 383 | }, 384 | "node_modules/get-stdin": { 385 | "version": "9.0.0", 386 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", 387 | "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", 388 | "dev": true, 389 | "engines": { 390 | "node": ">=12" 391 | }, 392 | "funding": { 393 | "url": "https://github.com/sponsors/sindresorhus" 394 | } 395 | }, 396 | "node_modules/glob-parent": { 397 | "version": "5.1.2", 398 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 399 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 400 | "dev": true, 401 | "dependencies": { 402 | "is-glob": "^4.0.1" 403 | }, 404 | "engines": { 405 | "node": ">= 6" 406 | } 407 | }, 408 | "node_modules/globby": { 409 | "version": "12.2.0", 410 | "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", 411 | "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", 412 | "dev": true, 413 | "dependencies": { 414 | "array-union": "^3.0.1", 415 | "dir-glob": "^3.0.1", 416 | "fast-glob": "^3.2.7", 417 | "ignore": "^5.1.9", 418 | "merge2": "^1.4.1", 419 | "slash": "^4.0.0" 420 | }, 421 | "engines": { 422 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 423 | }, 424 | "funding": { 425 | "url": "https://github.com/sponsors/sindresorhus" 426 | } 427 | }, 428 | "node_modules/graceful-fs": { 429 | "version": "4.2.9", 430 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", 431 | "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", 432 | "dev": true 433 | }, 434 | "node_modules/ignore": { 435 | "version": "5.2.0", 436 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", 437 | "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", 438 | "dev": true, 439 | "engines": { 440 | "node": ">= 4" 441 | } 442 | }, 443 | "node_modules/is-binary-path": { 444 | "version": "2.1.0", 445 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 446 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 447 | "dev": true, 448 | "dependencies": { 449 | "binary-extensions": "^2.0.0" 450 | }, 451 | "engines": { 452 | "node": ">=8" 453 | } 454 | }, 455 | "node_modules/is-extglob": { 456 | "version": "2.1.1", 457 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 458 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 459 | "dev": true, 460 | "engines": { 461 | "node": ">=0.10.0" 462 | } 463 | }, 464 | "node_modules/is-fullwidth-code-point": { 465 | "version": "3.0.0", 466 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 467 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 468 | "dev": true, 469 | "engines": { 470 | "node": ">=8" 471 | } 472 | }, 473 | "node_modules/is-glob": { 474 | "version": "4.0.3", 475 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 476 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 477 | "dev": true, 478 | "dependencies": { 479 | "is-extglob": "^2.1.1" 480 | }, 481 | "engines": { 482 | "node": ">=0.10.0" 483 | } 484 | }, 485 | "node_modules/is-number": { 486 | "version": "7.0.0", 487 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 488 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 489 | "dev": true, 490 | "engines": { 491 | "node": ">=0.12.0" 492 | } 493 | }, 494 | "node_modules/jsonfile": { 495 | "version": "6.1.0", 496 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 497 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 498 | "dev": true, 499 | "dependencies": { 500 | "universalify": "^2.0.0" 501 | }, 502 | "optionalDependencies": { 503 | "graceful-fs": "^4.1.6" 504 | } 505 | }, 506 | "node_modules/lilconfig": { 507 | "version": "2.0.4", 508 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", 509 | "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", 510 | "dev": true, 511 | "engines": { 512 | "node": ">=10" 513 | } 514 | }, 515 | "node_modules/merge2": { 516 | "version": "1.4.1", 517 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 518 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 519 | "dev": true, 520 | "engines": { 521 | "node": ">= 8" 522 | } 523 | }, 524 | "node_modules/micromatch": { 525 | "version": "4.0.4", 526 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", 527 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", 528 | "dev": true, 529 | "dependencies": { 530 | "braces": "^3.0.1", 531 | "picomatch": "^2.2.3" 532 | }, 533 | "engines": { 534 | "node": ">=8.6" 535 | } 536 | }, 537 | "node_modules/nanoid": { 538 | "version": "3.3.4", 539 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", 540 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", 541 | "dev": true, 542 | "bin": { 543 | "nanoid": "bin/nanoid.cjs" 544 | }, 545 | "engines": { 546 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 547 | } 548 | }, 549 | "node_modules/node-releases": { 550 | "version": "2.0.10", 551 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", 552 | "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", 553 | "dev": true 554 | }, 555 | "node_modules/normalize-path": { 556 | "version": "3.0.0", 557 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 558 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 559 | "dev": true, 560 | "engines": { 561 | "node": ">=0.10.0" 562 | } 563 | }, 564 | "node_modules/normalize-range": { 565 | "version": "0.1.2", 566 | "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", 567 | "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", 568 | "dev": true, 569 | "engines": { 570 | "node": ">=0.10.0" 571 | } 572 | }, 573 | "node_modules/path-type": { 574 | "version": "4.0.0", 575 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 576 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 577 | "dev": true, 578 | "engines": { 579 | "node": ">=8" 580 | } 581 | }, 582 | "node_modules/picocolors": { 583 | "version": "1.0.0", 584 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 585 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 586 | "dev": true 587 | }, 588 | "node_modules/picomatch": { 589 | "version": "2.3.1", 590 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 591 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 592 | "dev": true, 593 | "engines": { 594 | "node": ">=8.6" 595 | }, 596 | "funding": { 597 | "url": "https://github.com/sponsors/jonschlinkert" 598 | } 599 | }, 600 | "node_modules/postcss": { 601 | "version": "8.4.21", 602 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", 603 | "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", 604 | "dev": true, 605 | "funding": [ 606 | { 607 | "type": "opencollective", 608 | "url": "https://opencollective.com/postcss/" 609 | }, 610 | { 611 | "type": "tidelift", 612 | "url": "https://tidelift.com/funding/github/npm/postcss" 613 | } 614 | ], 615 | "dependencies": { 616 | "nanoid": "^3.3.4", 617 | "picocolors": "^1.0.0", 618 | "source-map-js": "^1.0.2" 619 | }, 620 | "engines": { 621 | "node": "^10 || ^12 || >=14" 622 | } 623 | }, 624 | "node_modules/postcss-cli": { 625 | "version": "9.1.0", 626 | "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-9.1.0.tgz", 627 | "integrity": "sha512-zvDN2ADbWfza42sAnj+O2uUWyL0eRL1V+6giM2vi4SqTR3gTYy8XzcpfwccayF2szcUif0HMmXiEaDv9iEhcpw==", 628 | "dev": true, 629 | "dependencies": { 630 | "chokidar": "^3.3.0", 631 | "dependency-graph": "^0.11.0", 632 | "fs-extra": "^10.0.0", 633 | "get-stdin": "^9.0.0", 634 | "globby": "^12.0.0", 635 | "picocolors": "^1.0.0", 636 | "postcss-load-config": "^3.0.0", 637 | "postcss-reporter": "^7.0.0", 638 | "pretty-hrtime": "^1.0.3", 639 | "read-cache": "^1.0.0", 640 | "slash": "^4.0.0", 641 | "yargs": "^17.0.0" 642 | }, 643 | "bin": { 644 | "postcss": "index.js" 645 | }, 646 | "engines": { 647 | "node": ">=12" 648 | }, 649 | "peerDependencies": { 650 | "postcss": "^8.0.0" 651 | } 652 | }, 653 | "node_modules/postcss-load-config": { 654 | "version": "3.1.3", 655 | "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.3.tgz", 656 | "integrity": "sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw==", 657 | "dev": true, 658 | "dependencies": { 659 | "lilconfig": "^2.0.4", 660 | "yaml": "^1.10.2" 661 | }, 662 | "engines": { 663 | "node": ">= 10" 664 | }, 665 | "funding": { 666 | "type": "opencollective", 667 | "url": "https://opencollective.com/postcss/" 668 | }, 669 | "peerDependencies": { 670 | "ts-node": ">=9.0.0" 671 | }, 672 | "peerDependenciesMeta": { 673 | "ts-node": { 674 | "optional": true 675 | } 676 | } 677 | }, 678 | "node_modules/postcss-reporter": { 679 | "version": "7.0.5", 680 | "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.5.tgz", 681 | "integrity": "sha512-glWg7VZBilooZGOFPhN9msJ3FQs19Hie7l5a/eE6WglzYqVeH3ong3ShFcp9kDWJT1g2Y/wd59cocf9XxBtkWA==", 682 | "dev": true, 683 | "dependencies": { 684 | "picocolors": "^1.0.0", 685 | "thenby": "^1.3.4" 686 | }, 687 | "engines": { 688 | "node": ">=10" 689 | }, 690 | "funding": { 691 | "type": "opencollective", 692 | "url": "https://opencollective.com/postcss/" 693 | }, 694 | "peerDependencies": { 695 | "postcss": "^8.1.0" 696 | } 697 | }, 698 | "node_modules/postcss-value-parser": { 699 | "version": "4.2.0", 700 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", 701 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", 702 | "dev": true 703 | }, 704 | "node_modules/pretty-hrtime": { 705 | "version": "1.0.3", 706 | "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", 707 | "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", 708 | "dev": true, 709 | "engines": { 710 | "node": ">= 0.8" 711 | } 712 | }, 713 | "node_modules/queue-microtask": { 714 | "version": "1.2.3", 715 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 716 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 717 | "dev": true, 718 | "funding": [ 719 | { 720 | "type": "github", 721 | "url": "https://github.com/sponsors/feross" 722 | }, 723 | { 724 | "type": "patreon", 725 | "url": "https://www.patreon.com/feross" 726 | }, 727 | { 728 | "type": "consulting", 729 | "url": "https://feross.org/support" 730 | } 731 | ] 732 | }, 733 | "node_modules/read-cache": { 734 | "version": "1.0.0", 735 | "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", 736 | "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", 737 | "dev": true, 738 | "dependencies": { 739 | "pify": "^2.3.0" 740 | } 741 | }, 742 | "node_modules/read-cache/node_modules/pify": { 743 | "version": "2.3.0", 744 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 745 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 746 | "dev": true, 747 | "engines": { 748 | "node": ">=0.10.0" 749 | } 750 | }, 751 | "node_modules/readdirp": { 752 | "version": "3.6.0", 753 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 754 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 755 | "dev": true, 756 | "dependencies": { 757 | "picomatch": "^2.2.1" 758 | }, 759 | "engines": { 760 | "node": ">=8.10.0" 761 | } 762 | }, 763 | "node_modules/require-directory": { 764 | "version": "2.1.1", 765 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 766 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 767 | "dev": true, 768 | "engines": { 769 | "node": ">=0.10.0" 770 | } 771 | }, 772 | "node_modules/reusify": { 773 | "version": "1.0.4", 774 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 775 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 776 | "dev": true, 777 | "engines": { 778 | "iojs": ">=1.0.0", 779 | "node": ">=0.10.0" 780 | } 781 | }, 782 | "node_modules/run-parallel": { 783 | "version": "1.2.0", 784 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 785 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 786 | "dev": true, 787 | "funding": [ 788 | { 789 | "type": "github", 790 | "url": "https://github.com/sponsors/feross" 791 | }, 792 | { 793 | "type": "patreon", 794 | "url": "https://www.patreon.com/feross" 795 | }, 796 | { 797 | "type": "consulting", 798 | "url": "https://feross.org/support" 799 | } 800 | ], 801 | "dependencies": { 802 | "queue-microtask": "^1.2.2" 803 | } 804 | }, 805 | "node_modules/slash": { 806 | "version": "4.0.0", 807 | "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", 808 | "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", 809 | "dev": true, 810 | "engines": { 811 | "node": ">=12" 812 | }, 813 | "funding": { 814 | "url": "https://github.com/sponsors/sindresorhus" 815 | } 816 | }, 817 | "node_modules/source-map-js": { 818 | "version": "1.0.2", 819 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 820 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 821 | "dev": true, 822 | "engines": { 823 | "node": ">=0.10.0" 824 | } 825 | }, 826 | "node_modules/string-width": { 827 | "version": "4.2.3", 828 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 829 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 830 | "dev": true, 831 | "dependencies": { 832 | "emoji-regex": "^8.0.0", 833 | "is-fullwidth-code-point": "^3.0.0", 834 | "strip-ansi": "^6.0.1" 835 | }, 836 | "engines": { 837 | "node": ">=8" 838 | } 839 | }, 840 | "node_modules/strip-ansi": { 841 | "version": "6.0.1", 842 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 843 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 844 | "dev": true, 845 | "dependencies": { 846 | "ansi-regex": "^5.0.1" 847 | }, 848 | "engines": { 849 | "node": ">=8" 850 | } 851 | }, 852 | "node_modules/thenby": { 853 | "version": "1.3.4", 854 | "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", 855 | "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", 856 | "dev": true 857 | }, 858 | "node_modules/to-regex-range": { 859 | "version": "5.0.1", 860 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 861 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 862 | "dev": true, 863 | "dependencies": { 864 | "is-number": "^7.0.0" 865 | }, 866 | "engines": { 867 | "node": ">=8.0" 868 | } 869 | }, 870 | "node_modules/universalify": { 871 | "version": "2.0.0", 872 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 873 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", 874 | "dev": true, 875 | "engines": { 876 | "node": ">= 10.0.0" 877 | } 878 | }, 879 | "node_modules/update-browserslist-db": { 880 | "version": "1.0.10", 881 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", 882 | "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", 883 | "dev": true, 884 | "funding": [ 885 | { 886 | "type": "opencollective", 887 | "url": "https://opencollective.com/browserslist" 888 | }, 889 | { 890 | "type": "tidelift", 891 | "url": "https://tidelift.com/funding/github/npm/browserslist" 892 | } 893 | ], 894 | "dependencies": { 895 | "escalade": "^3.1.1", 896 | "picocolors": "^1.0.0" 897 | }, 898 | "bin": { 899 | "browserslist-lint": "cli.js" 900 | }, 901 | "peerDependencies": { 902 | "browserslist": ">= 4.21.0" 903 | } 904 | }, 905 | "node_modules/wrap-ansi": { 906 | "version": "7.0.0", 907 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 908 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 909 | "dev": true, 910 | "dependencies": { 911 | "ansi-styles": "^4.0.0", 912 | "string-width": "^4.1.0", 913 | "strip-ansi": "^6.0.0" 914 | }, 915 | "engines": { 916 | "node": ">=10" 917 | }, 918 | "funding": { 919 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 920 | } 921 | }, 922 | "node_modules/y18n": { 923 | "version": "5.0.8", 924 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 925 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 926 | "dev": true, 927 | "engines": { 928 | "node": ">=10" 929 | } 930 | }, 931 | "node_modules/yaml": { 932 | "version": "1.10.2", 933 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", 934 | "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", 935 | "dev": true, 936 | "engines": { 937 | "node": ">= 6" 938 | } 939 | }, 940 | "node_modules/yargs": { 941 | "version": "17.3.1", 942 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", 943 | "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", 944 | "dev": true, 945 | "dependencies": { 946 | "cliui": "^7.0.2", 947 | "escalade": "^3.1.1", 948 | "get-caller-file": "^2.0.5", 949 | "require-directory": "^2.1.1", 950 | "string-width": "^4.2.3", 951 | "y18n": "^5.0.5", 952 | "yargs-parser": "^21.0.0" 953 | }, 954 | "engines": { 955 | "node": ">=12" 956 | } 957 | }, 958 | "node_modules/yargs-parser": { 959 | "version": "21.0.1", 960 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", 961 | "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", 962 | "dev": true, 963 | "engines": { 964 | "node": ">=12" 965 | } 966 | } 967 | }, 968 | "dependencies": { 969 | "@nodelib/fs.scandir": { 970 | "version": "2.1.5", 971 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 972 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 973 | "dev": true, 974 | "requires": { 975 | "@nodelib/fs.stat": "2.0.5", 976 | "run-parallel": "^1.1.9" 977 | } 978 | }, 979 | "@nodelib/fs.stat": { 980 | "version": "2.0.5", 981 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 982 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 983 | "dev": true 984 | }, 985 | "@nodelib/fs.walk": { 986 | "version": "1.2.8", 987 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 988 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 989 | "dev": true, 990 | "requires": { 991 | "@nodelib/fs.scandir": "2.1.5", 992 | "fastq": "^1.6.0" 993 | } 994 | }, 995 | "ansi-regex": { 996 | "version": "5.0.1", 997 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 998 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 999 | "dev": true 1000 | }, 1001 | "ansi-styles": { 1002 | "version": "4.3.0", 1003 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1004 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1005 | "dev": true, 1006 | "requires": { 1007 | "color-convert": "^2.0.1" 1008 | } 1009 | }, 1010 | "anymatch": { 1011 | "version": "3.1.2", 1012 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 1013 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 1014 | "dev": true, 1015 | "requires": { 1016 | "normalize-path": "^3.0.0", 1017 | "picomatch": "^2.0.4" 1018 | } 1019 | }, 1020 | "array-union": { 1021 | "version": "3.0.1", 1022 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", 1023 | "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", 1024 | "dev": true 1025 | }, 1026 | "autoprefixer": { 1027 | "version": "10.4.13", 1028 | "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", 1029 | "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", 1030 | "dev": true, 1031 | "requires": { 1032 | "browserslist": "^4.21.4", 1033 | "caniuse-lite": "^1.0.30001426", 1034 | "fraction.js": "^4.2.0", 1035 | "normalize-range": "^0.1.2", 1036 | "picocolors": "^1.0.0", 1037 | "postcss-value-parser": "^4.2.0" 1038 | } 1039 | }, 1040 | "binary-extensions": { 1041 | "version": "2.2.0", 1042 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 1043 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 1044 | "dev": true 1045 | }, 1046 | "braces": { 1047 | "version": "3.0.2", 1048 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 1049 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 1050 | "dev": true, 1051 | "requires": { 1052 | "fill-range": "^7.0.1" 1053 | } 1054 | }, 1055 | "browserslist": { 1056 | "version": "4.21.5", 1057 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", 1058 | "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", 1059 | "dev": true, 1060 | "requires": { 1061 | "caniuse-lite": "^1.0.30001449", 1062 | "electron-to-chromium": "^1.4.284", 1063 | "node-releases": "^2.0.8", 1064 | "update-browserslist-db": "^1.0.10" 1065 | } 1066 | }, 1067 | "caniuse-lite": { 1068 | "version": "1.0.30001451", 1069 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz", 1070 | "integrity": "sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w==", 1071 | "dev": true 1072 | }, 1073 | "chokidar": { 1074 | "version": "3.5.3", 1075 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 1076 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 1077 | "dev": true, 1078 | "requires": { 1079 | "anymatch": "~3.1.2", 1080 | "braces": "~3.0.2", 1081 | "fsevents": "~2.3.2", 1082 | "glob-parent": "~5.1.2", 1083 | "is-binary-path": "~2.1.0", 1084 | "is-glob": "~4.0.1", 1085 | "normalize-path": "~3.0.0", 1086 | "readdirp": "~3.6.0" 1087 | } 1088 | }, 1089 | "cliui": { 1090 | "version": "7.0.4", 1091 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 1092 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 1093 | "dev": true, 1094 | "requires": { 1095 | "string-width": "^4.2.0", 1096 | "strip-ansi": "^6.0.0", 1097 | "wrap-ansi": "^7.0.0" 1098 | } 1099 | }, 1100 | "color-convert": { 1101 | "version": "2.0.1", 1102 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1103 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1104 | "dev": true, 1105 | "requires": { 1106 | "color-name": "~1.1.4" 1107 | } 1108 | }, 1109 | "color-name": { 1110 | "version": "1.1.4", 1111 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1112 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1113 | "dev": true 1114 | }, 1115 | "dependency-graph": { 1116 | "version": "0.11.0", 1117 | "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", 1118 | "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", 1119 | "dev": true 1120 | }, 1121 | "dir-glob": { 1122 | "version": "3.0.1", 1123 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 1124 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 1125 | "dev": true, 1126 | "requires": { 1127 | "path-type": "^4.0.0" 1128 | } 1129 | }, 1130 | "electron-to-chromium": { 1131 | "version": "1.4.292", 1132 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.292.tgz", 1133 | "integrity": "sha512-ESWOSyJy5odDlE8wvh5NNAMORv4r6assPwIPGHEMWrWD0SONXcG/xT+9aD9CQyeRwyYDPo6dJT4Bbeg5uevVQQ==", 1134 | "dev": true 1135 | }, 1136 | "emoji-regex": { 1137 | "version": "8.0.0", 1138 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1139 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1140 | "dev": true 1141 | }, 1142 | "escalade": { 1143 | "version": "3.1.1", 1144 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 1145 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 1146 | "dev": true 1147 | }, 1148 | "fast-glob": { 1149 | "version": "3.2.11", 1150 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", 1151 | "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", 1152 | "dev": true, 1153 | "requires": { 1154 | "@nodelib/fs.stat": "^2.0.2", 1155 | "@nodelib/fs.walk": "^1.2.3", 1156 | "glob-parent": "^5.1.2", 1157 | "merge2": "^1.3.0", 1158 | "micromatch": "^4.0.4" 1159 | } 1160 | }, 1161 | "fastq": { 1162 | "version": "1.13.0", 1163 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", 1164 | "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", 1165 | "dev": true, 1166 | "requires": { 1167 | "reusify": "^1.0.4" 1168 | } 1169 | }, 1170 | "fill-range": { 1171 | "version": "7.0.1", 1172 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 1173 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 1174 | "dev": true, 1175 | "requires": { 1176 | "to-regex-range": "^5.0.1" 1177 | } 1178 | }, 1179 | "fraction.js": { 1180 | "version": "4.2.0", 1181 | "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", 1182 | "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", 1183 | "dev": true 1184 | }, 1185 | "fs-extra": { 1186 | "version": "10.0.1", 1187 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", 1188 | "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", 1189 | "dev": true, 1190 | "requires": { 1191 | "graceful-fs": "^4.2.0", 1192 | "jsonfile": "^6.0.1", 1193 | "universalify": "^2.0.0" 1194 | } 1195 | }, 1196 | "fsevents": { 1197 | "version": "2.3.2", 1198 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 1199 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 1200 | "dev": true, 1201 | "optional": true 1202 | }, 1203 | "get-caller-file": { 1204 | "version": "2.0.5", 1205 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1206 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 1207 | "dev": true 1208 | }, 1209 | "get-stdin": { 1210 | "version": "9.0.0", 1211 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", 1212 | "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", 1213 | "dev": true 1214 | }, 1215 | "glob-parent": { 1216 | "version": "5.1.2", 1217 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1218 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1219 | "dev": true, 1220 | "requires": { 1221 | "is-glob": "^4.0.1" 1222 | } 1223 | }, 1224 | "globby": { 1225 | "version": "12.2.0", 1226 | "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", 1227 | "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", 1228 | "dev": true, 1229 | "requires": { 1230 | "array-union": "^3.0.1", 1231 | "dir-glob": "^3.0.1", 1232 | "fast-glob": "^3.2.7", 1233 | "ignore": "^5.1.9", 1234 | "merge2": "^1.4.1", 1235 | "slash": "^4.0.0" 1236 | } 1237 | }, 1238 | "graceful-fs": { 1239 | "version": "4.2.9", 1240 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", 1241 | "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", 1242 | "dev": true 1243 | }, 1244 | "ignore": { 1245 | "version": "5.2.0", 1246 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", 1247 | "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", 1248 | "dev": true 1249 | }, 1250 | "is-binary-path": { 1251 | "version": "2.1.0", 1252 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1253 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1254 | "dev": true, 1255 | "requires": { 1256 | "binary-extensions": "^2.0.0" 1257 | } 1258 | }, 1259 | "is-extglob": { 1260 | "version": "2.1.1", 1261 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1262 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1263 | "dev": true 1264 | }, 1265 | "is-fullwidth-code-point": { 1266 | "version": "3.0.0", 1267 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1268 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1269 | "dev": true 1270 | }, 1271 | "is-glob": { 1272 | "version": "4.0.3", 1273 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1274 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1275 | "dev": true, 1276 | "requires": { 1277 | "is-extglob": "^2.1.1" 1278 | } 1279 | }, 1280 | "is-number": { 1281 | "version": "7.0.0", 1282 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1283 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1284 | "dev": true 1285 | }, 1286 | "jsonfile": { 1287 | "version": "6.1.0", 1288 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 1289 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 1290 | "dev": true, 1291 | "requires": { 1292 | "graceful-fs": "^4.1.6", 1293 | "universalify": "^2.0.0" 1294 | } 1295 | }, 1296 | "lilconfig": { 1297 | "version": "2.0.4", 1298 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", 1299 | "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", 1300 | "dev": true 1301 | }, 1302 | "merge2": { 1303 | "version": "1.4.1", 1304 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1305 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1306 | "dev": true 1307 | }, 1308 | "micromatch": { 1309 | "version": "4.0.4", 1310 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", 1311 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", 1312 | "dev": true, 1313 | "requires": { 1314 | "braces": "^3.0.1", 1315 | "picomatch": "^2.2.3" 1316 | } 1317 | }, 1318 | "nanoid": { 1319 | "version": "3.3.4", 1320 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", 1321 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", 1322 | "dev": true 1323 | }, 1324 | "node-releases": { 1325 | "version": "2.0.10", 1326 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", 1327 | "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", 1328 | "dev": true 1329 | }, 1330 | "normalize-path": { 1331 | "version": "3.0.0", 1332 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1333 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1334 | "dev": true 1335 | }, 1336 | "normalize-range": { 1337 | "version": "0.1.2", 1338 | "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", 1339 | "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", 1340 | "dev": true 1341 | }, 1342 | "path-type": { 1343 | "version": "4.0.0", 1344 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 1345 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 1346 | "dev": true 1347 | }, 1348 | "picocolors": { 1349 | "version": "1.0.0", 1350 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 1351 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 1352 | "dev": true 1353 | }, 1354 | "picomatch": { 1355 | "version": "2.3.1", 1356 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1357 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1358 | "dev": true 1359 | }, 1360 | "postcss": { 1361 | "version": "8.4.21", 1362 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", 1363 | "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", 1364 | "dev": true, 1365 | "requires": { 1366 | "nanoid": "^3.3.4", 1367 | "picocolors": "^1.0.0", 1368 | "source-map-js": "^1.0.2" 1369 | } 1370 | }, 1371 | "postcss-cli": { 1372 | "version": "9.1.0", 1373 | "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-9.1.0.tgz", 1374 | "integrity": "sha512-zvDN2ADbWfza42sAnj+O2uUWyL0eRL1V+6giM2vi4SqTR3gTYy8XzcpfwccayF2szcUif0HMmXiEaDv9iEhcpw==", 1375 | "dev": true, 1376 | "requires": { 1377 | "chokidar": "^3.3.0", 1378 | "dependency-graph": "^0.11.0", 1379 | "fs-extra": "^10.0.0", 1380 | "get-stdin": "^9.0.0", 1381 | "globby": "^12.0.0", 1382 | "picocolors": "^1.0.0", 1383 | "postcss-load-config": "^3.0.0", 1384 | "postcss-reporter": "^7.0.0", 1385 | "pretty-hrtime": "^1.0.3", 1386 | "read-cache": "^1.0.0", 1387 | "slash": "^4.0.0", 1388 | "yargs": "^17.0.0" 1389 | } 1390 | }, 1391 | "postcss-load-config": { 1392 | "version": "3.1.3", 1393 | "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.3.tgz", 1394 | "integrity": "sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw==", 1395 | "dev": true, 1396 | "requires": { 1397 | "lilconfig": "^2.0.4", 1398 | "yaml": "^1.10.2" 1399 | } 1400 | }, 1401 | "postcss-reporter": { 1402 | "version": "7.0.5", 1403 | "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.0.5.tgz", 1404 | "integrity": "sha512-glWg7VZBilooZGOFPhN9msJ3FQs19Hie7l5a/eE6WglzYqVeH3ong3ShFcp9kDWJT1g2Y/wd59cocf9XxBtkWA==", 1405 | "dev": true, 1406 | "requires": { 1407 | "picocolors": "^1.0.0", 1408 | "thenby": "^1.3.4" 1409 | } 1410 | }, 1411 | "postcss-value-parser": { 1412 | "version": "4.2.0", 1413 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", 1414 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", 1415 | "dev": true 1416 | }, 1417 | "pretty-hrtime": { 1418 | "version": "1.0.3", 1419 | "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", 1420 | "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", 1421 | "dev": true 1422 | }, 1423 | "queue-microtask": { 1424 | "version": "1.2.3", 1425 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1426 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1427 | "dev": true 1428 | }, 1429 | "read-cache": { 1430 | "version": "1.0.0", 1431 | "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", 1432 | "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", 1433 | "dev": true, 1434 | "requires": { 1435 | "pify": "^2.3.0" 1436 | }, 1437 | "dependencies": { 1438 | "pify": { 1439 | "version": "2.3.0", 1440 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1441 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 1442 | "dev": true 1443 | } 1444 | } 1445 | }, 1446 | "readdirp": { 1447 | "version": "3.6.0", 1448 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1449 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1450 | "dev": true, 1451 | "requires": { 1452 | "picomatch": "^2.2.1" 1453 | } 1454 | }, 1455 | "require-directory": { 1456 | "version": "2.1.1", 1457 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1458 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1459 | "dev": true 1460 | }, 1461 | "reusify": { 1462 | "version": "1.0.4", 1463 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1464 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1465 | "dev": true 1466 | }, 1467 | "run-parallel": { 1468 | "version": "1.2.0", 1469 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1470 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1471 | "dev": true, 1472 | "requires": { 1473 | "queue-microtask": "^1.2.2" 1474 | } 1475 | }, 1476 | "slash": { 1477 | "version": "4.0.0", 1478 | "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", 1479 | "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", 1480 | "dev": true 1481 | }, 1482 | "source-map-js": { 1483 | "version": "1.0.2", 1484 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 1485 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 1486 | "dev": true 1487 | }, 1488 | "string-width": { 1489 | "version": "4.2.3", 1490 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1491 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1492 | "dev": true, 1493 | "requires": { 1494 | "emoji-regex": "^8.0.0", 1495 | "is-fullwidth-code-point": "^3.0.0", 1496 | "strip-ansi": "^6.0.1" 1497 | } 1498 | }, 1499 | "strip-ansi": { 1500 | "version": "6.0.1", 1501 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1502 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1503 | "dev": true, 1504 | "requires": { 1505 | "ansi-regex": "^5.0.1" 1506 | } 1507 | }, 1508 | "thenby": { 1509 | "version": "1.3.4", 1510 | "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", 1511 | "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", 1512 | "dev": true 1513 | }, 1514 | "to-regex-range": { 1515 | "version": "5.0.1", 1516 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1517 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1518 | "dev": true, 1519 | "requires": { 1520 | "is-number": "^7.0.0" 1521 | } 1522 | }, 1523 | "universalify": { 1524 | "version": "2.0.0", 1525 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 1526 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", 1527 | "dev": true 1528 | }, 1529 | "update-browserslist-db": { 1530 | "version": "1.0.10", 1531 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", 1532 | "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", 1533 | "dev": true, 1534 | "requires": { 1535 | "escalade": "^3.1.1", 1536 | "picocolors": "^1.0.0" 1537 | } 1538 | }, 1539 | "wrap-ansi": { 1540 | "version": "7.0.0", 1541 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1542 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1543 | "dev": true, 1544 | "requires": { 1545 | "ansi-styles": "^4.0.0", 1546 | "string-width": "^4.1.0", 1547 | "strip-ansi": "^6.0.0" 1548 | } 1549 | }, 1550 | "y18n": { 1551 | "version": "5.0.8", 1552 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1553 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 1554 | "dev": true 1555 | }, 1556 | "yaml": { 1557 | "version": "1.10.2", 1558 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", 1559 | "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", 1560 | "dev": true 1561 | }, 1562 | "yargs": { 1563 | "version": "17.3.1", 1564 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", 1565 | "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", 1566 | "dev": true, 1567 | "requires": { 1568 | "cliui": "^7.0.2", 1569 | "escalade": "^3.1.1", 1570 | "get-caller-file": "^2.0.5", 1571 | "require-directory": "^2.1.1", 1572 | "string-width": "^4.2.3", 1573 | "y18n": "^5.0.5", 1574 | "yargs-parser": "^21.0.0" 1575 | } 1576 | }, 1577 | "yargs-parser": { 1578 | "version": "21.0.1", 1579 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", 1580 | "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", 1581 | "dev": true 1582 | } 1583 | } 1584 | } 1585 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frp-doc", 3 | "version": "0.0.1", 4 | "description": "frp documentation.", 5 | "main": "none.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/gofrp/frp-doc.git" 12 | }, 13 | "author": "", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/gofrp/frp-doc/issues" 17 | }, 18 | "homepage": "https://github.com/gofrp/frp-doc#readme", 19 | "devDependencies": { 20 | "autoprefixer": "^10.4.13", 21 | "postcss": "^8.4.21", 22 | "postcss-cli": "^9.1.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /static/favicons/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /static/favicons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /static/favicons/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /static/favicons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /static/favicons/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /static/favicons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /static/favicons/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /static/favicons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /static/favicons/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /static/favicons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/apple-touch-icon.png -------------------------------------------------------------------------------- /static/favicons/favicon-160x160.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/favicon-160x160.png -------------------------------------------------------------------------------- /static/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /static/favicons/favicon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/favicon-196x196.png -------------------------------------------------------------------------------- /static/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /static/favicons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/favicon-96x96.png -------------------------------------------------------------------------------- /static/favicons/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/mstile-144x144.png -------------------------------------------------------------------------------- /static/favicons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/mstile-150x150.png -------------------------------------------------------------------------------- /static/favicons/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/mstile-310x310.png -------------------------------------------------------------------------------- /static/favicons/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofrp/frp-doc/a5095f0b22f04a49e296bb3a0940880910c175e7/static/favicons/mstile-70x70.png -------------------------------------------------------------------------------- /static/js/lunr-2.3.9.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 3 | * Copyright (C) 2020 Oliver Nightingale 4 | * @license MIT 5 | */ 6 | !function(){var e=function(t){var r=new e.Builder;return r.pipeline.add(e.trimmer,e.stopWordFilter,e.stemmer),r.searchPipeline.add(e.stemmer),t.call(r,r),r.build()};e.version="2.3.9",e.utils={},e.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),e.utils.asString=function(e){return void 0===e||null===e?"":e.toString()},e.utils.clone=function(e){if(null===e||void 0===e)return e;for(var t=Object.create(null),r=Object.keys(e),i=0;i0){var c=e.utils.clone(r)||{};c.position=[a,l],c.index=s.length,s.push(new e.Token(i.slice(a,o),c))}a=o+1}}return s},e.tokenizer.separator=/[\s\-]+/,e.Pipeline=function(){this._stack=[]},e.Pipeline.registeredFunctions=Object.create(null),e.Pipeline.registerFunction=function(t,r){r in this.registeredFunctions&&e.utils.warn("Overwriting existing registered function: "+r),t.label=r,e.Pipeline.registeredFunctions[t.label]=t},e.Pipeline.warnIfFunctionNotRegistered=function(t){var r=t.label&&t.label in this.registeredFunctions;r||e.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",t)},e.Pipeline.load=function(t){var r=new e.Pipeline;return t.forEach(function(t){var i=e.Pipeline.registeredFunctions[t];if(!i)throw new Error("Cannot load unregistered function: "+t);r.add(i)}),r},e.Pipeline.prototype.add=function(){var t=Array.prototype.slice.call(arguments);t.forEach(function(t){e.Pipeline.warnIfFunctionNotRegistered(t),this._stack.push(t)},this)},e.Pipeline.prototype.after=function(t,r){e.Pipeline.warnIfFunctionNotRegistered(r);var i=this._stack.indexOf(t);if(i==-1)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,r)},e.Pipeline.prototype.before=function(t,r){e.Pipeline.warnIfFunctionNotRegistered(r);var i=this._stack.indexOf(t);if(i==-1)throw new Error("Cannot find existingFn");this._stack.splice(i,0,r)},e.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);t!=-1&&this._stack.splice(t,1)},e.Pipeline.prototype.run=function(e){for(var t=this._stack.length,r=0;r1&&(se&&(r=n),s!=e);)i=r-t,n=t+Math.floor(i/2),s=this.elements[2*n];return s==e?2*n:s>e?2*n:sa?l+=2:o==a&&(t+=r[u+1]*i[l+1],u+=2,l+=2);return t},e.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},e.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,r=0;t0){var o,a=s.str.charAt(0);a in s.node.edges?o=s.node.edges[a]:(o=new e.TokenSet,s.node.edges[a]=o),1==s.str.length&&(o["final"]=!0),n.push({node:o,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(0!=s.editsRemaining){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new e.TokenSet;s.node.edges["*"]=u}if(0==s.str.length&&(u["final"]=!0),n.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&n.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),1==s.str.length&&(s.node["final"]=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new e.TokenSet;s.node.edges["*"]=l}1==s.str.length&&(l["final"]=!0),n.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var c,h=s.str.charAt(0),d=s.str.charAt(1);d in s.node.edges?c=s.node.edges[d]:(c=new e.TokenSet,s.node.edges[d]=c),1==s.str.length&&(c["final"]=!0),n.push({node:c,editsRemaining:s.editsRemaining-1,str:h+s.str.slice(2)})}}}return i},e.TokenSet.fromString=function(t){for(var r=new e.TokenSet,i=r,n=0,s=t.length;n=e;t--){var r=this.uncheckedNodes[t],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r["char"]]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}},e.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},e.Index.prototype.search=function(t){return this.query(function(r){var i=new e.QueryParser(t,r);i.parse()})},e.Index.prototype.query=function(t){for(var r=new e.Query(this.fields),i=Object.create(null),n=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u1?this._b=1:this._b=e},e.Builder.prototype.k1=function(e){this._k1=e},e.Builder.prototype.add=function(t,r){var i=t[this._ref],n=Object.keys(this._fields);this._documents[i]=r||{},this.documentCount+=1;for(var s=0;s=this.length)return e.QueryLexer.EOS;var t=this.str.charAt(this.pos);return this.pos+=1,t},e.QueryLexer.prototype.width=function(){return this.pos-this.start},e.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},e.QueryLexer.prototype.backup=function(){this.pos-=1},e.QueryLexer.prototype.acceptDigitRun=function(){var t,r;do t=this.next(),r=t.charCodeAt(0);while(r>47&&r<58);t!=e.QueryLexer.EOS&&this.backup()},e.QueryLexer.prototype.more=function(){return this.pos1&&(t.backup(),t.emit(e.QueryLexer.TERM)),t.ignore(),t.more())return e.QueryLexer.lexText},e.QueryLexer.lexEditDistance=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.EDIT_DISTANCE),e.QueryLexer.lexText},e.QueryLexer.lexBoost=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.BOOST),e.QueryLexer.lexText},e.QueryLexer.lexEOS=function(t){t.width()>0&&t.emit(e.QueryLexer.TERM)},e.QueryLexer.termSeparator=e.tokenizer.separator,e.QueryLexer.lexText=function(t){for(;;){var r=t.next();if(r==e.QueryLexer.EOS)return e.QueryLexer.lexEOS;if(92!=r.charCodeAt(0)){if(":"==r)return e.QueryLexer.lexField;if("~"==r)return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexEditDistance;if("^"==r)return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexBoost;if("+"==r&&1===t.width())return t.emit(e.QueryLexer.PRESENCE),e.QueryLexer.lexText;if("-"==r&&1===t.width())return t.emit(e.QueryLexer.PRESENCE),e.QueryLexer.lexText;if(r.match(e.QueryLexer.termSeparator))return e.QueryLexer.lexTerm}else t.escapeCharacter()}},e.QueryParser=function(t,r){this.lexer=new e.QueryLexer(t),this.query=r,this.currentClause={},this.lexemeIdx=0},e.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var t=e.QueryParser.parseClause;t;)t=t(this);return this.query},e.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},e.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},e.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},e.QueryParser.parseClause=function(t){var r=t.peekLexeme();if(void 0!=r)switch(r.type){case e.QueryLexer.PRESENCE:return e.QueryParser.parsePresence;case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(i+=" with value '"+r.str+"'"),new e.QueryParseError(i,r.start,r.end)}},e.QueryParser.parsePresence=function(t){var r=t.consumeLexeme();if(void 0!=r){switch(r.str){case"-":t.currentClause.presence=e.Query.presence.PROHIBITED;break;case"+":t.currentClause.presence=e.Query.presence.REQUIRED;break;default:var i="unrecognised presence operator'"+r.str+"'";throw new e.QueryParseError(i,r.start,r.end)}var n=t.peekLexeme();if(void 0==n){var i="expecting term or field, found nothing";throw new e.QueryParseError(i,r.start,r.end)}switch(n.type){case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expecting term or field, found '"+n.type+"'";throw new e.QueryParseError(i,n.start,n.end)}}},e.QueryParser.parseField=function(t){var r=t.consumeLexeme();if(void 0!=r){if(t.query.allFields.indexOf(r.str)==-1){var i=t.query.allFields.map(function(e){return"'"+e+"'"}).join(", "),n="unrecognised field '"+r.str+"', possible fields: "+i;throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.fields=[r.str];var s=t.peekLexeme();if(void 0==s){var n="expecting term, found nothing";throw new e.QueryParseError(n,r.start,r.end)}switch(s.type){case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var n="expecting term, found '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},e.QueryParser.parseTerm=function(t){var r=t.consumeLexeme();if(void 0!=r){t.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(t.currentClause.usePipeline=!1);var i=t.peekLexeme();if(void 0==i)return void t.nextClause();switch(i.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+i.type+"'";throw new e.QueryParseError(n,i.start,i.end)}}},e.QueryParser.parseEditDistance=function(t){var r=t.consumeLexeme();if(void 0!=r){var i=parseInt(r.str,10);if(isNaN(i)){var n="edit distance must be numeric";throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.editDistance=i;var s=t.peekLexeme();if(void 0==s)return void t.nextClause();switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},e.QueryParser.parseBoost=function(t){var r=t.consumeLexeme();if(void 0!=r){var i=parseInt(r.str,10);if(isNaN(i)){var n="boost must be numeric";throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.boost=i;var s=t.peekLexeme();if(void 0==s)return void t.nextClause();switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.lunr=t()}(this,function(){return e})}(); 7 | --------------------------------------------------------------------------------