mirror of
https://github.com/bolucat/Archive.git
synced 2026-04-22 16:07:49 +08:00
2752 lines
110 KiB
HTML
2752 lines
110 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Brook</title>
|
||
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-R3M673HK5V"></script>
|
||
<script>
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag() {dataLayer.push(arguments);}
|
||
gtag('js', new Date());
|
||
gtag('config', 'G-R3M673HK5V');
|
||
</script>
|
||
|
||
<style>
|
||
@media (prefers-color-scheme: dark) {
|
||
.markdown-body {
|
||
color-scheme: dark;
|
||
--color-prettylights-syntax-comment: #8b949e;
|
||
--color-prettylights-syntax-constant: #79c0ff;
|
||
--color-prettylights-syntax-entity: #d2a8ff;
|
||
--color-prettylights-syntax-storage-modifier-import: #c9d1d9;
|
||
--color-prettylights-syntax-entity-tag: #7ee787;
|
||
--color-prettylights-syntax-keyword: #ff7b72;
|
||
--color-prettylights-syntax-string: #a5d6ff;
|
||
--color-prettylights-syntax-variable: #ffa657;
|
||
--color-prettylights-syntax-brackethighlighter-unmatched: #f85149;
|
||
--color-prettylights-syntax-invalid-illegal-text: #f0f6fc;
|
||
--color-prettylights-syntax-invalid-illegal-bg: #8e1519;
|
||
--color-prettylights-syntax-carriage-return-text: #f0f6fc;
|
||
--color-prettylights-syntax-carriage-return-bg: #b62324;
|
||
--color-prettylights-syntax-string-regexp: #7ee787;
|
||
--color-prettylights-syntax-markup-list: #f2cc60;
|
||
--color-prettylights-syntax-markup-heading: #1f6feb;
|
||
--color-prettylights-syntax-markup-italic: #c9d1d9;
|
||
--color-prettylights-syntax-markup-bold: #c9d1d9;
|
||
--color-prettylights-syntax-markup-deleted-text: #ffdcd7;
|
||
--color-prettylights-syntax-markup-deleted-bg: #67060c;
|
||
--color-prettylights-syntax-markup-inserted-text: #aff5b4;
|
||
--color-prettylights-syntax-markup-inserted-bg: #033a16;
|
||
--color-prettylights-syntax-markup-changed-text: #ffdfb6;
|
||
--color-prettylights-syntax-markup-changed-bg: #5a1e02;
|
||
--color-prettylights-syntax-markup-ignored-text: #c9d1d9;
|
||
--color-prettylights-syntax-markup-ignored-bg: #1158c7;
|
||
--color-prettylights-syntax-meta-diff-range: #d2a8ff;
|
||
--color-prettylights-syntax-brackethighlighter-angle: #8b949e;
|
||
--color-prettylights-syntax-sublimelinter-gutter-mark: #484f58;
|
||
--color-prettylights-syntax-constant-other-reference-link: #a5d6ff;
|
||
--color-fg-default: #c9d1d9;
|
||
--color-fg-muted: #8b949e;
|
||
--color-fg-subtle: #484f58;
|
||
--color-canvas-default: #0d1117;
|
||
--color-canvas-subtle: #161b22;
|
||
--color-border-default: #30363d;
|
||
--color-border-muted: #21262d;
|
||
--color-neutral-muted: rgba(110, 118, 129, 0.4);
|
||
--color-accent-fg: #58a6ff;
|
||
--color-accent-emphasis: #1f6feb;
|
||
--color-attention-subtle: rgba(187, 128, 9, 0.15);
|
||
--color-danger-fg: #f85149;
|
||
}
|
||
}
|
||
|
||
@media (prefers-color-scheme: light) {
|
||
.markdown-body {
|
||
color-scheme: light;
|
||
--color-prettylights-syntax-comment: #6e7781;
|
||
--color-prettylights-syntax-constant: #0550ae;
|
||
--color-prettylights-syntax-entity: #8250df;
|
||
--color-prettylights-syntax-storage-modifier-import: #24292f;
|
||
--color-prettylights-syntax-entity-tag: #116329;
|
||
--color-prettylights-syntax-keyword: #cf222e;
|
||
--color-prettylights-syntax-string: #0a3069;
|
||
--color-prettylights-syntax-variable: #953800;
|
||
--color-prettylights-syntax-brackethighlighter-unmatched: #82071e;
|
||
--color-prettylights-syntax-invalid-illegal-text: #f6f8fa;
|
||
--color-prettylights-syntax-invalid-illegal-bg: #82071e;
|
||
--color-prettylights-syntax-carriage-return-text: #f6f8fa;
|
||
--color-prettylights-syntax-carriage-return-bg: #cf222e;
|
||
--color-prettylights-syntax-string-regexp: #116329;
|
||
--color-prettylights-syntax-markup-list: #3b2300;
|
||
--color-prettylights-syntax-markup-heading: #0550ae;
|
||
--color-prettylights-syntax-markup-italic: #24292f;
|
||
--color-prettylights-syntax-markup-bold: #24292f;
|
||
--color-prettylights-syntax-markup-deleted-text: #82071e;
|
||
--color-prettylights-syntax-markup-deleted-bg: #FFEBE9;
|
||
--color-prettylights-syntax-markup-inserted-text: #116329;
|
||
--color-prettylights-syntax-markup-inserted-bg: #dafbe1;
|
||
--color-prettylights-syntax-markup-changed-text: #953800;
|
||
--color-prettylights-syntax-markup-changed-bg: #ffd8b5;
|
||
--color-prettylights-syntax-markup-ignored-text: #eaeef2;
|
||
--color-prettylights-syntax-markup-ignored-bg: #0550ae;
|
||
--color-prettylights-syntax-meta-diff-range: #8250df;
|
||
--color-prettylights-syntax-brackethighlighter-angle: #57606a;
|
||
--color-prettylights-syntax-sublimelinter-gutter-mark: #8c959f;
|
||
--color-prettylights-syntax-constant-other-reference-link: #0a3069;
|
||
--color-fg-default: #24292f;
|
||
--color-fg-muted: #57606a;
|
||
--color-fg-subtle: #6e7781;
|
||
--color-canvas-default: #ffffff;
|
||
--color-canvas-subtle: #f6f8fa;
|
||
--color-border-default: #d0d7de;
|
||
--color-border-muted: hsla(210, 18%, 87%, 1);
|
||
--color-neutral-muted: rgba(175, 184, 193, 0.2);
|
||
--color-accent-fg: #0969da;
|
||
--color-accent-emphasis: #0969da;
|
||
--color-attention-subtle: #fff8c5;
|
||
--color-danger-fg: #cf222e;
|
||
}
|
||
}
|
||
|
||
.markdown-body {
|
||
-ms-text-size-adjust: 100%;
|
||
-webkit-text-size-adjust: 100%;
|
||
margin: 0;
|
||
color: var(--color-fg-default);
|
||
background-color: var(--color-canvas-default);
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
||
font-size: 16px;
|
||
line-height: 1.5;
|
||
word-wrap: break-word;
|
||
}
|
||
|
||
.markdown-body .octicon {
|
||
display: inline-block;
|
||
fill: currentColor;
|
||
vertical-align: text-bottom;
|
||
}
|
||
|
||
.markdown-body h1:hover .anchor .octicon-link:before,
|
||
.markdown-body h2:hover .anchor .octicon-link:before,
|
||
.markdown-body h3:hover .anchor .octicon-link:before,
|
||
.markdown-body h4:hover .anchor .octicon-link:before,
|
||
.markdown-body h5:hover .anchor .octicon-link:before,
|
||
.markdown-body h6:hover .anchor .octicon-link:before {
|
||
width: 16px;
|
||
height: 16px;
|
||
content: ' ';
|
||
display: inline-block;
|
||
background-color: currentColor;
|
||
-webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>");
|
||
mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>");
|
||
}
|
||
|
||
.markdown-body details,
|
||
.markdown-body figcaption,
|
||
.markdown-body figure {
|
||
display: block;
|
||
}
|
||
|
||
.markdown-body summary {
|
||
display: list-item;
|
||
}
|
||
|
||
.markdown-body [hidden] {
|
||
display: none !important;
|
||
}
|
||
|
||
.markdown-body a {
|
||
background-color: transparent;
|
||
color: var(--color-accent-fg);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.markdown-body a:active,
|
||
.markdown-body a:hover {
|
||
outline-width: 0;
|
||
}
|
||
|
||
.markdown-body abbr[title] {
|
||
border-bottom: none;
|
||
text-decoration: underline dotted;
|
||
}
|
||
|
||
.markdown-body b,
|
||
.markdown-body strong {
|
||
font-weight: 600;
|
||
}
|
||
|
||
.markdown-body dfn {
|
||
font-style: italic;
|
||
}
|
||
|
||
.markdown-body h1 {
|
||
margin: .67em 0;
|
||
font-weight: 600;
|
||
padding-bottom: .3em;
|
||
font-size: 2em;
|
||
border-bottom: 1px solid var(--color-border-muted);
|
||
}
|
||
|
||
.markdown-body mark {
|
||
background-color: var(--color-attention-subtle);
|
||
color: var(--color-text-primary);
|
||
}
|
||
|
||
.markdown-body small {
|
||
font-size: 90%;
|
||
}
|
||
|
||
.markdown-body sub,
|
||
.markdown-body sup {
|
||
font-size: 75%;
|
||
line-height: 0;
|
||
position: relative;
|
||
vertical-align: baseline;
|
||
}
|
||
|
||
.markdown-body sub {
|
||
bottom: -0.25em;
|
||
}
|
||
|
||
.markdown-body sup {
|
||
top: -0.5em;
|
||
}
|
||
|
||
.markdown-body img {
|
||
border-style: none;
|
||
max-width: 100%;
|
||
box-sizing: content-box;
|
||
background-color: var(--color-canvas-default);
|
||
}
|
||
|
||
.markdown-body code,
|
||
.markdown-body kbd,
|
||
.markdown-body pre,
|
||
.markdown-body samp {
|
||
font-family: monospace, monospace;
|
||
font-size: 1em;
|
||
}
|
||
|
||
.markdown-body figure {
|
||
margin: 1em 40px;
|
||
}
|
||
|
||
.markdown-body hr {
|
||
box-sizing: content-box;
|
||
overflow: hidden;
|
||
background: transparent;
|
||
border-bottom: 1px solid var(--color-border-muted);
|
||
height: .25em;
|
||
padding: 0;
|
||
margin: 24px 0;
|
||
background-color: var(--color-border-default);
|
||
border: 0;
|
||
}
|
||
|
||
.markdown-body input {
|
||
font: inherit;
|
||
margin: 0;
|
||
overflow: visible;
|
||
font-family: inherit;
|
||
font-size: inherit;
|
||
line-height: inherit;
|
||
}
|
||
|
||
.markdown-body [type=button],
|
||
.markdown-body [type=reset],
|
||
.markdown-body [type=submit] {
|
||
-webkit-appearance: button;
|
||
}
|
||
|
||
.markdown-body [type=button]::-moz-focus-inner,
|
||
.markdown-body [type=reset]::-moz-focus-inner,
|
||
.markdown-body [type=submit]::-moz-focus-inner {
|
||
border-style: none;
|
||
padding: 0;
|
||
}
|
||
|
||
.markdown-body [type=button]:-moz-focusring,
|
||
.markdown-body [type=reset]:-moz-focusring,
|
||
.markdown-body [type=submit]:-moz-focusring {
|
||
outline: 1px dotted ButtonText;
|
||
}
|
||
|
||
.markdown-body [type=checkbox],
|
||
.markdown-body [type=radio] {
|
||
box-sizing: border-box;
|
||
padding: 0;
|
||
}
|
||
|
||
.markdown-body [type=number]::-webkit-inner-spin-button,
|
||
.markdown-body [type=number]::-webkit-outer-spin-button {
|
||
height: auto;
|
||
}
|
||
|
||
.markdown-body [type=search] {
|
||
-webkit-appearance: textfield;
|
||
outline-offset: -2px;
|
||
}
|
||
|
||
.markdown-body [type=search]::-webkit-search-cancel-button,
|
||
.markdown-body [type=search]::-webkit-search-decoration {
|
||
-webkit-appearance: none;
|
||
}
|
||
|
||
.markdown-body ::-webkit-input-placeholder {
|
||
color: inherit;
|
||
opacity: .54;
|
||
}
|
||
|
||
.markdown-body ::-webkit-file-upload-button {
|
||
-webkit-appearance: button;
|
||
font: inherit;
|
||
}
|
||
|
||
.markdown-body a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.markdown-body hr::before {
|
||
display: table;
|
||
content: "";
|
||
}
|
||
|
||
.markdown-body hr::after {
|
||
display: table;
|
||
clear: both;
|
||
content: "";
|
||
}
|
||
|
||
.markdown-body table {
|
||
border-spacing: 0;
|
||
border-collapse: collapse;
|
||
display: block;
|
||
width: max-content;
|
||
max-width: 100%;
|
||
overflow: auto;
|
||
}
|
||
|
||
.markdown-body td,
|
||
.markdown-body th {
|
||
padding: 0;
|
||
}
|
||
|
||
.markdown-body details summary {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.markdown-body details:not([open])>*:not(summary) {
|
||
display: none !important;
|
||
}
|
||
|
||
.markdown-body kbd {
|
||
display: inline-block;
|
||
padding: 3px 5px;
|
||
font: 11px ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
||
line-height: 10px;
|
||
color: var(--color-fg-default);
|
||
vertical-align: middle;
|
||
background-color: var(--color-canvas-subtle);
|
||
border: solid 1px var(--color-neutral-muted);
|
||
border-bottom-color: var(--color-neutral-muted);
|
||
border-radius: 6px;
|
||
box-shadow: inset 0 -1px 0 var(--color-neutral-muted);
|
||
}
|
||
|
||
.markdown-body h1,
|
||
.markdown-body h2,
|
||
.markdown-body h3,
|
||
.markdown-body h4,
|
||
.markdown-body h5,
|
||
.markdown-body h6 {
|
||
margin-top: 24px;
|
||
margin-bottom: 16px;
|
||
font-weight: 600;
|
||
line-height: 1.25;
|
||
}
|
||
|
||
.markdown-body h2 {
|
||
font-weight: 600;
|
||
padding-bottom: .3em;
|
||
font-size: 1.5em;
|
||
border-bottom: 1px solid var(--color-border-muted);
|
||
}
|
||
|
||
.markdown-body h3 {
|
||
font-weight: 600;
|
||
font-size: 1.25em;
|
||
}
|
||
|
||
.markdown-body h4 {
|
||
font-weight: 600;
|
||
font-size: 1em;
|
||
}
|
||
|
||
.markdown-body h5 {
|
||
font-weight: 600;
|
||
font-size: .875em;
|
||
}
|
||
|
||
.markdown-body h6 {
|
||
font-weight: 600;
|
||
font-size: .85em;
|
||
color: var(--color-fg-muted);
|
||
}
|
||
|
||
.markdown-body p {
|
||
margin-top: 0;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.markdown-body blockquote {
|
||
margin: 0;
|
||
padding: 0 1em;
|
||
color: var(--color-fg-muted);
|
||
border-left: .25em solid var(--color-border-default);
|
||
}
|
||
|
||
.markdown-body ul,
|
||
.markdown-body ol {
|
||
margin-top: 0;
|
||
margin-bottom: 0;
|
||
padding-left: 2em;
|
||
}
|
||
|
||
.markdown-body ol ol,
|
||
.markdown-body ul ol {
|
||
list-style-type: lower-roman;
|
||
}
|
||
|
||
.markdown-body ul ul ol,
|
||
.markdown-body ul ol ol,
|
||
.markdown-body ol ul ol,
|
||
.markdown-body ol ol ol {
|
||
list-style-type: lower-alpha;
|
||
}
|
||
|
||
.markdown-body dd {
|
||
margin-left: 0;
|
||
}
|
||
|
||
.markdown-body tt,
|
||
.markdown-body code {
|
||
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.markdown-body pre {
|
||
margin-top: 0;
|
||
margin-bottom: 0;
|
||
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
||
font-size: 12px;
|
||
word-wrap: normal;
|
||
}
|
||
|
||
.markdown-body .octicon {
|
||
display: inline-block;
|
||
overflow: visible !important;
|
||
vertical-align: text-bottom;
|
||
fill: currentColor;
|
||
}
|
||
|
||
.markdown-body ::placeholder {
|
||
color: var(--color-fg-subtle);
|
||
opacity: 1;
|
||
}
|
||
|
||
.markdown-body input::-webkit-outer-spin-button,
|
||
.markdown-body input::-webkit-inner-spin-button {
|
||
margin: 0;
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
}
|
||
|
||
.markdown-body .pl-c {
|
||
color: var(--color-prettylights-syntax-comment);
|
||
}
|
||
|
||
.markdown-body .pl-c1,
|
||
.markdown-body .pl-s .pl-v {
|
||
color: var(--color-prettylights-syntax-constant);
|
||
}
|
||
|
||
.markdown-body .pl-e,
|
||
.markdown-body .pl-en {
|
||
color: var(--color-prettylights-syntax-entity);
|
||
}
|
||
|
||
.markdown-body .pl-smi,
|
||
.markdown-body .pl-s .pl-s1 {
|
||
color: var(--color-prettylights-syntax-storage-modifier-import);
|
||
}
|
||
|
||
.markdown-body .pl-ent {
|
||
color: var(--color-prettylights-syntax-entity-tag);
|
||
}
|
||
|
||
.markdown-body .pl-k {
|
||
color: var(--color-prettylights-syntax-keyword);
|
||
}
|
||
|
||
.markdown-body .pl-s,
|
||
.markdown-body .pl-pds,
|
||
.markdown-body .pl-s .pl-pse .pl-s1,
|
||
.markdown-body .pl-sr,
|
||
.markdown-body .pl-sr .pl-cce,
|
||
.markdown-body .pl-sr .pl-sre,
|
||
.markdown-body .pl-sr .pl-sra {
|
||
color: var(--color-prettylights-syntax-string);
|
||
}
|
||
|
||
.markdown-body .pl-v,
|
||
.markdown-body .pl-smw {
|
||
color: var(--color-prettylights-syntax-variable);
|
||
}
|
||
|
||
.markdown-body .pl-bu {
|
||
color: var(--color-prettylights-syntax-brackethighlighter-unmatched);
|
||
}
|
||
|
||
.markdown-body .pl-ii {
|
||
color: var(--color-prettylights-syntax-invalid-illegal-text);
|
||
background-color: var(--color-prettylights-syntax-invalid-illegal-bg);
|
||
}
|
||
|
||
.markdown-body .pl-c2 {
|
||
color: var(--color-prettylights-syntax-carriage-return-text);
|
||
background-color: var(--color-prettylights-syntax-carriage-return-bg);
|
||
}
|
||
|
||
.markdown-body .pl-sr .pl-cce {
|
||
font-weight: bold;
|
||
color: var(--color-prettylights-syntax-string-regexp);
|
||
}
|
||
|
||
.markdown-body .pl-ml {
|
||
color: var(--color-prettylights-syntax-markup-list);
|
||
}
|
||
|
||
.markdown-body .pl-mh,
|
||
.markdown-body .pl-mh .pl-en,
|
||
.markdown-body .pl-ms {
|
||
font-weight: bold;
|
||
color: var(--color-prettylights-syntax-markup-heading);
|
||
}
|
||
|
||
.markdown-body .pl-mi {
|
||
font-style: italic;
|
||
color: var(--color-prettylights-syntax-markup-italic);
|
||
}
|
||
|
||
.markdown-body .pl-mb {
|
||
font-weight: bold;
|
||
color: var(--color-prettylights-syntax-markup-bold);
|
||
}
|
||
|
||
.markdown-body .pl-md {
|
||
color: var(--color-prettylights-syntax-markup-deleted-text);
|
||
background-color: var(--color-prettylights-syntax-markup-deleted-bg);
|
||
}
|
||
|
||
.markdown-body .pl-mi1 {
|
||
color: var(--color-prettylights-syntax-markup-inserted-text);
|
||
background-color: var(--color-prettylights-syntax-markup-inserted-bg);
|
||
}
|
||
|
||
.markdown-body .pl-mc {
|
||
color: var(--color-prettylights-syntax-markup-changed-text);
|
||
background-color: var(--color-prettylights-syntax-markup-changed-bg);
|
||
}
|
||
|
||
.markdown-body .pl-mi2 {
|
||
color: var(--color-prettylights-syntax-markup-ignored-text);
|
||
background-color: var(--color-prettylights-syntax-markup-ignored-bg);
|
||
}
|
||
|
||
.markdown-body .pl-mdr {
|
||
font-weight: bold;
|
||
color: var(--color-prettylights-syntax-meta-diff-range);
|
||
}
|
||
|
||
.markdown-body .pl-ba {
|
||
color: var(--color-prettylights-syntax-brackethighlighter-angle);
|
||
}
|
||
|
||
.markdown-body .pl-sg {
|
||
color: var(--color-prettylights-syntax-sublimelinter-gutter-mark);
|
||
}
|
||
|
||
.markdown-body .pl-corl {
|
||
text-decoration: underline;
|
||
color: var(--color-prettylights-syntax-constant-other-reference-link);
|
||
}
|
||
|
||
.markdown-body [data-catalyst] {
|
||
display: block;
|
||
}
|
||
|
||
.markdown-body g-emoji {
|
||
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||
font-size: 1em;
|
||
font-style: normal !important;
|
||
font-weight: 400;
|
||
line-height: 1;
|
||
vertical-align: -0.075em;
|
||
}
|
||
|
||
.markdown-body g-emoji img {
|
||
width: 1em;
|
||
height: 1em;
|
||
}
|
||
|
||
.markdown-body::before {
|
||
display: table;
|
||
content: "";
|
||
}
|
||
|
||
.markdown-body::after {
|
||
display: table;
|
||
clear: both;
|
||
content: "";
|
||
}
|
||
|
||
.markdown-body>*:first-child {
|
||
margin-top: 0 !important;
|
||
}
|
||
|
||
.markdown-body>*:last-child {
|
||
margin-bottom: 0 !important;
|
||
}
|
||
|
||
.markdown-body a:not([href]) {
|
||
color: inherit;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.markdown-body .absent {
|
||
color: var(--color-danger-fg);
|
||
}
|
||
|
||
.markdown-body .anchor {
|
||
float: left;
|
||
padding-right: 4px;
|
||
margin-left: -20px;
|
||
line-height: 1;
|
||
}
|
||
|
||
.markdown-body .anchor:focus {
|
||
outline: none;
|
||
}
|
||
|
||
.markdown-body p,
|
||
.markdown-body blockquote,
|
||
.markdown-body ul,
|
||
.markdown-body ol,
|
||
.markdown-body dl,
|
||
.markdown-body table,
|
||
.markdown-body pre,
|
||
.markdown-body details {
|
||
margin-top: 0;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.markdown-body blockquote>:first-child {
|
||
margin-top: 0;
|
||
}
|
||
|
||
.markdown-body blockquote>:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.markdown-body sup>a::before {
|
||
content: "[";
|
||
}
|
||
|
||
.markdown-body sup>a::after {
|
||
content: "]";
|
||
}
|
||
|
||
.markdown-body h1 .octicon-link,
|
||
.markdown-body h2 .octicon-link,
|
||
.markdown-body h3 .octicon-link,
|
||
.markdown-body h4 .octicon-link,
|
||
.markdown-body h5 .octicon-link,
|
||
.markdown-body h6 .octicon-link {
|
||
color: var(--color-fg-default);
|
||
vertical-align: middle;
|
||
visibility: hidden;
|
||
}
|
||
|
||
.markdown-body h1:hover .anchor,
|
||
.markdown-body h2:hover .anchor,
|
||
.markdown-body h3:hover .anchor,
|
||
.markdown-body h4:hover .anchor,
|
||
.markdown-body h5:hover .anchor,
|
||
.markdown-body h6:hover .anchor {
|
||
text-decoration: none;
|
||
}
|
||
|
||
.markdown-body h1:hover .anchor .octicon-link,
|
||
.markdown-body h2:hover .anchor .octicon-link,
|
||
.markdown-body h3:hover .anchor .octicon-link,
|
||
.markdown-body h4:hover .anchor .octicon-link,
|
||
.markdown-body h5:hover .anchor .octicon-link,
|
||
.markdown-body h6:hover .anchor .octicon-link {
|
||
visibility: visible;
|
||
}
|
||
|
||
.markdown-body h1 tt,
|
||
.markdown-body h1 code,
|
||
.markdown-body h2 tt,
|
||
.markdown-body h2 code,
|
||
.markdown-body h3 tt,
|
||
.markdown-body h3 code,
|
||
.markdown-body h4 tt,
|
||
.markdown-body h4 code,
|
||
.markdown-body h5 tt,
|
||
.markdown-body h5 code,
|
||
.markdown-body h6 tt,
|
||
.markdown-body h6 code {
|
||
padding: 0 .2em;
|
||
font-size: inherit;
|
||
}
|
||
|
||
.markdown-body ul.no-list,
|
||
.markdown-body ol.no-list {
|
||
padding: 0;
|
||
list-style-type: none;
|
||
}
|
||
|
||
.markdown-body ol[type="1"] {
|
||
list-style-type: decimal;
|
||
}
|
||
|
||
.markdown-body ol[type=a] {
|
||
list-style-type: lower-alpha;
|
||
}
|
||
|
||
.markdown-body ol[type=i] {
|
||
list-style-type: lower-roman;
|
||
}
|
||
|
||
.markdown-body div>ol:not([type]) {
|
||
list-style-type: decimal;
|
||
}
|
||
|
||
.markdown-body ul ul,
|
||
.markdown-body ul ol,
|
||
.markdown-body ol ol,
|
||
.markdown-body ol ul {
|
||
margin-top: 0;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.markdown-body li>p {
|
||
margin-top: 16px;
|
||
}
|
||
|
||
.markdown-body li+li {
|
||
margin-top: .25em;
|
||
}
|
||
|
||
.markdown-body dl {
|
||
padding: 0;
|
||
}
|
||
|
||
.markdown-body dl dt {
|
||
padding: 0;
|
||
margin-top: 16px;
|
||
font-size: 1em;
|
||
font-style: italic;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.markdown-body dl dd {
|
||
padding: 0 16px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.markdown-body table th {
|
||
font-weight: 600;
|
||
}
|
||
|
||
.markdown-body table th,
|
||
.markdown-body table td {
|
||
padding: 6px 13px;
|
||
border: 1px solid var(--color-border-default);
|
||
}
|
||
|
||
.markdown-body table tr {
|
||
background-color: var(--color-canvas-default);
|
||
border-top: 1px solid var(--color-border-muted);
|
||
}
|
||
|
||
.markdown-body table tr:nth-child(2n) {
|
||
background-color: var(--color-canvas-subtle);
|
||
}
|
||
|
||
.markdown-body table img {
|
||
background-color: transparent;
|
||
}
|
||
|
||
.markdown-body img[align=right] {
|
||
padding-left: 20px;
|
||
}
|
||
|
||
.markdown-body img[align=left] {
|
||
padding-right: 20px;
|
||
}
|
||
|
||
.markdown-body .emoji {
|
||
max-width: none;
|
||
vertical-align: text-top;
|
||
background-color: transparent;
|
||
}
|
||
|
||
.markdown-body span.frame {
|
||
display: block;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.markdown-body span.frame>span {
|
||
display: block;
|
||
float: left;
|
||
width: auto;
|
||
padding: 7px;
|
||
margin: 13px 0 0;
|
||
overflow: hidden;
|
||
border: 1px solid var(--color-border-default);
|
||
}
|
||
|
||
.markdown-body span.frame span img {
|
||
display: block;
|
||
float: left;
|
||
}
|
||
|
||
.markdown-body span.frame span span {
|
||
display: block;
|
||
padding: 5px 0 0;
|
||
clear: both;
|
||
color: var(--color-fg-default);
|
||
}
|
||
|
||
.markdown-body span.align-center {
|
||
display: block;
|
||
overflow: hidden;
|
||
clear: both;
|
||
}
|
||
|
||
.markdown-body span.align-center>span {
|
||
display: block;
|
||
margin: 13px auto 0;
|
||
overflow: hidden;
|
||
text-align: center;
|
||
}
|
||
|
||
.markdown-body span.align-center span img {
|
||
margin: 0 auto;
|
||
text-align: center;
|
||
}
|
||
|
||
.markdown-body span.align-right {
|
||
display: block;
|
||
overflow: hidden;
|
||
clear: both;
|
||
}
|
||
|
||
.markdown-body span.align-right>span {
|
||
display: block;
|
||
margin: 13px 0 0;
|
||
overflow: hidden;
|
||
text-align: right;
|
||
}
|
||
|
||
.markdown-body span.align-right span img {
|
||
margin: 0;
|
||
text-align: right;
|
||
}
|
||
|
||
.markdown-body span.float-left {
|
||
display: block;
|
||
float: left;
|
||
margin-right: 13px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.markdown-body span.float-left span {
|
||
margin: 13px 0 0;
|
||
}
|
||
|
||
.markdown-body span.float-right {
|
||
display: block;
|
||
float: right;
|
||
margin-left: 13px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.markdown-body span.float-right>span {
|
||
display: block;
|
||
margin: 13px auto 0;
|
||
overflow: hidden;
|
||
text-align: right;
|
||
}
|
||
|
||
.markdown-body code,
|
||
.markdown-body tt {
|
||
padding: .2em .4em;
|
||
margin: 0;
|
||
font-size: 85%;
|
||
background-color: var(--color-neutral-muted);
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.markdown-body code br,
|
||
.markdown-body tt br {
|
||
display: none;
|
||
}
|
||
|
||
.markdown-body del code {
|
||
text-decoration: inherit;
|
||
}
|
||
|
||
.markdown-body pre code {
|
||
font-size: 100%;
|
||
}
|
||
|
||
.markdown-body pre>code {
|
||
padding: 0;
|
||
margin: 0;
|
||
word-break: normal;
|
||
white-space: pre;
|
||
background: transparent;
|
||
border: 0;
|
||
}
|
||
|
||
.markdown-body .highlight {
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.markdown-body .highlight pre {
|
||
margin-bottom: 0;
|
||
word-break: normal;
|
||
}
|
||
|
||
.markdown-body .highlight pre,
|
||
.markdown-body pre {
|
||
padding: 16px;
|
||
overflow: auto;
|
||
font-size: 85%;
|
||
line-height: 1.45;
|
||
background-color: var(--color-canvas-subtle);
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.markdown-body pre code,
|
||
.markdown-body pre tt {
|
||
display: inline;
|
||
max-width: auto;
|
||
padding: 0;
|
||
margin: 0;
|
||
overflow: visible;
|
||
line-height: inherit;
|
||
word-wrap: normal;
|
||
background-color: transparent;
|
||
border: 0;
|
||
}
|
||
|
||
.markdown-body .csv-data td,
|
||
.markdown-body .csv-data th {
|
||
padding: 5px;
|
||
overflow: hidden;
|
||
font-size: 12px;
|
||
line-height: 1;
|
||
text-align: left;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.markdown-body .csv-data .blob-num {
|
||
padding: 10px 8px 9px;
|
||
text-align: right;
|
||
background: var(--color-canvas-default);
|
||
border: 0;
|
||
}
|
||
|
||
.markdown-body .csv-data tr {
|
||
border-top: 0;
|
||
}
|
||
|
||
.markdown-body .csv-data th {
|
||
font-weight: 600;
|
||
background: var(--color-canvas-subtle);
|
||
border-top: 0;
|
||
}
|
||
|
||
.markdown-body .footnotes {
|
||
font-size: 12px;
|
||
color: var(--color-fg-muted);
|
||
border-top: 1px solid var(--color-border-default);
|
||
}
|
||
|
||
.markdown-body .footnotes ol {
|
||
padding-left: 16px;
|
||
}
|
||
|
||
.markdown-body .footnotes li {
|
||
position: relative;
|
||
}
|
||
|
||
.markdown-body .footnotes li:target::before {
|
||
position: absolute;
|
||
top: -8px;
|
||
right: -8px;
|
||
bottom: -8px;
|
||
left: -24px;
|
||
pointer-events: none;
|
||
content: "";
|
||
border: 2px solid var(--color-accent-emphasis);
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.markdown-body .footnotes li:target {
|
||
color: var(--color-fg-default);
|
||
}
|
||
|
||
.markdown-body .footnotes .data-footnote-backref g-emoji {
|
||
font-family: monospace;
|
||
}
|
||
|
||
.markdown-body .task-list-item {
|
||
list-style-type: none;
|
||
}
|
||
|
||
.markdown-body .task-list-item label {
|
||
font-weight: 400;
|
||
}
|
||
|
||
.markdown-body .task-list-item.enabled label {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.markdown-body .task-list-item+.task-list-item {
|
||
margin-top: 3px;
|
||
}
|
||
|
||
.markdown-body .task-list-item .handle {
|
||
display: none;
|
||
}
|
||
|
||
.markdown-body .task-list-item-checkbox {
|
||
margin: 0 .2em .25em -1.6em;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
.markdown-body .contains-task-list:dir(rtl) .task-list-item-checkbox {
|
||
margin: 0 -1.6em .25em .2em;
|
||
}
|
||
|
||
.markdown-body ::-webkit-calendar-picker-indicator {
|
||
filter: invert(50%);
|
||
}
|
||
</style>
|
||
<style>
|
||
.markdown-body {
|
||
box-sizing: border-box;
|
||
min-width: 200px;
|
||
max-width: 980px;
|
||
margin: 0 auto;
|
||
padding: 45px;
|
||
}
|
||
|
||
@media (max-width: 767px) {
|
||
.markdown-body {
|
||
padding: 15px;
|
||
}
|
||
}
|
||
</style>
|
||
<style>
|
||
.sidebar {
|
||
margin: 0;
|
||
padding: 0;
|
||
width: 300px;
|
||
position: fixed;
|
||
height: 100vh;
|
||
overflow: auto;
|
||
}
|
||
|
||
@media (prefers-color-scheme: light) {
|
||
.sidebar {
|
||
background-color: #f1f2f5;
|
||
}
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
.sidebar {
|
||
background-color: #0e1116;
|
||
border-right: 1px solid #919191;
|
||
}
|
||
}
|
||
|
||
.sidebar ul {
|
||
list-style-type: none;
|
||
}
|
||
|
||
.sidebar>ul>li>a {
|
||
font-weight: bold;
|
||
}
|
||
|
||
.sidebarmob {
|
||
display: none;
|
||
}
|
||
|
||
div.content {
|
||
margin-left: 300px;
|
||
}
|
||
|
||
.sidebar a {
|
||
display: block;
|
||
color: black;
|
||
text-decoration: none;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
overflow: hidden;
|
||
padding: 10px 10px 10px 0px;
|
||
}
|
||
|
||
.sidebar a:hover:not(.active) {
|
||
color: #0969da;
|
||
}
|
||
|
||
@media screen and (max-width: 700px) {
|
||
.sidebar {
|
||
display: none;
|
||
}
|
||
|
||
.sidebarmob {
|
||
display: block;
|
||
}
|
||
|
||
div.content {
|
||
margin-left: 0;
|
||
}
|
||
}
|
||
</style>
|
||
<style>
|
||
@media (prefers-color-scheme: dark) {
|
||
body {
|
||
background-color: #0d1117
|
||
}
|
||
|
||
.sidebar a {
|
||
color: #c9d1d9
|
||
}
|
||
|
||
.sidebar a:hover:not(.active) {
|
||
color: #58a6ff;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body style="margin:0">
|
||
|
||
<div class="sidebar">
|
||
<ul>
|
||
<li><a href="#sponsor">Sponsor</a></li>
|
||
<li><a href="#getting-started">Getting Started</a><ul>
|
||
<li><a href="#server">Server</a></li>
|
||
<li><a href="#gui-client">GUI Client</a></li>
|
||
<li><a href="#cli-client">CLI Client</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#gui-documentation">GUI Documentation</a><ul>
|
||
<li><a href="#software-for-which-this-article-applies">Software for which this article applies</a></li>
|
||
<li><a href="#programmable">Programmable</a><ul>
|
||
<li><a href="#introduction-to-incoming-variables">Introduction to incoming variables</a></li>
|
||
<li><a href="#in_brooklinks">in_brooklinks</a></li>
|
||
<li><a href="#in_dnsquery">in_dnsquery</a></li>
|
||
<li><a href="#in_address">in_address</a></li>
|
||
<li><a href="#in_httprequest">in_httprequest</a></li>
|
||
<li><a href="#in_httpresponse">in_httpresponse</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#write-script">Write script</a></li>
|
||
<li><a href="#debug-script">Debug script</a></li>
|
||
<li><a href="#install-ca">Install CA</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#resources">Resources</a></li>
|
||
<li><a href="#cli-documentation">CLI Documentation</a></li>
|
||
<li><a href="#name">NAME</a></li>
|
||
<li><a href="#synopsis">SYNOPSIS</a></li>
|
||
<li><a href="#global-options">GLOBAL OPTIONS</a></li>
|
||
<li><a href="#commands">COMMANDS</a><ul>
|
||
<li><a href="#server">server</a></li>
|
||
<li><a href="#client">client</a></li>
|
||
<li><a href="#wsserver">wsserver</a></li>
|
||
<li><a href="#wsclient">wsclient</a></li>
|
||
<li><a href="#wssserver">wssserver</a></li>
|
||
<li><a href="#wssclient">wssclient</a></li>
|
||
<li><a href="#quicserver">quicserver</a></li>
|
||
<li><a href="#quicclient">quicclient</a></li>
|
||
<li><a href="#relayoverbrook">relayoverbrook</a></li>
|
||
<li><a href="#dnsserveroverbrook">dnsserveroverbrook</a></li>
|
||
<li><a href="#link">link</a></li>
|
||
<li><a href="#connect">connect</a></li>
|
||
<li><a href="#relay">relay</a></li>
|
||
<li><a href="#dnsserver">dnsserver</a></li>
|
||
<li><a href="#dnsclient">dnsclient</a></li>
|
||
<li><a href="#dohserver">dohserver</a></li>
|
||
<li><a href="#dohclient">dohclient</a></li>
|
||
<li><a href="#dhcpserver">dhcpserver</a></li>
|
||
<li><a href="#socks5">socks5</a></li>
|
||
<li><a href="#socks5tohttp">socks5tohttp</a></li>
|
||
<li><a href="#pac">pac</a></li>
|
||
<li><a href="#testsocks5">testsocks5</a></li>
|
||
<li><a href="#testbrook">testbrook</a></li>
|
||
<li><a href="#echoserver">echoserver</a></li>
|
||
<li><a href="#echoclient">echoclient</a></li>
|
||
<li><a href="#ipcountry">ipcountry</a></li>
|
||
<li><a href="#completion">completion</a></li>
|
||
<li><a href="#mdpage">mdpage</a><ul>
|
||
<li><a href="#help-h">help, h</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#manpage">manpage</a></li>
|
||
<li><a href="#help-h-1">help, h</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#examples">Examples</a><ul>
|
||
<li><a href="#run-brook-server">Run brook server</a></li>
|
||
<li><a href="#run-brook-wsserver">Run brook wsserver</a></li>
|
||
<li><a href="#run-brook-wssserver-automatically-certificate">Run brook wssserver: automatically certificate</a></li>
|
||
<li><a href="#run-brook-wssserver-use-a-certificate-issued-by-an-existing-trust-authority">Run brook wssserver Use a certificate issued by an existing trust authority</a></li>
|
||
<li><a href="#run-brook-wssserver-issue-untrusted-certificates-yourself-any-domain">Run brook wssserver issue untrusted certificates yourself, any domain</a></li>
|
||
<li><a href="#withoutbrookprotocol">withoutBrookProtocol</a></li>
|
||
<li><a href="#withoutbrookprotocol-automatically-certificate">withoutBrookProtocol automatically certificate</a></li>
|
||
<li><a href="#withoutbrookprotocol-use-a-certificate-issued-by-an-existing-trust-authority">withoutBrookProtocol Use a certificate issued by an existing trust authority</a></li>
|
||
<li><a href="#withoutbrookprotocol-issue-untrusted-certificates-yourself-any-domain">withoutBrookProtocol issue untrusted certificates yourself, any domain</a></li>
|
||
<li><a href="#run-brook-socks5-a-stand-alone-standard-socks5-server">Run brook socks5, A stand-alone standard socks5 server</a></li>
|
||
<li><a href="#run-brook-socks5-with-username-and-password-a-stand-alone-standard-socks5-server">Run brook socks5 with username and password. A stand-alone standard socks5 server</a></li>
|
||
<li><a href="#brook-relayoverbrook-can-relay-a-local-address-to-a-remote-address-over-brook-both-tcp-and-udp-it-works-with-brook-server-wsserver-wssserver">brook relayoverbrook can relay a local address to a remote address over brook, both TCP and UDP, it works with brook server wsserver wssserver.</a></li>
|
||
<li><a href="#brook-dnsserveroverbrook-can-create-a-encrypted-dns-server-both-tcp-and-udp-it-works-with-brook-server-wsserver-wssserver">brook dnsserveroverbrook can create a encrypted DNS server, both TCP and UDP, it works with brook server wsserver wssserver.</a></li>
|
||
<li><a href="#brook-openwrt-router-perfectly-supports-ipv4ipv6tcpudp-native-ipv6">Brook OpenWRT Router: Perfectly supports IPv4/IPv6/TCP/UDP. Native IPv6</a></li>
|
||
<li><a href="#turn-macos-into-a-gateway-with-brook">Turn macOS into a Gateway with Brook</a></li>
|
||
<li><a href="#turn-windows-into-a-gateway-with-brook">Turn Windows into a Gateway with Brook</a></li>
|
||
<li><a href="#turn-linux-into-a-gateway-with-brook">Turn Linux into a Gateway with Brook</a></li>
|
||
<li><a href="#brook-relay-can-relay-a-address-to-a-remote-address-it-can-relay-any-tcp-and-udp-server">brook relay can relay a address to a remote address. It can relay any tcp and udp server</a></li>
|
||
<li><a href="#brook-socks5tohttp-can-convert-a-socks5-to-a-http-proxy">brook socks5tohttp can convert a socks5 to a http proxy</a></li>
|
||
<li><a href="#brook-pac-creates-pac-server">brook pac creates pac server</a></li>
|
||
<li><a href="#brook-pac-creates-pac-file">brook pac creates pac file</a></li>
|
||
<li><a href="#there-are-countless-examples-for-more-feature-suggestions-its-best-to-look-at-the-commands-and-parameters-in-the-cli-documentation-one-by-one-and-blog-youtube">There are countless examples; for more feature suggestions, it's best to look at the commands and parameters in the CLI documentation one by one, and blog, YouTube...</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#diagram">Diagram</a><ul>
|
||
<li><a href="#overview">overview</a></li>
|
||
<li><a href="#withoutbrookprotocol-1">withoutBrookProtocol</a></li>
|
||
<li><a href="#relayoverbrook-1">relayoverbrook</a></li>
|
||
<li><a href="#dnsserveroverbrook-1">dnsserveroverbrook</a></li>
|
||
<li><a href="#relay-1">relay</a></li>
|
||
<li><a href="#dnsserver-1">dnsserver</a></li>
|
||
<li><a href="#tproxy">tproxy</a></li>
|
||
<li><a href="#gui">gui</a></li>
|
||
<li><a href="#script">script</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
</div>
|
||
<div class="content">
|
||
<div class="markdown-body">
|
||
<h1 id="brook">Brook</h1>
|
||
|
||
<div class="sidebarmob">
|
||
<ul>
|
||
<li><a href="#sponsor">Sponsor</a></li>
|
||
<li><a href="#getting-started">Getting Started</a><ul>
|
||
<li><a href="#server">Server</a></li>
|
||
<li><a href="#gui-client">GUI Client</a></li>
|
||
<li><a href="#cli-client">CLI Client</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#gui-documentation">GUI Documentation</a><ul>
|
||
<li><a href="#software-for-which-this-article-applies">Software for which this article applies</a></li>
|
||
<li><a href="#programmable">Programmable</a><ul>
|
||
<li><a href="#introduction-to-incoming-variables">Introduction to incoming variables</a></li>
|
||
<li><a href="#in_brooklinks">in_brooklinks</a></li>
|
||
<li><a href="#in_dnsquery">in_dnsquery</a></li>
|
||
<li><a href="#in_address">in_address</a></li>
|
||
<li><a href="#in_httprequest">in_httprequest</a></li>
|
||
<li><a href="#in_httpresponse">in_httpresponse</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#write-script">Write script</a></li>
|
||
<li><a href="#debug-script">Debug script</a></li>
|
||
<li><a href="#install-ca">Install CA</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#resources">Resources</a></li>
|
||
<li><a href="#cli-documentation">CLI Documentation</a></li>
|
||
<li><a href="#name">NAME</a></li>
|
||
<li><a href="#synopsis">SYNOPSIS</a></li>
|
||
<li><a href="#global-options">GLOBAL OPTIONS</a></li>
|
||
<li><a href="#commands">COMMANDS</a><ul>
|
||
<li><a href="#server">server</a></li>
|
||
<li><a href="#client">client</a></li>
|
||
<li><a href="#wsserver">wsserver</a></li>
|
||
<li><a href="#wsclient">wsclient</a></li>
|
||
<li><a href="#wssserver">wssserver</a></li>
|
||
<li><a href="#wssclient">wssclient</a></li>
|
||
<li><a href="#quicserver">quicserver</a></li>
|
||
<li><a href="#quicclient">quicclient</a></li>
|
||
<li><a href="#relayoverbrook">relayoverbrook</a></li>
|
||
<li><a href="#dnsserveroverbrook">dnsserveroverbrook</a></li>
|
||
<li><a href="#link">link</a></li>
|
||
<li><a href="#connect">connect</a></li>
|
||
<li><a href="#relay">relay</a></li>
|
||
<li><a href="#dnsserver">dnsserver</a></li>
|
||
<li><a href="#dnsclient">dnsclient</a></li>
|
||
<li><a href="#dohserver">dohserver</a></li>
|
||
<li><a href="#dohclient">dohclient</a></li>
|
||
<li><a href="#dhcpserver">dhcpserver</a></li>
|
||
<li><a href="#socks5">socks5</a></li>
|
||
<li><a href="#socks5tohttp">socks5tohttp</a></li>
|
||
<li><a href="#pac">pac</a></li>
|
||
<li><a href="#testsocks5">testsocks5</a></li>
|
||
<li><a href="#testbrook">testbrook</a></li>
|
||
<li><a href="#echoserver">echoserver</a></li>
|
||
<li><a href="#echoclient">echoclient</a></li>
|
||
<li><a href="#ipcountry">ipcountry</a></li>
|
||
<li><a href="#completion">completion</a></li>
|
||
<li><a href="#mdpage">mdpage</a><ul>
|
||
<li><a href="#help-h">help, h</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#manpage">manpage</a></li>
|
||
<li><a href="#help-h-1">help, h</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#examples">Examples</a><ul>
|
||
<li><a href="#run-brook-server">Run brook server</a></li>
|
||
<li><a href="#run-brook-wsserver">Run brook wsserver</a></li>
|
||
<li><a href="#run-brook-wssserver-automatically-certificate">Run brook wssserver: automatically certificate</a></li>
|
||
<li><a href="#run-brook-wssserver-use-a-certificate-issued-by-an-existing-trust-authority">Run brook wssserver Use a certificate issued by an existing trust authority</a></li>
|
||
<li><a href="#run-brook-wssserver-issue-untrusted-certificates-yourself-any-domain">Run brook wssserver issue untrusted certificates yourself, any domain</a></li>
|
||
<li><a href="#withoutbrookprotocol">withoutBrookProtocol</a></li>
|
||
<li><a href="#withoutbrookprotocol-automatically-certificate">withoutBrookProtocol automatically certificate</a></li>
|
||
<li><a href="#withoutbrookprotocol-use-a-certificate-issued-by-an-existing-trust-authority">withoutBrookProtocol Use a certificate issued by an existing trust authority</a></li>
|
||
<li><a href="#withoutbrookprotocol-issue-untrusted-certificates-yourself-any-domain">withoutBrookProtocol issue untrusted certificates yourself, any domain</a></li>
|
||
<li><a href="#run-brook-socks5-a-stand-alone-standard-socks5-server">Run brook socks5, A stand-alone standard socks5 server</a></li>
|
||
<li><a href="#run-brook-socks5-with-username-and-password-a-stand-alone-standard-socks5-server">Run brook socks5 with username and password. A stand-alone standard socks5 server</a></li>
|
||
<li><a href="#brook-relayoverbrook-can-relay-a-local-address-to-a-remote-address-over-brook-both-tcp-and-udp-it-works-with-brook-server-wsserver-wssserver">brook relayoverbrook can relay a local address to a remote address over brook, both TCP and UDP, it works with brook server wsserver wssserver.</a></li>
|
||
<li><a href="#brook-dnsserveroverbrook-can-create-a-encrypted-dns-server-both-tcp-and-udp-it-works-with-brook-server-wsserver-wssserver">brook dnsserveroverbrook can create a encrypted DNS server, both TCP and UDP, it works with brook server wsserver wssserver.</a></li>
|
||
<li><a href="#brook-openwrt-router-perfectly-supports-ipv4ipv6tcpudp-native-ipv6">Brook OpenWRT Router: Perfectly supports IPv4/IPv6/TCP/UDP. Native IPv6</a></li>
|
||
<li><a href="#turn-macos-into-a-gateway-with-brook">Turn macOS into a Gateway with Brook</a></li>
|
||
<li><a href="#turn-windows-into-a-gateway-with-brook">Turn Windows into a Gateway with Brook</a></li>
|
||
<li><a href="#turn-linux-into-a-gateway-with-brook">Turn Linux into a Gateway with Brook</a></li>
|
||
<li><a href="#brook-relay-can-relay-a-address-to-a-remote-address-it-can-relay-any-tcp-and-udp-server">brook relay can relay a address to a remote address. It can relay any tcp and udp server</a></li>
|
||
<li><a href="#brook-socks5tohttp-can-convert-a-socks5-to-a-http-proxy">brook socks5tohttp can convert a socks5 to a http proxy</a></li>
|
||
<li><a href="#brook-pac-creates-pac-server">brook pac creates pac server</a></li>
|
||
<li><a href="#brook-pac-creates-pac-file">brook pac creates pac file</a></li>
|
||
<li><a href="#there-are-countless-examples-for-more-feature-suggestions-its-best-to-look-at-the-commands-and-parameters-in-the-cli-documentation-one-by-one-and-blog-youtube">There are countless examples; for more feature suggestions, it's best to look at the commands and parameters in the CLI documentation one by one, and blog, YouTube...</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#diagram">Diagram</a><ul>
|
||
<li><a href="#overview">overview</a></li>
|
||
<li><a href="#withoutbrookprotocol-1">withoutBrookProtocol</a></li>
|
||
<li><a href="#relayoverbrook-1">relayoverbrook</a></li>
|
||
<li><a href="#dnsserveroverbrook-1">dnsserveroverbrook</a></li>
|
||
<li><a href="#relay-1">relay</a></li>
|
||
<li><a href="#dnsserver-1">dnsserver</a></li>
|
||
<li><a href="#tproxy">tproxy</a></li>
|
||
<li><a href="#gui">gui</a></li>
|
||
<li><a href="#script">script</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
</div>
|
||
<!--SIDEBAR-->
|
||
<!--G-R3M673HK5V-->
|
||
<p>A cross-platform programmable network tool.</p>
|
||
<h1 id="sponsor">Sponsor</h1>
|
||
<p><strong>❤️ <a href="https://www.txthinking.com/shiliew.html">Shiliew - China Optimized Network App</a></strong></p>
|
||
<h1 id="getting-started">Getting Started</h1>
|
||
<h2 id="server">Server</h2>
|
||
<pre><code>bash <(curl https://bash.ooo/nami.sh)
|
||
</code></pre>
|
||
<pre><code>nami install brook
|
||
</code></pre>
|
||
<pre><code>brook server -l :9999 -p hello
|
||
</code></pre>
|
||
<h2 id="gui-client">GUI Client</h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>iOS</th>
|
||
<th>Android</th>
|
||
<th>Mac</th>
|
||
<th>Windows</th>
|
||
<th>Linux</th>
|
||
<th>OpenWrt</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td><a href="https://apps.apple.com/us/app/brook-network-tool/id1216002642"><img src="https://brook.app/images/appstore.png" alt=""></a></td>
|
||
<td><a href="https://github.com/txthinking/brook/releases/latest/download/Brook.apk"><img src="https://brook.app/images/android.png" alt=""></a></td>
|
||
<td><a href="https://apps.apple.com/us/app/brook-network-tool/id1216002642"><img src="https://brook.app/images/mac.png" alt=""></a></td>
|
||
<td><a href="https://github.com/txthinking/brook/releases/latest/download/Brook.msix"><img src="https://brook.app/images/windows.png" alt="Windows"></a></td>
|
||
<td><a href="https://github.com/txthinking/brook/releases/latest/download/Brook.bin"><img src="https://brook.app/images/linux.png" alt=""></a></td>
|
||
<td><a href="https://github.com/txthinking/brook/releases"><img src="https://brook.app/images/openwrt.png" alt="OpenWrt"></a></td>
|
||
</tr>
|
||
<tr>
|
||
<td>/</td>
|
||
<td>/</td>
|
||
<td><a href="https://www.txthinking.com/talks/articles/macos-app-mode-en.article">App Mode</a></td>
|
||
<td><a href="https://www.txthinking.com/talks/articles/msix-brook-en.article">How</a></td>
|
||
<td><a href="https://www.txthinking.com/talks/articles/linux-app-brook-en.article">How</a></td>
|
||
<td><a href="https://www.txthinking.com/talks/articles/brook-openwrt-en.article">How</a></td>
|
||
</tr>
|
||
</tbody></table>
|
||
<h2 id="cli-client">CLI Client</h2>
|
||
<pre><code>brook client -s 1.2.3.4:9999 -p hello --socks5 127.0.0.1:1080
|
||
</code></pre>
|
||
<h1 id="gui-documentation">GUI Documentation</h1>
|
||
<h2 id="software-for-which-this-article-applies">Software for which this article applies</h2>
|
||
<ul>
|
||
<li><a href="https://github.com/txthinking/brook">Brook</a></li>
|
||
<li><a href="https://www.txthinking.com/shiliew.html">Shiliew</a></li>
|
||
<li><a href="https://github.com/txthinking/tun2brook">tun2brook</a></li>
|
||
</ul>
|
||
<h2 id="programmable">Programmable</h2>
|
||
<pre><code>Brook GUI will pass different global variables to the script at different times, and the script only needs to assign the processing result to the global variable out
|
||
</code></pre>
|
||
<h3 id="introduction-to-incoming-variables">Introduction to incoming variables</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>variable</th>
|
||
<th>type</th>
|
||
<th>condition</th>
|
||
<th>timing</th>
|
||
<th>description</th>
|
||
<th>out type</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td>in_brooklinks</td>
|
||
<td>map</td>
|
||
<td>/</td>
|
||
<td>Before connecting</td>
|
||
<td>Predefine multiple brook links, and then programmatically specify which one to connect to</td>
|
||
<td>map</td>
|
||
</tr>
|
||
<tr>
|
||
<td>in_dnsquery</td>
|
||
<td>map</td>
|
||
<td>FakeDNS: On</td>
|
||
<td>When a DNS query occurs</td>
|
||
<td>Script can decide how to handle this request</td>
|
||
<td>map</td>
|
||
</tr>
|
||
<tr>
|
||
<td>in_address</td>
|
||
<td>map</td>
|
||
<td>/</td>
|
||
<td>When connecting to an address</td>
|
||
<td>script can decide how to connect</td>
|
||
<td>map</td>
|
||
</tr>
|
||
<tr>
|
||
<td>in_httprequest</td>
|
||
<td>map</td>
|
||
<td>/</td>
|
||
<td>When an HTTP(S) request comes in</td>
|
||
<td>the script can decide how to handle this request</td>
|
||
<td>map</td>
|
||
</tr>
|
||
<tr>
|
||
<td>in_httprequest,in_httpresponse</td>
|
||
<td>map</td>
|
||
<td>/</td>
|
||
<td>when an HTTP(S) response comes in</td>
|
||
<td>the script can decide how to handle this response</td>
|
||
<td>map</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<h3 id="in_brooklinks">in_brooklinks</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Key</th>
|
||
<th>Type</th>
|
||
<th>Description</th>
|
||
<th>Example</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td>_</td>
|
||
<td>bool</td>
|
||
<td>meaningless</td>
|
||
<td>true</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<p><code>out</code>, ignored if not of type <code>map</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Key</th>
|
||
<th>Type</th>
|
||
<th>Description</th>
|
||
<th>Example</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td>...</td>
|
||
<td>...</td>
|
||
<td>...</td>
|
||
<td>...</td>
|
||
</tr>
|
||
<tr>
|
||
<td>custom name</td>
|
||
<td>string</td>
|
||
<td>brook link</td>
|
||
<td>brook://...</td>
|
||
</tr>
|
||
<tr>
|
||
<td>...</td>
|
||
<td>...</td>
|
||
<td>...</td>
|
||
<td>...</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<h3 id="in_dnsquery">in_dnsquery</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Key</th>
|
||
<th>Type</th>
|
||
<th>Description</th>
|
||
<th>Example</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td>domain</td>
|
||
<td>string</td>
|
||
<td>domain name</td>
|
||
<td>google.com</td>
|
||
</tr>
|
||
<tr>
|
||
<td>type</td>
|
||
<td>string</td>
|
||
<td>query type</td>
|
||
<td>A</td>
|
||
</tr>
|
||
<tr>
|
||
<td>appid</td>
|
||
<td>string</td>
|
||
<td>App ID or path</td>
|
||
<td>com.google.Chrome.helper</td>
|
||
</tr>
|
||
<tr>
|
||
<td>interface</td>
|
||
<td>string</td>
|
||
<td>network interface. Mac only</td>
|
||
<td>en0</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<p><code>out</code>, if it is <code>error</code> type will be recorded in the log. Ignored if not of type <code>map</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Key</th>
|
||
<th>Type</th>
|
||
<th>Description</th>
|
||
<th>Example</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td>block</td>
|
||
<td>bool</td>
|
||
<td>Whether Block, default <code>false</code></td>
|
||
<td>false</td>
|
||
</tr>
|
||
<tr>
|
||
<td>ip</td>
|
||
<td>string</td>
|
||
<td>Specify IP directly, only valid when <code>type</code> is <code>A</code>/<code>AAAA</code></td>
|
||
<td>1.2.3.4</td>
|
||
</tr>
|
||
<tr>
|
||
<td>system</td>
|
||
<td>bool</td>
|
||
<td>Resolve by System DNS, default <code>false</code></td>
|
||
<td>false</td>
|
||
</tr>
|
||
<tr>
|
||
<td>bypass</td>
|
||
<td>bool</td>
|
||
<td>Resolve by Bypass DNS, default <code>false</code></td>
|
||
<td>false</td>
|
||
</tr>
|
||
<tr>
|
||
<td>brooklinkkey</td>
|
||
<td>string</td>
|
||
<td>When need to connect the Server,instead, connect to the Server specified by the key in_brooklinks</td>
|
||
<td>custom name</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<h3 id="in_address">in_address</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Key</th>
|
||
<th>Type</th>
|
||
<th>Description</th>
|
||
<th>Example</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td>network</td>
|
||
<td>string</td>
|
||
<td>Network type, the value <code>tcp</code>/<code>udp</code></td>
|
||
<td>tcp</td>
|
||
</tr>
|
||
<tr>
|
||
<td>ipaddress</td>
|
||
<td>string</td>
|
||
<td>IP type address. There is only of ipaddress and domainaddress. Note that there is no relationship between these two</td>
|
||
<td>1.2.3.4:443</td>
|
||
</tr>
|
||
<tr>
|
||
<td>domainaddress</td>
|
||
<td>string</td>
|
||
<td>Domain type address, because of FakeDNS we can get the domain name address here</td>
|
||
<td>google.com:443</td>
|
||
</tr>
|
||
<tr>
|
||
<td>appid</td>
|
||
<td>string</td>
|
||
<td>App ID or path</td>
|
||
<td>com.google.Chrome.helper</td>
|
||
</tr>
|
||
<tr>
|
||
<td>interface</td>
|
||
<td>string</td>
|
||
<td>network interface. Mac only</td>
|
||
<td>en0</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<p><code>out</code>, if it is <code>error</code> type will be recorded in the log. Ignored if not of type <code>map</code></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Key</th>
|
||
<th>Type</th>
|
||
<th>Description</th>
|
||
<th>Example</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td>block</td>
|
||
<td>bool</td>
|
||
<td>Whether Block, default <code>false</code></td>
|
||
<td>false</td>
|
||
</tr>
|
||
<tr>
|
||
<td>ipaddress</td>
|
||
<td>string</td>
|
||
<td>IP type address, rewrite destination</td>
|
||
<td>1.2.3.4:443</td>
|
||
</tr>
|
||
<tr>
|
||
<td>ipaddressfrombypassdns</td>
|
||
<td>string</td>
|
||
<td>Use Bypass DNS to obtain <code>A</code> or <code>AAAA</code> IP and rewrite the destination, only valid when <code>domainaddress</code> exists, the value <code>A</code>/<code>AAAA</code></td>
|
||
<td>A</td>
|
||
</tr>
|
||
<tr>
|
||
<td>bypass</td>
|
||
<td>bool</td>
|
||
<td>Bypass, default <code>false</code>. If <code>true</code> and <code>domainaddress</code>, then <code>ipaddress</code> or <code>ipaddressfrombypassdns</code> must be specified</td>
|
||
<td>false</td>
|
||
</tr>
|
||
<tr>
|
||
<td>mitm</td>
|
||
<td>bool</td>
|
||
<td>Whether to perform MITM, default <code>false</code>. Only valid when <code>network</code> is <code>tcp</code>. Need to install CA, see below</td>
|
||
<td>false</td>
|
||
</tr>
|
||
<tr>
|
||
<td>mitmprotocol</td>
|
||
<td>string</td>
|
||
<td>MITM protocol needs to be specified explicitly, the value is <code>http</code>/<code>https</code></td>
|
||
<td>https</td>
|
||
</tr>
|
||
<tr>
|
||
<td>mitmcertdomain</td>
|
||
<td>string</td>
|
||
<td>The MITM certificate domain name, which is taken from <code>domainaddress</code> by default. If <code>ipaddress</code> and <code>mitm</code> is <code>true</code> and <code>mitmprotocol</code> is <code>https</code> then must be must be specified explicitly</td>
|
||
<td>example.com</td>
|
||
</tr>
|
||
<tr>
|
||
<td>mitmwithbody</td>
|
||
<td>bool</td>
|
||
<td>Whether to manipulate the http body, default <code>false</code>. will read the body of the request and response into the memory and interact with the script. iOS 50M total memory limit may kill process</td>
|
||
<td>false</td>
|
||
</tr>
|
||
<tr>
|
||
<td>mitmautohandlecompress</td>
|
||
<td>bool</td>
|
||
<td>Whether to automatically decompress the http body when interacting with the script, default <code>false</code></td>
|
||
<td>false</td>
|
||
</tr>
|
||
<tr>
|
||
<td>mitmclienttimeout</td>
|
||
<td>int</td>
|
||
<td>Timeout for MITM talk to server, second, default 0</td>
|
||
<td>0</td>
|
||
</tr>
|
||
<tr>
|
||
<td>mitmserverreadtimeout</td>
|
||
<td>int</td>
|
||
<td>Timeout for MITM read from client, second, default 0</td>
|
||
<td>0</td>
|
||
</tr>
|
||
<tr>
|
||
<td>mitmserverwritetimeout</td>
|
||
<td>int</td>
|
||
<td>Timeout for MITM write to client, second, default 0</td>
|
||
<td>0</td>
|
||
</tr>
|
||
<tr>
|
||
<td>brooklinkkey</td>
|
||
<td>string</td>
|
||
<td>When need to connect the Server,instead, connect to the Server specified by the key in_brooklinks</td>
|
||
<td>custom name</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<h3 id="in_httprequest">in_httprequest</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Key</th>
|
||
<th>Type</th>
|
||
<th>Description</th>
|
||
<th>Example</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td>URL</td>
|
||
<td>string</td>
|
||
<td>URL</td>
|
||
<td><code>https://example.com/hello</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Method</td>
|
||
<td>string</td>
|
||
<td>HTTP method</td>
|
||
<td>GET</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Body</td>
|
||
<td>bytes</td>
|
||
<td>HTTP request body</td>
|
||
<td>/</td>
|
||
</tr>
|
||
<tr>
|
||
<td>...</td>
|
||
<td>string</td>
|
||
<td>other fields are HTTP headers</td>
|
||
<td>/</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<p><code>out</code>, must be set to a request or response</p>
|
||
<h3 id="in_httpresponse">in_httpresponse</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Key</th>
|
||
<th>Type</th>
|
||
<th>Description</th>
|
||
<th>Example</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td>StatusCode</td>
|
||
<td>int</td>
|
||
<td>HTTP status code</td>
|
||
<td>200</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Body</td>
|
||
<td>bytes</td>
|
||
<td>HTTP response body</td>
|
||
<td>/</td>
|
||
</tr>
|
||
<tr>
|
||
<td>...</td>
|
||
<td>string</td>
|
||
<td>other fields are HTTP headers</td>
|
||
<td>/</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<p><code>out</code>, must be set to a response</p>
|
||
<h2 id="write-script">Write script</h2>
|
||
<p><a href="https://github.com/d5/tengo/blob/master/docs/tutorial.md">Tengo Language Syntax</a></p>
|
||
<p>Library</p>
|
||
<ul>
|
||
<li><p><a href="https://github.com/d5/tengo/blob/master/docs/stdlib-text.md">text</a>: regular expressions, string conversion, and manipulation</p>
|
||
</li>
|
||
<li><p><a href="https://github.com/d5/tengo/blob/master/docs/stdlib-math.md">math</a>: mathematical constants and functions</p>
|
||
</li>
|
||
<li><p><a href="https://github.com/d5/tengo/blob/master/docs/stdlib-times.md">times</a>: time-related functions</p>
|
||
</li>
|
||
<li><p><a href="https://github.com/d5/tengo/blob/master/docs/stdlib-rand.md">rand</a>: random functions</p>
|
||
</li>
|
||
<li><p><a href="https://github.com/d5/tengo/blob/master/docs/stdlib-fmt.md">fmt</a>: formatting functions</p>
|
||
</li>
|
||
<li><p><a href="https://github.com/d5/tengo/blob/master/docs/stdlib-json.md">json</a>: JSON functions</p>
|
||
</li>
|
||
<li><p><a href="https://github.com/d5/tengo/blob/master/docs/stdlib-enum.md">enum</a>: Enumeration functions</p>
|
||
</li>
|
||
<li><p><a href="https://github.com/d5/tengo/blob/master/docs/stdlib-hex.md">hex</a>: hex encoding and decoding functions</p>
|
||
</li>
|
||
<li><p><a href="https://github.com/d5/tengo/blob/master/docs/stdlib-base64.md">base64</a>: base64 encoding and decoding functions</p>
|
||
</li>
|
||
<li><p><code>brook</code>: brook module</p>
|
||
<pre><code>Constants
|
||
|
||
* os: string, linux/darwin/windows/ios/android
|
||
|
||
Functions
|
||
|
||
* splithostport(address string) => map/error: splits a network address of the form "host:port" to { "host": "xxx", "port": "xxx" }
|
||
* country(ip string) => string/error: get country code from ip
|
||
* cidrcontainsip(cidr string, ip string) => bool/error: reports whether the network includes ip
|
||
* parseurl(url string) => map/error: parses a raw url into a map, keys: scheme/host/path/rawpath/rawquery
|
||
* parsequery(query string) => map/error: parses a raw query into a kv map
|
||
* map2query(kv map) => string/error: convert map{string:string} into a query string
|
||
* bytes2ints(b bytes) => array/error: convert bytes into [int]
|
||
* ints2bytes(ints array) => bytes/error: convert [int] into bytes
|
||
* bytescompare(a bytes, b bytes) => int/error: returns an integer comparing two bytes lexicographically. The result will be 0 if a == b, -1 if a < b, and +1 if a > b
|
||
* bytescontains(b bytes, sub bytes) => bool/error: reports whether sub is within b
|
||
* byteshasprefix(s bytes, prefix bytes) => bool/error: tests whether the bytes s begins with prefix
|
||
* byteshassuffix(s bytes, suffix bytes) => bool/error: tests whether the bytes s ends with suffix
|
||
* bytesindex(s bytes, sep bytes) => int/error: returns the index of the first instance of sep in s, or -1 if sep is not present in s
|
||
* byteslastindex(s bytes, sep bytes) => int/error: returns the index of the last instance of sep in s, or -1 if sep is not present in s
|
||
* bytesreplace(s bytes, old bytes, new bytes, n int) => bytes/error: returns a copy of the s with the first n non-overlapping instances of old replaced by new. If n < 0, there is no limit on the number of replacements
|
||
* pathescape(s string) => string/error: escapes the string so it can be safely placed inside a URL path segment, replacing special characters (including /) with %XX sequences as needed
|
||
* pathunescape(s string) => string/error: does the inverse transformation of pathescape
|
||
* queryescape(s string) => string/error: escapes the string so it can be safely placed inside a URL query
|
||
* queryunescape(s string) => string/error: does the inverse transformation of queryescape
|
||
* hexdecode(s string) => bytes/error: returns the bytes represented by the hexadecimal string s
|
||
* hexencode(s string) => string/error: returns the hexadecimal encoding of src
|
||
</code></pre>
|
||
</li>
|
||
</ul>
|
||
<h2 id="debug-script">Debug script</h2>
|
||
<p>It is recommended to use <a href="https://github.com/txthinking/tun2brook">tun2brook</a> on desktop to debug with <code>fmt.println</code></p>
|
||
<h2 id="install-ca">Install CA</h2>
|
||
<p><a href="https://txthinking.github.io/ca/ca.pem">https://txthinking.github.io/ca/ca.pem</a></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>OS</th>
|
||
<th>How</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td>iOS</td>
|
||
<td><a href="https://www.youtube.com/watch?v=HSGPC2vpDGk">https://www.youtube.com/watch?v=HSGPC2vpDGk</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Android</td>
|
||
<td>Android has user CA and system CA, must be installed in the system CA after ROOT</td>
|
||
</tr>
|
||
<tr>
|
||
<td>macOS</td>
|
||
<td><code>nami install mad ca.txthinking</code>, <code>sudo mad install --ca ~/.nami/bin/ca.pem</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Windows</td>
|
||
<td><code>nami install mad ca.txthinking</code>, Admin: <code>mad install --ca ~/.nami/bin/ca.pem</code></td>
|
||
</tr>
|
||
</tbody></table>
|
||
<blockquote>
|
||
<p>Some software may not read the system CA,you can use <code>curl --cacert ~/.nami/bin/ca.pem</code> to debug</p>
|
||
</blockquote>
|
||
<h1 id="resources">Resources</h1>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>CLI</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td><a href="https://github.com/txthinking/nami">nami</a></td>
|
||
<td>A clean and tidy decentralized package manager</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking/joker">joker</a></td>
|
||
<td>Joker can turn process into daemon. Zero-Configuration</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking/nico">nico</a></td>
|
||
<td>Nico can work with brook wsserver together</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking/zhen">zhen</a></td>
|
||
<td>zhen - process and cron manager</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking/tun2brook">tun2brook</a></td>
|
||
<td>Proxy all traffic just one line command</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking/mad">mad</a></td>
|
||
<td>Generate root CA and derivative certificate for any domains and any IPs</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking/hancock">hancock</a></td>
|
||
<td>Manage multiple remote servers and execute commands remotely</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking/sshexec">sshexec</a></td>
|
||
<td>A command-line tool to execute remote command through ssh</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking/jb">jb</a></td>
|
||
<td>write script in an easier way than bash</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking/bash">bash</a></td>
|
||
<td>Many one-click scripts</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://archlinux.org/packages/extra/x86_64/brook/">pacman</a></td>
|
||
<td><code>pacman -S brook</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://formulae.brew.sh/formula/brook">brew</a></td>
|
||
<td><code>brew install brook</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://hub.docker.com/r/txthinking/brook">docker</a></td>
|
||
<td><code>docker run txthinking/brook</code></td>
|
||
</tr>
|
||
</tbody></table>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Resources</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td><a href="https://github.com/txthinking/brook/tree/master/protocol">Protocol</a></td>
|
||
<td>Brook Protocol</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://www.txthinking.com/talks/">Blog</a></td>
|
||
<td>Some articles you should read</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://www.youtube.com/txthinking">YouTube</a></td>
|
||
<td>Some videos you should watch</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://t.me/txthinking">Telegram</a></td>
|
||
<td>Ask questions here</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://t.me/s/txthinking_news">Announce</a></td>
|
||
<td>All news you should care</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking">GitHub</a></td>
|
||
<td>Other useful repos</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://chromewebstore.google.com/detail/socks5-configurator/hnpgnjkeaobghpjjhaiemlahikgmnghb">Socks5 Configurator</a></td>
|
||
<td>If you prefer CLI brook client</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://chromewebstore.google.com/detail/ipvbar/nepjlegfiihpkcdhlmaebfdfppckonlj">IPvBar</a></td>
|
||
<td>See domain, IP and country in browser</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://www.txthinking.com/ssh.html">TxThinking SSH</a></td>
|
||
<td>A SSH Terminal</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://www.txthinking.com/deploy.html">Brook Deploy</a></td>
|
||
<td>Deploy brook with GUI</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://github.com/txthinking/brook-manager">brook-manager</a></td>
|
||
<td>Brook Manager is a Brook management system for medium to large merchants</td>
|
||
</tr>
|
||
<tr>
|
||
<td><a href="https://www.txthinking.com">TxThinking</a></td>
|
||
<td>Everything</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<h1 id="cli-documentation">CLI Documentation</h1>
|
||
<h1 id="name">NAME</h1>
|
||
<p>Brook - A cross-platform programmable network tool</p>
|
||
<h1 id="synopsis">SYNOPSIS</h1>
|
||
<p>Brook</p>
|
||
<pre><code>brook --help
|
||
</code></pre>
|
||
<p><strong>Usage</strong>:</p>
|
||
<pre><code>Brook [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
|
||
</code></pre>
|
||
<h1 id="global-options">GLOBAL OPTIONS</h1>
|
||
<ul>
|
||
<li><p><strong>--clientHKDFInfo</strong>="": client HKDF info, most time you don't need to change this, if changed, all and each brook links in client side must be same, I mean each (default: "brook")</p>
|
||
</li>
|
||
<li><p><strong>--dialWithDNS</strong>="": When a domain name needs to be resolved, use the specified DNS. Such as 8.8.8.8:53 or <a href="https://dns.google/dns-query?address=8.8.8.8%3A443">https://dns.google/dns-query?address=8.8.8.8%3A443</a>, the address is required. Note that for client-side commands, this does not affect the client passing the domain address to the server</p>
|
||
</li>
|
||
<li><p><strong>--dialWithDNSPrefer</strong>="": This is used with the dialWithDNS parameter. Prefer A record or AAAA record. Value is A or AAAA</p>
|
||
</li>
|
||
<li><p><strong>--dialWithIP4</strong>="": When the current machine establishes a network connection to the outside IPv4, both TCP and UDP, it is used to specify the IPv4 used</p>
|
||
</li>
|
||
<li><p><strong>--dialWithIP6</strong>="": When the current machine establishes a network connection to the outside IPv6, both TCP and UDP, it is used to specify the IPv6 used</p>
|
||
</li>
|
||
<li><p><strong>--dialWithNIC</strong>="": When the current machine establishes a network connection to the outside, both TCP and UDP, it is used to specify the NIC used</p>
|
||
</li>
|
||
<li><p><strong>--dialWithSocks5</strong>="": When the current machine establishes a network connection to the outside, both TCP and UDP, with your socks5 proxy, such as 127.0.0.1:1081</p>
|
||
</li>
|
||
<li><p><strong>--dialWithSocks5Password</strong>="": If there is</p>
|
||
</li>
|
||
<li><p><strong>--dialWithSocks5TCPTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--dialWithSocks5UDPTimeout</strong>="": time (s) (default: 60)</p>
|
||
</li>
|
||
<li><p><strong>--dialWithSocks5Username</strong>="": If there is</p>
|
||
</li>
|
||
<li><p><strong>--help, -h</strong>: show help</p>
|
||
</li>
|
||
<li><p><strong>--ipLimitInterval</strong>="": Interval (s) for ipLimitMax (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--ipLimitMax</strong>="": Limit the number of client IP addresses, be careful when using this parameter, as the client may have dynamic IP. Works with server/wsserver/wssserver/quicserver (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--ipLimitWait</strong>="": How long (s) to wait for recovery after exceeding ipLimitMax (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--log</strong>="": Enable log. A valid value is file path or 'console'. If you want to debug SOCKS5 lib, set env SOCKS5_DEBUG=true</p>
|
||
</li>
|
||
<li><p><strong>--pprof</strong>="": go http pprof listen addr, such as :6060</p>
|
||
</li>
|
||
<li><p><strong>--prometheus</strong>="": prometheus http listen addr, such as :7070. If it is transmitted on the public network, it is recommended to use it with nico</p>
|
||
</li>
|
||
<li><p><strong>--prometheusPath</strong>="": prometheus http path, such as /xxx. If it is transmitted on the public network, a hard-to-guess value is recommended</p>
|
||
</li>
|
||
<li><p><strong>--serverHKDFInfo</strong>="": server HKDF info, most time you don't need to change this, if changed, all and each brook links in client side must be same, I mean each (default: "brook")</p>
|
||
</li>
|
||
<li><p><strong>--serverLog</strong>="": Enable server log, traffic and more. A valid value is file path or 'console'. Mutually exclusive with the --log parameter. Works with server/wsserver/wssserver/quicserver</p>
|
||
</li>
|
||
<li><p><strong>--speedLimit</strong>="": Limit speed (b), such as 500kb/s: 500000, works with server/wsserver/wssserver/quicserver (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--tag</strong>="": Tag can be used to the process, will be append into log or serverLog, such as: 'key1:value1'</p>
|
||
</li>
|
||
<li><p><strong>--version, -v</strong>: print the version</p>
|
||
</li>
|
||
</ul>
|
||
<h1 id="commands">COMMANDS</h1>
|
||
<h2 id="server-1">server</h2>
|
||
<p>Run as brook server, both TCP and UDP</p>
|
||
<ul>
|
||
<li><p><strong>--blockCIDR4List</strong>="": One CIDR per line, https://, http:// or local file absolute path, like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr4.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr4.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockCIDR6List</strong>="": One CIDR per line, https://, http:// or local file absolute path, like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr6.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr6.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockDomainList</strong>="": One domain per line, suffix match mode. https://, http:// or local file absolute path. Like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockGeoIP</strong>="": Block IP by Geo country code, such as US</p>
|
||
</li>
|
||
<li><p><strong>--listen, -l</strong>="": Listen address, like: ':9999'</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Server password</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--updateListInterval</strong>="": Update list interval, second. default 0, only read one time on start (default: 0)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="client">client</h2>
|
||
<p>Run as brook client, both TCP and UDP, to start a socks5 proxy, [src <-> socks5 <-> $ brook client <-> $ brook server <-> dst]</p>
|
||
<ul>
|
||
<li><p><strong>--http</strong>="": Where to listen for HTTP proxy connections</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Brook server password</p>
|
||
</li>
|
||
<li><p><strong>--server, -s</strong>="": Brook server address, like: 1.2.3.4:9999</p>
|
||
</li>
|
||
<li><p><strong>--socks5</strong>="": Where to listen for SOCKS5 connections (default: 127.0.0.1:1080)</p>
|
||
</li>
|
||
<li><p><strong>--socks5ServerIP</strong>="": Only if your socks5 server IP is different from listen IP</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpovertcp</strong>: UDP over TCP</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="wsserver">wsserver</h2>
|
||
<p>Run as brook wsserver, both TCP and UDP, it will start a standard http server and websocket server</p>
|
||
<ul>
|
||
<li><p><strong>--blockCIDR4List</strong>="": One CIDR per line, https://, http:// or local file absolute path, like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr4.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr4.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockCIDR6List</strong>="": One CIDR per line, https://, http:// or local file absolute path, like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr6.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr6.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockDomainList</strong>="": One domain per line, suffix match mode. https://, http:// or local file absolute path. Like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockGeoIP</strong>="": Block IP by Geo country code, such as US</p>
|
||
</li>
|
||
<li><p><strong>--listen, -l</strong>="": Listen address, like: ':80'</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Server password</p>
|
||
</li>
|
||
<li><p><strong>--path</strong>="": URL path (default: /ws)</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--updateListInterval</strong>="": Update list interval, second. default 0, only read one time on start (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--withoutBrookProtocol</strong>: The data will not be encrypted with brook protocol</p>
|
||
</li>
|
||
<li><p><strong>--xForwardedFor</strong>: Replace the from field in --log, note that this may be forged</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="wsclient">wsclient</h2>
|
||
<p>Run as brook wsclient, both TCP and UDP, to start a socks5 proxy, [src <-> socks5 <-> $ brook wsclient <-> $ brook wsserver <-> dst]</p>
|
||
<ul>
|
||
<li><p><strong>--address</strong>="": Specify address instead of resolving addresses from host, such as 1.2.3.4:443</p>
|
||
</li>
|
||
<li><p><strong>--http</strong>="": Where to listen for HTTP proxy connections</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Brook wsserver password</p>
|
||
</li>
|
||
<li><p><strong>--socks5</strong>="": Where to listen for SOCKS5 connections (default: 127.0.0.1:1080)</p>
|
||
</li>
|
||
<li><p><strong>--socks5ServerIP</strong>="": Only if your socks5 server IP is different from listen IP</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--withoutBrookProtocol</strong>: The data will not be encrypted with brook protocol</p>
|
||
</li>
|
||
<li><p><strong>--wsserver, -s</strong>="": Brook wsserver address, like: ws://1.2.3.4:80, if no path then /ws will be used. Do not omit the port under any circumstances</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="wssserver">wssserver</h2>
|
||
<p>Run as brook wssserver, both TCP and UDP, it will start a standard https server and websocket server</p>
|
||
<ul>
|
||
<li><p><strong>--blockCIDR4List</strong>="": One CIDR per line, https://, http:// or local file absolute path, like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr4.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr4.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockCIDR6List</strong>="": One CIDR per line, https://, http:// or local file absolute path, like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr6.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr6.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockDomainList</strong>="": One domain per line, suffix match mode. https://, http:// or local file absolute path. Like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockGeoIP</strong>="": Block IP by Geo country code, such as US</p>
|
||
</li>
|
||
<li><p><strong>--cert</strong>="": The cert file absolute path for the domain, such as /path/to/cert.pem. If cert or certkey is empty, a certificate will be issued automatically</p>
|
||
</li>
|
||
<li><p><strong>--certkey</strong>="": The cert key file absolute path for the domain, such as /path/to/certkey.pem. If cert or certkey is empty, a certificate will be issued automatically</p>
|
||
</li>
|
||
<li><p><strong>--domainaddress</strong>="": Such as: domain.com:443. If you choose to automatically issue certificates, the domain must have been resolved to the server IP and 80 port also will be used</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Server password</p>
|
||
</li>
|
||
<li><p><strong>--path</strong>="": URL path (default: /ws)</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--updateListInterval</strong>="": Update list interval, second. default 0, only read one time on start (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--withoutBrookProtocol</strong>: The data will not be encrypted with brook protocol</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="wssclient">wssclient</h2>
|
||
<p>Run as brook wssclient, both TCP and UDP, to start a socks5 proxy, [src <-> socks5 <-> $ brook wssclient <-> $ brook wssserver <-> dst]</p>
|
||
<ul>
|
||
<li><p><strong>--http</strong>="": Where to listen for HTTP proxy connections</p>
|
||
</li>
|
||
<li><p><strong>--link</strong>="": brook link, you can get it via $ brook link. The wssserver and password parameters will be ignored</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Brook wssserver password</p>
|
||
</li>
|
||
<li><p><strong>--socks5</strong>="": Where to listen for SOCKS5 connections (default: 127.0.0.1:1080)</p>
|
||
</li>
|
||
<li><p><strong>--socks5ServerIP</strong>="": Only if your socks5 server IP is different from listen IP</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--wssserver, -s</strong>="": Brook wssserver address, like: wss://google.com:443, if no path then /ws will be used. Do not omit the port under any circumstances</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="quicserver">quicserver</h2>
|
||
<p>Run as brook quicserver, both TCP and UDP</p>
|
||
<ul>
|
||
<li><p><strong>--blockCIDR4List</strong>="": One CIDR per line, https://, http:// or local file absolute path, like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr4.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr4.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockCIDR6List</strong>="": One CIDR per line, https://, http:// or local file absolute path, like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr6.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr6.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockDomainList</strong>="": One domain per line, suffix match mode. https://, http:// or local file absolute path. Like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--blockGeoIP</strong>="": Block IP by Geo country code, such as US</p>
|
||
</li>
|
||
<li><p><strong>--cert</strong>="": The cert file absolute path for the domain, such as /path/to/cert.pem. If cert or certkey is empty, a certificate will be issued automatically</p>
|
||
</li>
|
||
<li><p><strong>--certkey</strong>="": The cert key file absolute path for the domain, such as /path/to/certkey.pem. If cert or certkey is empty, a certificate will be issued automatically</p>
|
||
</li>
|
||
<li><p><strong>--domainaddress</strong>="": Such as: domain.com:443. If you choose to automatically issue certificates, the domain must have been resolved to the server IP and 80 port also will be used</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Server password</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--updateListInterval</strong>="": Update list interval, second. default 0, only read one time on start (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--withoutBrookProtocol</strong>: The data will not be encrypted with brook protocol</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="quicclient">quicclient</h2>
|
||
<p>Run as brook quicclient, both TCP and UDP, to start a socks5 proxy, [src <-> socks5 <-> $ brook quicclient <-> $ brook quicserver <-> dst]. (Note that the global dial parameter is ignored now)</p>
|
||
<ul>
|
||
<li><p><strong>--address</strong>="": Specify address instead of resolving addresses from host, such as 1.2.3.4:443</p>
|
||
</li>
|
||
<li><p><strong>--ca</strong>="": Specify ca instead of insecure, such as /path/to/ca.pem</p>
|
||
</li>
|
||
<li><p><strong>--http</strong>="": Where to listen for HTTP proxy connections</p>
|
||
</li>
|
||
<li><p><strong>--insecure</strong>: Client do not verify the server's certificate chain and host name</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Brook quicserver password</p>
|
||
</li>
|
||
<li><p><strong>--quicserver, -s</strong>="": Brook quicserver address, like: quic://google.com:443. Do not omit the port under any circumstances</p>
|
||
</li>
|
||
<li><p><strong>--socks5</strong>="": Where to listen for SOCKS5 connections (default: 127.0.0.1:1080)</p>
|
||
</li>
|
||
<li><p><strong>--socks5ServerIP</strong>="": Only if your socks5 server IP is different from listen IP</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--withoutBrookProtocol</strong>: The data will not be encrypted with brook protocol</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="relayoverbrook">relayoverbrook</h2>
|
||
<p>Run as relay over brook, both TCP and UDP, this means access [from address] is equal to [to address], [src <-> from address <-> $ brook server/wsserver/wssserver/quicserver <-> to address]</p>
|
||
<ul>
|
||
<li><p><strong>--from, -f, -l</strong>="": Listen address: like ':9999'</p>
|
||
</li>
|
||
<li><p><strong>--link</strong>="": brook link, you can get it via $ brook link. The server and password parameters will be ignored</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Password</p>
|
||
</li>
|
||
<li><p><strong>--server, -s</strong>="": brook server or brook wsserver or brook wssserver or brook quicserver, like: 1.2.3.4:9999, ws://1.2.3.4:9999, wss://domain:443/ws, quic://domain.com:443</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--to, -t</strong>="": Address which relay to, like: 1.2.3.4:9999</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="dnsserveroverbrook">dnsserveroverbrook</h2>
|
||
<p>Run as dns server over brook, both TCP and UDP, [src <-> $ brook dnserversoverbrook <-> $ brook server/wsserver/wssserver/quicserver <-> dns] or [src <-> $ brook dnsserveroverbrook <-> dnsForBypass]</p>
|
||
<ul>
|
||
<li><p><strong>--blockDomainList</strong>="": One domain per line, suffix match mode. https://, http:// or local absolute file path. Like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--bypassDomainList</strong>="": One domain per line, suffix match mode. https://, http:// or local absolute file path. Like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--disableA</strong>: Disable A query</p>
|
||
</li>
|
||
<li><p><strong>--disableAAAA</strong>: Disable AAAA query</p>
|
||
</li>
|
||
<li><p><strong>--dns</strong>="": DNS server for resolving domains NOT in list (default: 8.8.8.8:53)</p>
|
||
</li>
|
||
<li><p><strong>--dnsForBypass</strong>="": DNS server for resolving domains in bypass list. Such as 223.5.5.5:53 or <a href="https://dns.alidns.com/dns-query?address=223.5.5.5:443">https://dns.alidns.com/dns-query?address=223.5.5.5:443</a>, the address is required (default: 223.5.5.5:53)</p>
|
||
</li>
|
||
<li><p><strong>--link</strong>="": brook link, you can get it via $ brook link. The server and password parameters will be ignored</p>
|
||
</li>
|
||
<li><p><strong>--listen, -l</strong>="": Listen address, like: 127.0.0.1:53</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Password</p>
|
||
</li>
|
||
<li><p><strong>--server, -s</strong>="": brook server or brook wsserver or brook wssserver or brook quicserver, like: 1.2.3.4:9999, ws://1.2.3.4:9999, wss://domain.com:443/ws, quic://domain.com:443</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="link">link</h2>
|
||
<p>Generate brook link</p>
|
||
<ul>
|
||
<li><p><strong>--address</strong>="": When server is brook wsserver or brook wssserver or brook quicserver, specify address instead of resolving addresses from host, such as 1.2.3.4:443</p>
|
||
</li>
|
||
<li><p><strong>--ca</strong>="": When server is brook wssserver or brook quicserver, specify ca for untrusted cert, such as /path/to/ca.pem</p>
|
||
</li>
|
||
<li><p><strong>--clientHKDFInfo</strong>="": client HKDF info, most time you don't need to change this, read brook protocol if you don't know what this is</p>
|
||
</li>
|
||
<li><p><strong>--fragment</strong>="": When server is brook wssserver, split the ClientHello into multiple fragments and then send them one by one with delays (millisecond). The format is min_length:max_length:min_delay:max_delay, cannot be zero, such as 50:100:10:50, Note that: This is an experimental feature, currently only supported by the brook CLI and tun2brook.</p>
|
||
</li>
|
||
<li><p><strong>--insecure</strong>: When server is brook wssserver or brook quicserver, client do not verify the server's certificate chain and host name</p>
|
||
</li>
|
||
<li><p><strong>--name</strong>="": Give this server a name</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Password</p>
|
||
</li>
|
||
<li><p><strong>--server, -s</strong>="": Support brook server, brook wsserver, brook wssserver, socks5 server, brook quicserver. Like: 1.2.3.4:9999, ws://1.2.3.4:9999, wss://google.com:443/ws, socks5://1.2.3.4:1080, quic://google.com:443</p>
|
||
</li>
|
||
<li><p><strong>--serverHKDFInfo</strong>="": server HKDF info, most time you don't need to change this, read brook protocol if you don't know what this is</p>
|
||
</li>
|
||
<li><p><strong>--tlsfingerprint</strong>="": When server is brook wssserver, select tls fingerprint, value can be: chrome</p>
|
||
</li>
|
||
<li><p><strong>--udpovertcp</strong>: When server is brook server, UDP over TCP</p>
|
||
</li>
|
||
<li><p><strong>--username, -u</strong>="": Username, when server is socks5 server</p>
|
||
</li>
|
||
<li><p><strong>--withoutBrookProtocol</strong>: When server is brook wsserver or brook wssserver or brook quicserver, the data will not be encrypted with brook protocol</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="connect">connect</h2>
|
||
<p>Run as client and connect to brook link, both TCP and UDP, to start a socks5 proxy, [src <-> socks5 <-> $ brook connect <-> $ brook server/wsserver/wssserver/quicserver <-> dst]</p>
|
||
<ul>
|
||
<li><p><strong>--http</strong>="": Where to listen for HTTP proxy connections</p>
|
||
</li>
|
||
<li><p><strong>--link, -l</strong>="": brook link, you can get it via $ brook link</p>
|
||
</li>
|
||
<li><p><strong>--socks5</strong>="": Where to listen for SOCKS5 connections (default: 127.0.0.1:1080)</p>
|
||
</li>
|
||
<li><p><strong>--socks5ServerIP</strong>="": Only if your socks5 server IP is different from listen IP</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="relay">relay</h2>
|
||
<p>Run as standalone relay, both TCP and UDP, this means access [from address] is equal to access [to address], [src <-> from address <-> to address]</p>
|
||
<ul>
|
||
<li><p><strong>--from, -f, -l</strong>="": Listen address: like ':9999'</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--to, -t</strong>="": Address which relay to, like: 1.2.3.4:9999</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="dnsserver">dnsserver</h2>
|
||
<p>Run as standalone dns server</p>
|
||
<ul>
|
||
<li><p><strong>--blockDomainList</strong>="": One domain per line, suffix match mode. https://, http:// or local absolute file path. Like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--disableA</strong>: Disable A query</p>
|
||
</li>
|
||
<li><p><strong>--disableAAAA</strong>: Disable AAAA query</p>
|
||
</li>
|
||
<li><p><strong>--dns</strong>="": DNS server which forward to. Such as 8.8.8.8:53 or <a href="https://dns.google/dns-query?address=8.8.8.8%3A443">https://dns.google/dns-query?address=8.8.8.8%3A443</a>, the address is required (default: 8.8.8.8:53)</p>
|
||
</li>
|
||
<li><p><strong>--listen, -l</strong>="": Listen address, like: 127.0.0.1:53</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="dnsclient">dnsclient</h2>
|
||
<p>Send a dns query</p>
|
||
<ul>
|
||
<li><p><strong>--dns, -s</strong>="": DNS server, such as 8.8.8.8:53 (default: 8.8.8.8:53)</p>
|
||
</li>
|
||
<li><p><strong>--domain, -d</strong>="": Domain</p>
|
||
</li>
|
||
<li><p><strong>--short</strong>: Short for A/AAAA</p>
|
||
</li>
|
||
<li><p><strong>--type, -t</strong>="": Type, such as A (default: A)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="dohserver">dohserver</h2>
|
||
<p>Run as standalone doh server</p>
|
||
<ul>
|
||
<li><p><strong>--blockDomainList</strong>="": One domain per line, suffix match mode. https://, http:// or local absolute file path. Like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--cert</strong>="": The cert file absolute path for the domain, such as /path/to/cert.pem. If cert or certkey is empty, a certificate will be issued automatically</p>
|
||
</li>
|
||
<li><p><strong>--certkey</strong>="": The cert key file absolute path for the domain, such as /path/to/certkey.pem. If cert or certkey is empty, a certificate will be issued automatically</p>
|
||
</li>
|
||
<li><p><strong>--disableA</strong>: Disable A query</p>
|
||
</li>
|
||
<li><p><strong>--disableAAAA</strong>: Disable AAAA query</p>
|
||
</li>
|
||
<li><p><strong>--dns</strong>="": DNS server which forward to. Such as 8.8.8.8:53 or <a href="https://dns.google/dns-query?address=8.8.8.8%3A443">https://dns.google/dns-query?address=8.8.8.8%3A443</a>, the address is required (default: 8.8.8.8:53)</p>
|
||
</li>
|
||
<li><p><strong>--domainaddress</strong>="": Such as: domain.com:443, if you want to create a https server. If you choose to automatically issue certificates, the domain must have been resolved to the server IP and 80 port also will be used</p>
|
||
</li>
|
||
<li><p><strong>--listen</strong>="": listen address, if you want to create a http server behind nico</p>
|
||
</li>
|
||
<li><p><strong>--path</strong>="": URL path (default: /dns-query)</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": time (s) (default: 0)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="dohclient">dohclient</h2>
|
||
<p>Send a dns query</p>
|
||
<ul>
|
||
<li><p><strong>--doh, -s</strong>="": DOH server, the address is required (default: <a href="https://dns.quad9.net/dns-query?address=9.9.9.9%3A443">https://dns.quad9.net/dns-query?address=9.9.9.9%3A443</a>)</p>
|
||
</li>
|
||
<li><p><strong>--domain, -d</strong>="": Domain</p>
|
||
</li>
|
||
<li><p><strong>--short</strong>: Short for A/AAAA</p>
|
||
</li>
|
||
<li><p><strong>--type, -t</strong>="": Type, such as A (default: A)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="dhcpserver">dhcpserver</h2>
|
||
<p>Run as standalone dhcp server. Note that you need to stop other dhcp servers, if there are.</p>
|
||
<ul>
|
||
<li><p><strong>--cache</strong>="": Cache file, local absolute file path, default is $HOME/.brook.dhcpserver</p>
|
||
</li>
|
||
<li><p><strong>--count</strong>="": IP range from the start, which you want to assign to clients (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--dnsserver</strong>="": The dns server which you want to assign to clients, such as: 192.168.1.1 or 8.8.8.8</p>
|
||
</li>
|
||
<li><p><strong>--gateway</strong>="": The router gateway which you want to assign to clients, such as: 192.168.1.1</p>
|
||
</li>
|
||
<li><p><strong>--interface</strong>="": Select interface on multi interface device. Linux only</p>
|
||
</li>
|
||
<li><p><strong>--netmask</strong>="": Subnet netmask which you want to assign to clients (default: 255.255.255.0)</p>
|
||
</li>
|
||
<li><p><strong>--serverip</strong>="": DHCP server IP, the IP of the this machine, you shoud set a static IP to this machine before doing this, such as: 192.168.1.10</p>
|
||
</li>
|
||
<li><p><strong>--start</strong>="": Start IP which you want to assign to clients, such as: 192.168.1.100</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="socks5">socks5</h2>
|
||
<p>Run as standalone standard socks5 server, both TCP and UDP</p>
|
||
<ul>
|
||
<li><p><strong>--limitUDP</strong>: The server MAY use this information to limit access to the UDP association. This usually causes connection failures in a NAT environment, where most clients are.</p>
|
||
</li>
|
||
<li><p><strong>--listen, -l</strong>="": Socks5 server listen address, like: :1080 or 1.2.3.4:1080</p>
|
||
</li>
|
||
<li><p><strong>--password</strong>="": Password, optional</p>
|
||
</li>
|
||
<li><p><strong>--socks5ServerIP</strong>="": Only if your socks5 server IP is different from listen IP</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": Connection deadline time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--udpTimeout</strong>="": Connection deadline time (s) (default: 0)</p>
|
||
</li>
|
||
<li><p><strong>--username</strong>="": User name, optional</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="socks5tohttp">socks5tohttp</h2>
|
||
<p>Convert socks5 to http proxy, [src <-> listen address(http proxy) <-> socks5 address <-> dst]</p>
|
||
<ul>
|
||
<li><p><strong>--listen, -l</strong>="": HTTP proxy which will be create: like: 127.0.0.1:8010</p>
|
||
</li>
|
||
<li><p><strong>--socks5, -s</strong>="": Socks5 server address, like: 127.0.0.1:1080</p>
|
||
</li>
|
||
<li><p><strong>--socks5password</strong>="": Socks5 password, optional</p>
|
||
</li>
|
||
<li><p><strong>--socks5username</strong>="": Socks5 username, optional</p>
|
||
</li>
|
||
<li><p><strong>--tcpTimeout</strong>="": Connection tcp timeout (s) (default: 0)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="pac">pac</h2>
|
||
<p>Run as PAC server or save PAC to file</p>
|
||
<ul>
|
||
<li><p><strong>--bypassDomainList, -b</strong>="": One domain per line, suffix match mode. http(s):// or local absolute file path. Like: <a href="https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt">https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt</a></p>
|
||
</li>
|
||
<li><p><strong>--file, -f</strong>="": Save PAC to file, this will ignore listen address</p>
|
||
</li>
|
||
<li><p><strong>--listen, -l</strong>="": Listen address, like: 127.0.0.1:1980</p>
|
||
</li>
|
||
<li><p><strong>--proxy, -p</strong>="": Proxy, like: 'SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT' (default: SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="testsocks5">testsocks5</h2>
|
||
<p>Test UDP and TCP of socks5 server</p>
|
||
<ul>
|
||
<li><p><strong>--dns</strong>="": DNS server for connecting (default: 8.8.8.8:53)</p>
|
||
</li>
|
||
<li><p><strong>--domain</strong>="": Domain for query (default: http3.ooo)</p>
|
||
</li>
|
||
<li><p><strong>--password, -p</strong>="": Socks5 password</p>
|
||
</li>
|
||
<li><p><strong>--socks5, -s</strong>="": Like: 127.0.0.1:1080</p>
|
||
</li>
|
||
<li><p><strong>--username, -u</strong>="": Socks5 username</p>
|
||
</li>
|
||
<li><p><strong>-a</strong>="": The A record of domain (default: 137.184.237.95)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="testbrook">testbrook</h2>
|
||
<p>Test UDP and TCP of brook server/wsserver/wssserver/quicserver. (Note that the global dial parameter is ignored now)</p>
|
||
<ul>
|
||
<li><p><strong>--dns</strong>="": DNS server for connecting (default: 8.8.8.8:53)</p>
|
||
</li>
|
||
<li><p><strong>--domain</strong>="": Domain for query (default: http3.ooo)</p>
|
||
</li>
|
||
<li><p><strong>--link, -l</strong>="": brook link. Get it via $ brook link</p>
|
||
</li>
|
||
<li><p><strong>--socks5</strong>="": Temporarily listening socks5 (default: 127.0.0.1:11080)</p>
|
||
</li>
|
||
<li><p><strong>-a</strong>="": The A record of domain (default: 137.184.237.95)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="echoserver">echoserver</h2>
|
||
<p>Echo server, echo UDP and TCP address of routes</p>
|
||
<ul>
|
||
<li><strong>--listen, -l</strong>="": Listen address, like: ':7777'</li>
|
||
</ul>
|
||
<h2 id="echoclient">echoclient</h2>
|
||
<p>Connect to echoserver, echo UDP and TCP address of routes</p>
|
||
<ul>
|
||
<li><p><strong>--server, -s</strong>="": Echo server address, such as 1.2.3.4:7777</p>
|
||
</li>
|
||
<li><p><strong>--times</strong>="": Times of interactions (default: 0)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="ipcountry">ipcountry</h2>
|
||
<p>Get country of IP</p>
|
||
<ul>
|
||
<li><strong>--ip</strong>="": 1.1.1.1</li>
|
||
</ul>
|
||
<h2 id="completion">completion</h2>
|
||
<p>Generate shell completions</p>
|
||
<ul>
|
||
<li><strong>--file, -f</strong>="": Write to file (default: brook_autocomplete)</li>
|
||
</ul>
|
||
<h2 id="mdpage">mdpage</h2>
|
||
<p>Generate markdown page</p>
|
||
<ul>
|
||
<li><p><strong>--file, -f</strong>="": Write to file, default print to stdout</p>
|
||
</li>
|
||
<li><p><strong>--help, -h</strong>: show help</p>
|
||
</li>
|
||
</ul>
|
||
<h3 id="help-h">help, h</h3>
|
||
<p>Shows a list of commands or help for one command</p>
|
||
<h2 id="manpage">manpage</h2>
|
||
<p>Generate man.1 page</p>
|
||
<ul>
|
||
<li><strong>--file, -f</strong>="": Write to file, default print to stdout. You should put to /path/to/man/man1/brook.1 on linux or /usr/local/share/man/man1/brook.1 on macos</li>
|
||
</ul>
|
||
<h2 id="help-h-1">help, h</h2>
|
||
<p>Shows a list of commands or help for one command</p>
|
||
<h1 id="examples">Examples</h1>
|
||
<p>List some examples of common scene commands, pay attention to replace the parameters such as IP, port, password, domain name, certificate path, etc. in the example by yourself</p>
|
||
<h2 id="run-brook-server">Run brook server</h2>
|
||
<pre><code>brook server --listen :9999 --password hello
|
||
</code></pre>
|
||
<p>then</p>
|
||
<ul>
|
||
<li>server: <code>1.2.3.4:9999</code></li>
|
||
<li>password: <code>hello</code></li>
|
||
</ul>
|
||
<p>or get brook link</p>
|
||
<pre><code>brook link --server 1.2.3.4:9999 --password hello --name 'my brook server'
|
||
</code></pre>
|
||
<p>or get brook link with <code>--udpovertcp</code></p>
|
||
<pre><code>brook link --server 1.2.3.4:9999 --password hello --udpovertcp --name 'my brook server'
|
||
</code></pre>
|
||
<h2 id="run-brook-wsserver">Run brook wsserver</h2>
|
||
<pre><code>brook wsserver --listen :9999 --password hello
|
||
</code></pre>
|
||
<p>then</p>
|
||
<ul>
|
||
<li>server: <code>ws://1.2.3.4:9999</code></li>
|
||
<li>password: <code>hello</code></li>
|
||
</ul>
|
||
<p>or get brook link</p>
|
||
<pre><code>brook link --server ws://1.2.3.4:9999 --password hello --name 'my brook wsserver'
|
||
</code></pre>
|
||
<p>or get brook link with domain, even if that's not your domain</p>
|
||
<pre><code>brook link --server ws://hello.com:9999 --password hello --address 1.2.3.4:9999 --name 'my brook wsserver'
|
||
</code></pre>
|
||
<h2 id="run-brook-wssserver-automatically-certificate">Run brook wssserver: automatically certificate</h2>
|
||
<blockquote>
|
||
<p>Make sure your domain has been resolved to your server IP successfully. Automatic certificate issuance requires the use of port 80</p>
|
||
</blockquote>
|
||
<pre><code>brook wssserver --domainaddress domain.com:443 --password hello
|
||
</code></pre>
|
||
<p>then</p>
|
||
<ul>
|
||
<li>server: <code>wss://domain.com:443</code></li>
|
||
<li>password: <code>hello</code></li>
|
||
</ul>
|
||
<p>or get brook link</p>
|
||
<pre><code>brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver'
|
||
</code></pre>
|
||
<h2 id="run-brook-wssserver-use-a-certificate-issued-by-an-existing-trust-authority">Run brook wssserver Use a certificate issued by an existing trust authority</h2>
|
||
<blockquote>
|
||
<p>Make sure your domain has been resolved to your server IP successfully</p>
|
||
</blockquote>
|
||
<pre><code>brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem
|
||
</code></pre>
|
||
<p>then</p>
|
||
<ul>
|
||
<li>server: <code>wss://domain.com:443</code></li>
|
||
<li>password: <code>hello</code></li>
|
||
</ul>
|
||
<p>or get brook link</p>
|
||
<pre><code>brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver'
|
||
</code></pre>
|
||
<h2 id="run-brook-wssserver-issue-untrusted-certificates-yourself-any-domain">Run brook wssserver issue untrusted certificates yourself, any domain</h2>
|
||
<p>Install <a href="https://github.com/txthinking/mad">mad</a></p>
|
||
<pre><code>nami install mad
|
||
</code></pre>
|
||
<p>Generate root ca</p>
|
||
<pre><code>mad ca --ca /root/ca.pem --key /root/cakey.pem
|
||
</code></pre>
|
||
<p>Generate domain cert by root ca</p>
|
||
<pre><code>mad cert --ca /root/ca.pem --ca_key /root/cakey.pem --cert /root/cert.pem --key /root/certkey.pem --domain domain.com
|
||
</code></pre>
|
||
<p>Run brook</p>
|
||
<pre><code>brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem
|
||
</code></pre>
|
||
<p>get brook link with <code>--insecure</code></p>
|
||
<pre><code>brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --address 1.2.3.4:443 --insecure
|
||
</code></pre>
|
||
<p>or get brook link with <code>--ca</code></p>
|
||
<pre><code>brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --address 1.2.3.4:443 --ca /root/ca.pem
|
||
</code></pre>
|
||
<h2 id="withoutbrookprotocol">withoutBrookProtocol</h2>
|
||
<p>Better performance, but data is not strongly encrypted using Brook protocol. So please use certificate encryption, and it is not recommended to use --withoutBrookProtocol and --insecure together</p>
|
||
<h2 id="withoutbrookprotocol-automatically-certificate">withoutBrookProtocol automatically certificate</h2>
|
||
<blockquote>
|
||
<p>Make sure your domain has been resolved to your server IP successfully. Automatic certificate issuance requires the use of port 80</p>
|
||
</blockquote>
|
||
<pre><code>brook wssserver --domainaddress domain.com:443 --password hello --withoutBrookProtocol
|
||
</code></pre>
|
||
<p>get brook link</p>
|
||
<pre><code>brook link --server wss://domain.com:443 --password hello --withoutBrookProtocol
|
||
</code></pre>
|
||
<h2 id="withoutbrookprotocol-use-a-certificate-issued-by-an-existing-trust-authority">withoutBrookProtocol Use a certificate issued by an existing trust authority</h2>
|
||
<blockquote>
|
||
<p>Make sure your domain has been resolved to your server IP successfully</p>
|
||
</blockquote>
|
||
<pre><code>brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem --withoutBrookProtocol
|
||
</code></pre>
|
||
<p>get brook link</p>
|
||
<pre><code>brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --withoutBrookProtocol
|
||
</code></pre>
|
||
<h2 id="withoutbrookprotocol-issue-untrusted-certificates-yourself-any-domain">withoutBrookProtocol issue untrusted certificates yourself, any domain</h2>
|
||
<p>Install <a href="https://github.com/txthinking/mad">mad</a></p>
|
||
<pre><code>nami install mad
|
||
</code></pre>
|
||
<p>Generate root ca</p>
|
||
<pre><code>mad ca --ca /root/ca.pem --key /root/cakey.pem
|
||
</code></pre>
|
||
<p>Generate domain cert by root ca</p>
|
||
<pre><code>mad cert --ca /root/ca.pem --ca_key /root/cakey.pem --cert /root/cert.pem --key /root/certkey.pem --domain domain.com
|
||
</code></pre>
|
||
<p>Run brook wssserver</p>
|
||
<pre><code>brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem --withoutBrookProtocol
|
||
</code></pre>
|
||
<p>Get brook link</p>
|
||
<pre><code>brook link --server wss://domain.com:443 --password hello --withoutBrookProtocol --address 1.2.3.4:443 --ca /root/ca.pem
|
||
</code></pre>
|
||
<h2 id="run-brook-socks5-a-stand-alone-standard-socks5-server">Run brook socks5, A stand-alone standard socks5 server</h2>
|
||
<pre><code>brook socks5 --listen :1080 --socks5ServerIP 1.2.3.4
|
||
</code></pre>
|
||
<p>then</p>
|
||
<ul>
|
||
<li>server: <code>1.2.3.4:1080</code></li>
|
||
</ul>
|
||
<p>or get brook link</p>
|
||
<pre><code>brook link --server socks5://1.2.3.4:1080
|
||
</code></pre>
|
||
<h2 id="run-brook-socks5-with-username-and-password-a-stand-alone-standard-socks5-server">Run brook socks5 with username and password. A stand-alone standard socks5 server</h2>
|
||
<pre><code>brook socks5 --listen :1080 --socks5ServerIP 1.2.3.4 --username hello --password world
|
||
</code></pre>
|
||
<p>then</p>
|
||
<ul>
|
||
<li>server: <code>1.2.3.4:1080</code></li>
|
||
<li>username: <code>hello</code></li>
|
||
<li>password: <code>world</code></li>
|
||
</ul>
|
||
<p>or get brook link</p>
|
||
<pre><code>brook link --server socks5://1.2.3.4:1080 --username hello --password world
|
||
</code></pre>
|
||
<h2 id="brook-relayoverbrook-can-relay-a-local-address-to-a-remote-address-over-brook-both-tcp-and-udp-it-works-with-brook-server-wsserver-wssserver">brook relayoverbrook can relay a local address to a remote address over brook, both TCP and UDP, it works with brook server wsserver wssserver.</h2>
|
||
<pre><code>brook relayoverbrook ... --from 127.0.0.1:5353 --to 8.8.8.8:53
|
||
</code></pre>
|
||
<h2 id="brook-dnsserveroverbrook-can-create-a-encrypted-dns-server-both-tcp-and-udp-it-works-with-brook-server-wsserver-wssserver">brook dnsserveroverbrook can create a encrypted DNS server, both TCP and UDP, it works with brook server wsserver wssserver.</h2>
|
||
<pre><code>brook dnsserveroverbrook ... --listen 127.0.0.1:53
|
||
</code></pre>
|
||
<h2 id="brook-openwrt-router-perfectly-supports-ipv4ipv6tcpudp-native-ipv6">Brook OpenWRT Router: Perfectly supports IPv4/IPv6/TCP/UDP. Native IPv6</h2>
|
||
<p><a href="https://www.txthinking.com/talks/articles/brook-openwrt-en.article">https://www.txthinking.com/talks/articles/brook-openwrt-en.article</a></p>
|
||
<h2 id="turn-macos-into-a-gateway-with-brook">Turn macOS into a Gateway with Brook</h2>
|
||
<p><a href="https://www.txthinking.com/talks/articles/brook-macos-gateway-en.article">https://www.txthinking.com/talks/articles/brook-macos-gateway-en.article</a></p>
|
||
<h2 id="turn-windows-into-a-gateway-with-brook">Turn Windows into a Gateway with Brook</h2>
|
||
<p><a href="https://www.txthinking.com/talks/articles/brook-windows-gateway-en.article">https://www.txthinking.com/talks/articles/brook-windows-gateway-en.article</a></p>
|
||
<h2 id="turn-linux-into-a-gateway-with-brook">Turn Linux into a Gateway with Brook</h2>
|
||
<p><a href="https://www.txthinking.com/talks/articles/brook-linux-gateway-en.article">https://www.txthinking.com/talks/articles/brook-linux-gateway-en.article</a></p>
|
||
<h2 id="brook-relay-can-relay-a-address-to-a-remote-address-it-can-relay-any-tcp-and-udp-server">brook relay can relay a address to a remote address. It can relay any tcp and udp server</h2>
|
||
<pre><code>brook relay --from :9999 --to 1.2.3.4:9999
|
||
</code></pre>
|
||
<h2 id="brook-socks5tohttp-can-convert-a-socks5-to-a-http-proxy">brook socks5tohttp can convert a socks5 to a http proxy</h2>
|
||
<pre><code>brook socks5tohttp --socks5 127.0.0.1:1080 --listen 127.0.0.1:8010
|
||
</code></pre>
|
||
<h2 id="brook-pac-creates-pac-server">brook pac creates pac server</h2>
|
||
<pre><code>brook pac --listen 127.0.0.1:8080 --proxy 'SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT' --bypassDomainList ...
|
||
</code></pre>
|
||
<h2 id="brook-pac-creates-pac-file">brook pac creates pac file</h2>
|
||
<pre><code>brook pac --file proxy.pac --proxy 'SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT' --bypassDomainList ...
|
||
</code></pre>
|
||
<h2 id="there-are-countless-examples-for-more-feature-suggestions-its-best-to-look-at-the-commands-and-parameters-in-the-cli-documentation-one-by-one-and-blog-youtube">There are countless examples; for more feature suggestions, it's best to look at the commands and parameters in the CLI documentation one by one, and blog, YouTube...</h2>
|
||
<h1 id="diagram">Diagram</h1>
|
||
<blockquote>
|
||
<p>Maybe outdated</p>
|
||
</blockquote>
|
||
<h2 id="overview">overview</h2>
|
||
<p><img src="https://txthinking.github.io/brook/svg/overview.svg" alt="overview"></p>
|
||
<h2 id="withoutbrookprotocol-1">withoutBrookProtocol</h2>
|
||
<p><img src="https://txthinking.github.io/brook/svg/wbp.svg" alt="wbp"></p>
|
||
<h2 id="relayoverbrook-1">relayoverbrook</h2>
|
||
<p><img src="https://txthinking.github.io/brook/svg/relayoverbrook.svg" alt="relayoverbrook"></p>
|
||
<h2 id="dnsserveroverbrook-1">dnsserveroverbrook</h2>
|
||
<p><img src="https://txthinking.github.io/brook/svg/dnsserveroverbrook.svg" alt="dnsserveroverbrook"></p>
|
||
<h2 id="relay-1">relay</h2>
|
||
<p><img src="https://txthinking.github.io/brook/svg/relay.svg" alt="relay"></p>
|
||
<h2 id="dnsserver-1">dnsserver</h2>
|
||
<p><img src="https://txthinking.github.io/brook/svg/dnsserver.svg" alt="dnsserver"></p>
|
||
<h2 id="tproxy">tproxy</h2>
|
||
<p><img src="https://txthinking.github.io/brook/svg/tproxy.svg" alt="tproxy"></p>
|
||
<h2 id="gui">gui</h2>
|
||
<p><img src="https://txthinking.github.io/brook/svg/gui.svg" alt="gui"></p>
|
||
<h2 id="script">script</h2>
|
||
<p><img src="https://txthinking.github.io/brook/svg/script.svg" alt="script"></p>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</body>
|
||
|
||
</html> |