Compare commits
8 Commits
f4bc441ca8
...
a6748f30d9
Author | SHA1 | Date | |
---|---|---|---|
a6748f30d9 | |||
902b2c0d55 | |||
fb7a7d9cae | |||
1c325f45b4 | |||
79c931fc38 | |||
915e39b684 | |||
0c5153bbd6 | |||
01784ee3fd |
3
.cargo/config.toml
Normal file
3
.cargo/config.toml
Normal file
@ -0,0 +1,3 @@
|
||||
[profile.release]
|
||||
lto = "thin"
|
||||
strip = true
|
92
.drone.jsonnet
Normal file
92
.drone.jsonnet
Normal file
@ -0,0 +1,92 @@
|
||||
local executableName = 'fourth';
|
||||
local build_image = 'img.kie.rs/jjkiers/rust-cross:rust1.70-zig';
|
||||
|
||||
local archs = [
|
||||
{ target: 'aarch64-unknown-linux-musl', short: 'arm64-musl' },
|
||||
{ target: 'x86_64-pc-windows-gnu', short: 'windows' },
|
||||
{ target: 'x86_64-unknown-linux-musl', short: 'amd64-musl' },
|
||||
];
|
||||
|
||||
local getStepName(arch) = 'Build for ' + arch.short;
|
||||
|
||||
local builtExecutableName(arch) = executableName + if std.length(std.findSubstr(arch.short, 'windows')) > 0 then '.exe' else '';
|
||||
local targetExecutableName(arch) = executableName + '-' + arch.target + if std.length(std.findSubstr(arch.short, 'windows')) > 0 then '.exe' else '';
|
||||
|
||||
local getVolumeName(arch) = 'target-' + arch.target;
|
||||
local getLocalVolumes(arch) = [
|
||||
{
|
||||
name: getVolumeName(arch),
|
||||
temp: {},
|
||||
}
|
||||
for arch in archs
|
||||
];
|
||||
|
||||
local add_build_steps() = [
|
||||
{
|
||||
name: getStepName(arch),
|
||||
image: build_image,
|
||||
commands: [
|
||||
'echo Hello World from Jsonnet on ' + arch.target + '!',
|
||||
'cargo zigbuild --release --target ' + arch.target,
|
||||
'cp target/' + arch.target + '/release/' + builtExecutableName(arch) + ' artifacts/' + targetExecutableName(arch),
|
||||
'rm -rf target/' + arch.target + '/release/*',
|
||||
],
|
||||
depends_on: ['Prepare'],
|
||||
volumes: [{
|
||||
name: getVolumeName(arch),
|
||||
path: '/drone/src/target',
|
||||
}],
|
||||
}
|
||||
for arch in archs
|
||||
];
|
||||
|
||||
{
|
||||
kind: 'pipeline',
|
||||
type: 'docker',
|
||||
name: 'default',
|
||||
platform: {
|
||||
arch: 'amd64',
|
||||
},
|
||||
steps:
|
||||
[{
|
||||
name: 'Prepare',
|
||||
image: build_image,
|
||||
commands: [
|
||||
'mkdir artifacts',
|
||||
'echo Using image: ' + build_image,
|
||||
'cargo --version',
|
||||
'rustc --version',
|
||||
],
|
||||
}] +
|
||||
add_build_steps() +
|
||||
[
|
||||
{
|
||||
name: 'Show built artifacts',
|
||||
image: build_image,
|
||||
commands: [
|
||||
'ls -lah artifacts',
|
||||
],
|
||||
depends_on: [getStepName(a) for a in archs],
|
||||
},
|
||||
{
|
||||
name: 'Create release on gitea',
|
||||
image: 'plugins/gitea-release',
|
||||
settings: {
|
||||
api_key: {
|
||||
from_secret: 'gitea_token',
|
||||
},
|
||||
base_url: 'https://code.kiers.eu',
|
||||
files: 'artifacts/*',
|
||||
checksum: 'sha256',
|
||||
},
|
||||
when: {
|
||||
event: ['tag', 'promote'],
|
||||
},
|
||||
depends_on: ['Show built artifacts'],
|
||||
},
|
||||
],
|
||||
|
||||
volumes: getLocalVolumes(archs),
|
||||
|
||||
image_pull_secrets: ['docker_private_repo'],
|
||||
}
|
39
.github/workflows/publish-binaries.yml
vendored
39
.github/workflows/publish-binaries.yml
vendored
@ -1,39 +0,0 @@
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
name: Publish binaries to release
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish for ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
artifact_name: fourth
|
||||
asset_name: fourth-linux-amd64
|
||||
- os: macos-latest
|
||||
artifact_name: fourth
|
||||
asset_name: fourth-macos-amd64
|
||||
- os: windows-latest
|
||||
artifact_name: fourth.exe
|
||||
asset_name: fourth-windows-amd64.exe
|
||||
|
||||
steps:
|
||||
- uses: hecrj/setup-rust-action@master
|
||||
with:
|
||||
rust-version: stable
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: cargo build --release --locked
|
||||
- name: Publish
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
with:
|
||||
repo_token: ${{ secrets.PUBLISH_TOKEN }}
|
||||
file: target/release/${{ matrix.artifact_name }}
|
||||
asset_name: ${{ matrix.asset_name }}
|
||||
tag: ${{ github.ref }}
|
24
.github/workflows/rust.yml
vendored
24
.github/workflows/rust.yml
vendored
@ -1,24 +0,0 @@
|
||||
name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Upgrade Rust
|
||||
run: rustup update
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
/target
|
||||
config.yaml
|
||||
|
383
Cargo.lock
generated
383
Cargo.lock
generated
@ -3,10 +3,25 @@
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.0.1"
|
||||
name = "addr2line"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
|
||||
checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@ -28,6 +43,21 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
@ -46,12 +76,27 @@ version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929"
|
||||
|
||||
[[package]]
|
||||
name = "enum_primitive"
|
||||
version = "0.1.1"
|
||||
@ -75,10 +120,16 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.1.0"
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
@ -156,7 +207,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -191,9 +242,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.9"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
||||
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@ -201,10 +252,16 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
name = "gimli"
|
||||
version = "0.27.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
@ -217,12 +274,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.6"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
@ -235,9 +289,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
|
||||
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
@ -245,31 +299,31 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.144"
|
||||
version = "0.2.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
@ -277,9 +331,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.18"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
@ -293,6 +347,15 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.8"
|
||||
@ -301,7 +364,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -342,25 +405,25 @@ version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||
dependencies = [
|
||||
"num-traits 0.2.15",
|
||||
"num-traits 0.2.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.15.0"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi 0.2.6",
|
||||
"hermit-abi 0.3.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -373,6 +436,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
@ -385,22 +457,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.7"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
|
||||
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys 0.45.0",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.2.0"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
@ -442,9 +514,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
@ -470,9 +542,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.59"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
|
||||
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -485,9 +557,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.28"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
|
||||
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -524,18 +596,30 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.8.3"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
|
||||
checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@ -544,9 +628,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.2"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
||||
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rusticata-macros"
|
||||
@ -559,47 +649,47 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.12"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.13"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.163"
|
||||
version = "1.0.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
|
||||
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.163"
|
||||
version = "1.0.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
|
||||
checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.21"
|
||||
version = "0.9.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c"
|
||||
checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
@ -634,18 +724,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.10.0"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.9"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
|
||||
checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -661,9 +751,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.18"
|
||||
version = "2.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
|
||||
checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -681,10 +771,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.21"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
|
||||
checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"libc",
|
||||
"num_threads",
|
||||
@ -701,9 +792,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.9"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
|
||||
checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
@ -739,11 +830,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.28.2"
|
||||
version = "1.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2"
|
||||
checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
@ -753,7 +844,7 @@ dependencies = [
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -764,7 +855,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -775,9 +866,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.9"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
@ -790,15 +881,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6"
|
||||
checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.3.1"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
|
||||
checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
@ -842,134 +933,68 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.0",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
checksum = "d1eeca1c172a285ee6c2c84c341ccea837e7c01b12fbb2d0fe3c9e550ce49ec8"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.0",
|
||||
"windows_aarch64_msvc 0.48.0",
|
||||
"windows_i686_gnu 0.48.0",
|
||||
"windows_i686_msvc 0.48.0",
|
||||
"windows_x86_64_gnu 0.48.0",
|
||||
"windows_x86_64_gnullvm 0.48.0",
|
||||
"windows_x86_64_msvc 0.48.0",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
checksum = "b10d0c968ba7f6166195e13d593af609ec2e3d24f916f081690695cf5eaffb2f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
checksum = "571d8d4e62f26d4932099a9efe89660e8bd5087775a2ab5cdd8b747b811f1058"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
checksum = "2229ad223e178db5fbbc8bd8d3835e51e566b8474bfca58d2e6150c48bb723cd"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
checksum = "600956e2d840c194eedfc5d18f8242bc2e17c7775b6684488af3a9fff6fe3287"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
checksum = "ea99ff3f8b49fb7a8e0d305e5aec485bd068c2ba691b6e277d29eaeac945868a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
checksum = "8f1a05a1ece9a7a0d5a7ccf30ba2c33e3a61a30e042ffd247567d1de1d94120d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
checksum = "d419259aba16b663966e29e6d7c6ecfa0bb8425818bb96f6f1f3c3eb71a6e7b9"
|
||||
|
@ -24,7 +24,6 @@ futures = "0.3"
|
||||
tls-parser = "0.11"
|
||||
url = "2.2.2"
|
||||
time = { version = "0.3.1", features = ["local-offset", "formatting"] }
|
||||
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
|
||||
bytes = "1.1"
|
||||
|
70
README-EN.md
70
README-EN.md
@ -1,70 +0,0 @@
|
||||
# Fourth
|
||||
|
||||
> Hey, now we are on level 4!
|
||||
|
||||
[![](https://img.shields.io/crates/v/fourth)](https://crates.io/crates/fourth) [![CI](https://img.shields.io/github/workflow/status/kernelerr/fourth/Rust)](https://github.com/KernelErr/fourth/actions/workflows/rust.yml)
|
||||
|
||||
**Under heavy development, version 0.1 may update frequently**
|
||||
|
||||
Fourth is a layer 4 proxy implemented by Rust to listen on specific ports and transfer TCP/KCP data to remote addresses(only TCP) according to configuration.
|
||||
|
||||
## Features
|
||||
|
||||
- Listen on specific port and proxy to local or remote port
|
||||
- SNI-based rule without terminating TLS connection
|
||||
- Allow KCP inbound(warning: untested)
|
||||
|
||||
## Installation
|
||||
|
||||
To gain best performance on your computer's architecture, please consider build the source code. First, you may need [Rust tool chain](https://rustup.rs/).
|
||||
|
||||
```bash
|
||||
$ cd fourth
|
||||
$ cargo build --release
|
||||
```
|
||||
|
||||
Binary file will be generated at `target/release/fourth`, or you can use `cargo install --path .` to install.
|
||||
|
||||
Or you can use Cargo to install Fourth:
|
||||
|
||||
```bash
|
||||
$ cargo install fourth
|
||||
```
|
||||
|
||||
Or you can download binary file form the Release page.
|
||||
|
||||
## Configuration
|
||||
|
||||
Fourth will read yaml format configuration file from `/etc/fourth/config.yaml`, and you can set custom path to environment variable `FOURTH_CONFIG`, here is an minimal viable example:
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
log: info
|
||||
|
||||
servers:
|
||||
proxy_server:
|
||||
listen:
|
||||
- "127.0.0.1:8081"
|
||||
default: remote
|
||||
|
||||
upstream:
|
||||
remote: "tcp://www.remote.example.com:8082" # proxy to remote address
|
||||
```
|
||||
|
||||
Built-in two upstreams: ban(terminate connection immediately), echo. For detailed configuration, check [this example](./example-config.yaml).
|
||||
|
||||
## Performance Benchmark
|
||||
|
||||
Tested on 4C2G server:
|
||||
|
||||
Use fourth to proxy to Nginx(QPS of direct connection: ~120000): ~70000 req/s (Command: `wrk -t200 -c1000 -d120s --latency http://proxy-server:8081`)
|
||||
|
||||
Use fourth to proxy to local iperf3: 8Gbps
|
||||
|
||||
## Thanks
|
||||
|
||||
- [tokio_kcp](https://github.com/Matrix-Zhang/tokio_kcp)
|
||||
|
||||
## License
|
||||
|
||||
Fourth is available under terms of Apache-2.0.
|
80
README-ZH.md
Normal file
80
README-ZH.md
Normal file
@ -0,0 +1,80 @@
|
||||
# Fourth
|
||||
|
||||
> 这一波在第四层。
|
||||
|
||||
[![](https://img.shields.io/crates/v/fourth)](https://crates.io/crates/fourth) [![CI](https://img.shields.io/github/workflow/status/kernelerr/fourth/Rust)](https://github.com/KernelErr/fourth/actions/workflows/rust.yml)
|
||||
|
||||
[English](/README-EN.md)
|
||||
|
||||
**积极开发中,0.1版本迭代可能较快**
|
||||
|
||||
Fourth是一个Rust实现的Layer 4代理,用于监听指定端口TCP/KCP流量,并根据规则转发到指定目标(目前只支持TCP)。
|
||||
|
||||
## 功能
|
||||
|
||||
- 监听指定端口代理到本地或远端指定端口
|
||||
- 监听指定端口,通过TLS ClientHello消息中的SNI进行分流
|
||||
- 支持KCP入站(警告:未测试)
|
||||
|
||||
## 安装方法
|
||||
|
||||
为了确保获得您架构下的最佳性能,请考虑自行编译,首选需要确保您拥有[Rust工具链](https://rustup.rs/)。
|
||||
|
||||
```bash
|
||||
$ cd fourth
|
||||
$ cargo build --release
|
||||
```
|
||||
|
||||
将在`target/release/fourth`生成二进制文件,您也可以使用`cargo install --path . `来安装二进制文件。
|
||||
|
||||
或者您也可以使用Cargo直接安装:
|
||||
|
||||
```bash
|
||||
$ cargo install fourth
|
||||
```
|
||||
|
||||
或者您也可以直接从Release中下载二进制文件。
|
||||
|
||||
## 配置
|
||||
|
||||
Fourth使用yaml格式的配置文件,默认情况下会读取`/etc/fourth/config.yaml`,您也可以设置自定义路径到环境变量`FOURTH_CONFIG`,如下是一个最小有效配置:
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
log: info
|
||||
|
||||
servers:
|
||||
proxy_server:
|
||||
listen:
|
||||
- "127.0.0.1:8081"
|
||||
default: remote
|
||||
|
||||
upstream:
|
||||
remote: "tcp://www.remote.example.com:8082" # proxy to remote address
|
||||
```
|
||||
|
||||
内置两个的upstream:ban(立即中断连接)、echo(返回读到的数据)。更详细的配置可以参考[示例配置](./example-config.yaml)。
|
||||
|
||||
注意:[::]会默认同时绑定IPv4和IPv6。
|
||||
|
||||
## 性能测试
|
||||
|
||||
在4C2G的服务器上测试:
|
||||
|
||||
使用Fourth代理到Nginx(直连QPS 120000): ~70000req/s (测试命令:`wrk -t200 -c1000 -d120s --latency http://proxy-server:8081 `)
|
||||
|
||||
使用Fourth代理到本地iperf3:8Gbps
|
||||
|
||||
## io_uring?
|
||||
|
||||
尽管经过了很多尝试,我们发现目前一些Rust下面的io_uring实现存在问题,我们使用的io_uring库实现尽管在吞吐量上可以做到单线程20Gbps(相比之下Tokio仅有8Gbps),但在QPS上存在性能损失较大的问题。因此在有成熟的io_uring实现之前,我们仍然选择epoll。之后我们会持续关注相关进展。
|
||||
|
||||
可能以后会为Linux高内核版本的用户提供可选的io_uring加速。
|
||||
|
||||
## 感谢
|
||||
|
||||
- [tokio_kcp](https://github.com/Matrix-Zhang/tokio_kcp)
|
||||
|
||||
## 协议
|
||||
|
||||
Fourth以Apache-2.0协议开源。
|
54
README.md
54
README.md
@ -1,43 +1,41 @@
|
||||
# Fourth
|
||||
|
||||
> 这一波在第四层。
|
||||
> Hey, now we are on level 4!
|
||||
|
||||
[![](https://img.shields.io/crates/v/fourth)](https://crates.io/crates/fourth) [![CI](https://img.shields.io/github/workflow/status/kernelerr/fourth/Rust)](https://github.com/KernelErr/fourth/actions/workflows/rust.yml)
|
||||
|
||||
[English](/README-EN.md)
|
||||
**Under heavy development, version 0.1 may update frequently**
|
||||
|
||||
**积极开发中,0.1版本迭代可能较快**
|
||||
Fourth is a layer 4 proxy implemented by Rust to listen on specific ports and transfer TCP/KCP data to remote addresses(only TCP) according to configuration.
|
||||
|
||||
Fourth是一个Rust实现的Layer 4代理,用于监听指定端口TCP/KCP流量,并根据规则转发到指定目标(目前只支持TCP)。
|
||||
## Features
|
||||
|
||||
## 功能
|
||||
- Listen on specific port and proxy to local or remote port
|
||||
- SNI-based rule without terminating TLS connection
|
||||
- Allow KCP inbound(warning: untested)
|
||||
|
||||
- 监听指定端口代理到本地或远端指定端口
|
||||
- 监听指定端口,通过TLS ClientHello消息中的SNI进行分流
|
||||
- 支持KCP入站(警告:未测试)
|
||||
## Installation
|
||||
|
||||
## 安装方法
|
||||
|
||||
为了确保获得您架构下的最佳性能,请考虑自行编译,首选需要确保您拥有[Rust工具链](https://rustup.rs/)。
|
||||
To gain best performance on your computer's architecture, please consider build the source code. First, you may need [Rust tool chain](https://rustup.rs/).
|
||||
|
||||
```bash
|
||||
$ cd fourth
|
||||
$ cargo build --release
|
||||
```
|
||||
|
||||
将在`target/release/fourth`生成二进制文件,您也可以使用`cargo install --path . `来安装二进制文件。
|
||||
Binary file will be generated at `target/release/fourth`, or you can use `cargo install --path .` to install.
|
||||
|
||||
或者您也可以使用Cargo直接安装:
|
||||
Or you can use Cargo to install Fourth:
|
||||
|
||||
```bash
|
||||
$ cargo install fourth
|
||||
```
|
||||
|
||||
或者您也可以直接从Release中下载二进制文件。
|
||||
Or you can download binary file form the Release page.
|
||||
|
||||
## 配置
|
||||
## Configuration
|
||||
|
||||
Fourth使用yaml格式的配置文件,默认情况下会读取`/etc/fourth/config.yaml`,您也可以设置自定义路径到环境变量`FOURTH_CONFIG`,如下是一个最小有效配置:
|
||||
Fourth will read yaml format configuration file from `/etc/fourth/config.yaml`, and you can set custom path to environment variable `FOURTH_CONFIG`, here is an minimal viable example:
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
@ -53,28 +51,20 @@ upstream:
|
||||
remote: "tcp://www.remote.example.com:8082" # proxy to remote address
|
||||
```
|
||||
|
||||
内置两个的upstream:ban(立即中断连接)、echo(返回读到的数据)。更详细的配置可以参考[示例配置](./example-config.yaml)。
|
||||
Built-in two upstreams: ban(terminate connection immediately), echo. For detailed configuration, check [this example](./example-config.yaml).
|
||||
|
||||
注意:[::]会默认同时绑定IPv4和IPv6。
|
||||
## Performance Benchmark
|
||||
|
||||
## 性能测试
|
||||
Tested on 4C2G server:
|
||||
|
||||
在4C2G的服务器上测试:
|
||||
Use fourth to proxy to Nginx(QPS of direct connection: ~120000): ~70000 req/s (Command: `wrk -t200 -c1000 -d120s --latency http://proxy-server:8081`)
|
||||
|
||||
使用Fourth代理到Nginx(直连QPS 120000): ~70000req/s (测试命令:`wrk -t200 -c1000 -d120s --latency http://proxy-server:8081 `)
|
||||
Use fourth to proxy to local iperf3: 8Gbps
|
||||
|
||||
使用Fourth代理到本地iperf3:8Gbps
|
||||
|
||||
## io_uring?
|
||||
|
||||
尽管经过了很多尝试,我们发现目前一些Rust下面的io_uring实现存在问题,我们使用的io_uring库实现尽管在吞吐量上可以做到单线程20Gbps(相比之下Tokio仅有8Gbps),但在QPS上存在性能损失较大的问题。因此在有成熟的io_uring实现之前,我们仍然选择epoll。之后我们会持续关注相关进展。
|
||||
|
||||
可能以后会为Linux高内核版本的用户提供可选的io_uring加速。
|
||||
|
||||
## 感谢
|
||||
## Thanks
|
||||
|
||||
- [tokio_kcp](https://github.com/Matrix-Zhang/tokio_kcp)
|
||||
|
||||
## 协议
|
||||
## License
|
||||
|
||||
Fourth以Apache-2.0协议开源。
|
||||
Fourth is available under terms of Apache-2.0.
|
16
config.yaml.example
Normal file
16
config.yaml.example
Normal file
@ -0,0 +1,16 @@
|
||||
version: 1
|
||||
log: debug
|
||||
|
||||
servers:
|
||||
example_server:
|
||||
listen:
|
||||
- "0.0.0.0:8443"
|
||||
tls: true # Enable TLS features like SNI filtering
|
||||
sni:
|
||||
api.example.org: example-api
|
||||
www.example.org: gh-proxy
|
||||
default: ban
|
||||
|
||||
upstream:
|
||||
proxy: "tcp://new-www.example.org:443" # Connect over IPv4 or IPv6 to new-www.example.org:443
|
||||
example-api: "tcp6://api-v1.example.com:443" # Connect over IPv6 to api-v1.example.com:443
|
@ -1,3 +1,4 @@
|
||||
use crate::servers::upstream_address::UpstreamAddress;
|
||||
use log::{debug, warn};
|
||||
use serde::Deserialize;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
@ -6,8 +7,6 @@ use std::io::{Error as IOError, Read};
|
||||
use std::net::SocketAddr;
|
||||
use tokio::sync::Mutex;
|
||||
use url::Url;
|
||||
use tokio::time::Instant;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
@ -47,7 +46,7 @@ pub enum Upstream {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Addr(Mutex<Vec<SocketAddr>>);
|
||||
struct Addr(Mutex<UpstreamAddress>);
|
||||
|
||||
impl Default for Addr {
|
||||
fn default() -> Self {
|
||||
@ -71,38 +70,9 @@ pub struct CustomUpstream {
|
||||
}
|
||||
|
||||
impl CustomUpstream {
|
||||
pub async fn resolve_addresses(&self) -> std::io::Result<()> {
|
||||
{
|
||||
let addr = self.addresses.0.lock().await;
|
||||
if addr.len() > 0 {
|
||||
debug!("Already have addresses: {:?}", &addr);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Resolving addresses for {}", &self.addr);
|
||||
let addresses = tokio::net::lookup_host(self.addr.clone()).await?;
|
||||
|
||||
let mut addr: Vec<SocketAddr> = match self.protocol.as_ref() {
|
||||
"tcp4" => addresses.into_iter().filter(|a| a.is_ipv4()).collect(),
|
||||
"tcp6" => addresses.into_iter().filter(|a| a.is_ipv6()).collect(),
|
||||
_ => addresses.collect(),
|
||||
};
|
||||
|
||||
debug!("Got addresses for {}: {:?}", &self.addr, &addr);
|
||||
debug!("Resolved at {}", OffsetDateTime::now_utc().format(&time::format_description::well_known::Rfc3339).expect("Format"));
|
||||
|
||||
{
|
||||
let mut self_addr = self.addresses.0.lock().await;
|
||||
self_addr.clear();
|
||||
self_addr.append(&mut addr);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_addresses(&self) -> Vec<SocketAddr> {
|
||||
let a = self.addresses.0.lock().await;
|
||||
a.clone()
|
||||
pub async fn resolve_addresses(&self) -> std::io::Result<Vec<SocketAddr>> {
|
||||
let mut addr = self.addresses.0.lock().await;
|
||||
addr.resolve((*self.protocol).into()).await
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,23 +5,25 @@ use std::sync::Arc;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
mod protocol;
|
||||
pub(crate) mod upstream_address;
|
||||
|
||||
use crate::config::{ParsedConfig, Upstream};
|
||||
use protocol::tcp;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Server {
|
||||
pub(crate) struct Server {
|
||||
pub proxies: Vec<Arc<Proxy>>,
|
||||
pub config: ParsedConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Proxy {
|
||||
pub(crate) struct Proxy {
|
||||
pub name: String,
|
||||
pub listen: SocketAddr,
|
||||
pub protocol: String,
|
||||
pub tls: bool,
|
||||
pub sni: Option<HashMap<String, String>>,
|
||||
pub default: String,
|
||||
pub default_action: String,
|
||||
pub upstream: HashMap<String, Upstream>,
|
||||
}
|
||||
|
||||
@ -60,7 +62,7 @@ impl Server {
|
||||
protocol: protocol.clone(),
|
||||
tls,
|
||||
sni: sni.clone(),
|
||||
default: default.clone(),
|
||||
default_action: default.clone(),
|
||||
upstream: upstream.clone(),
|
||||
};
|
||||
new_server.proxies.push(Arc::new(proxy));
|
||||
|
@ -8,7 +8,7 @@ use tokio::io;
|
||||
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
pub async fn proxy(config: Arc<Proxy>) -> Result<(), Box<dyn std::error::Error>> {
|
||||
pub(crate) async fn proxy(config: Arc<Proxy>) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let listener = TcpListener::bind(config.listen).await?;
|
||||
let config = config.clone();
|
||||
|
||||
@ -37,17 +37,17 @@ async fn accept(inbound: TcpStream, proxy: Arc<Proxy>) -> Result<(), Box<dyn std
|
||||
info!("New connection from {:?}", inbound.peer_addr()?);
|
||||
|
||||
let upstream_name = match proxy.tls {
|
||||
false => proxy.default.clone(),
|
||||
false => proxy.default_action.clone(),
|
||||
true => {
|
||||
let mut hello_buf = [0u8; 1024];
|
||||
inbound.peek(&mut hello_buf).await?;
|
||||
let snis = get_sni(&hello_buf);
|
||||
if snis.is_empty() {
|
||||
proxy.default.clone()
|
||||
proxy.default_action.clone()
|
||||
} else {
|
||||
match proxy.sni.clone() {
|
||||
Some(sni_map) => {
|
||||
let mut upstream = proxy.default.clone();
|
||||
let mut upstream = proxy.default_action.clone();
|
||||
for sni in snis {
|
||||
let m = sni_map.get(&sni);
|
||||
if m.is_some() {
|
||||
@ -57,7 +57,7 @@ async fn accept(inbound: TcpStream, proxy: Arc<Proxy>) -> Result<(), Box<dyn std
|
||||
}
|
||||
upstream
|
||||
}
|
||||
None => proxy.default.clone(),
|
||||
None => proxy.default_action.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,18 +70,17 @@ async fn accept(inbound: TcpStream, proxy: Arc<Proxy>) -> Result<(), Box<dyn std
|
||||
None => {
|
||||
warn!(
|
||||
"No upstream named {:?} on server {:?}",
|
||||
proxy.default, proxy.name
|
||||
proxy.default_action, proxy.name
|
||||
);
|
||||
return process(inbound, proxy.upstream.get(&proxy.default).unwrap().clone()).await;
|
||||
return process(
|
||||
inbound,
|
||||
proxy.upstream.get(&proxy.default_action).unwrap().clone(),
|
||||
)
|
||||
.await;
|
||||
// ToDo: Remove unwrap and check default option
|
||||
}
|
||||
};
|
||||
|
||||
match upstream {
|
||||
Upstream::Custom(u) => u.resolve_addresses().await?,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
return process(inbound, upstream.clone()).await;
|
||||
}
|
||||
|
||||
@ -100,10 +99,9 @@ async fn process(
|
||||
debug!("Bytes read: {:?}", bytes_tx);
|
||||
}
|
||||
Upstream::Custom(custom) => {
|
||||
custom.resolve_addresses().await?;
|
||||
let outbound = match custom.protocol.as_ref() {
|
||||
"tcp4" | "tcp6" | "tcp" => {
|
||||
TcpStream::connect(custom.get_addresses().await.as_slice()).await?
|
||||
TcpStream::connect(custom.resolve_addresses().await?.as_slice()).await?
|
||||
}
|
||||
_ => {
|
||||
error!("Reached unknown protocol: {:?}", custom.protocol);
|
||||
|
115
src/servers/upstream_address.rs
Normal file
115
src/servers/upstream_address.rs
Normal file
@ -0,0 +1,115 @@
|
||||
use log::debug;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::io::Result;
|
||||
use std::net::SocketAddr;
|
||||
use time::{Duration, Instant, OffsetDateTime};
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub(crate) struct UpstreamAddress {
|
||||
address: String,
|
||||
resolved_addresses: Vec<SocketAddr>,
|
||||
resolved_time: Option<Instant>,
|
||||
ttl: Option<Duration>,
|
||||
}
|
||||
|
||||
impl Display for UpstreamAddress {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
self.address.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl UpstreamAddress {
|
||||
pub fn is_valid(&self) -> bool {
|
||||
if let Some(resolved) = self.resolved_time {
|
||||
if let Some(ttl) = self.ttl {
|
||||
return resolved.elapsed() < ttl;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn is_resolved(&self) -> bool {
|
||||
self.resolved_addresses.len() > 0
|
||||
}
|
||||
|
||||
fn time_remaining(&self) -> Duration {
|
||||
if !self.is_valid() {
|
||||
return Duration::seconds(0);
|
||||
}
|
||||
|
||||
self.ttl.unwrap() - self.resolved_time.unwrap().elapsed()
|
||||
}
|
||||
|
||||
pub async fn resolve(&mut self, mode: ResolutionMode) -> Result<Vec<SocketAddr>> {
|
||||
if self.is_resolved() && self.is_valid() {
|
||||
debug!(
|
||||
"Already got address {:?}, still valid for {}",
|
||||
&self.resolved_addresses,
|
||||
self.time_remaining()
|
||||
);
|
||||
return Ok(self.resolved_addresses.clone());
|
||||
}
|
||||
|
||||
debug!("Resolving addresses for {}", &self.address);
|
||||
|
||||
let lookup_result = tokio::net::lookup_host(&self.address).await;
|
||||
|
||||
let resolved_addresses = match lookup_result {
|
||||
Ok(resolved_addresses) => resolved_addresses,
|
||||
Err(e) => {
|
||||
// Protect against DNS flooding. Cache the result for 1 second.
|
||||
self.resolved_time = Some(Instant::now());
|
||||
self.ttl = Some(Duration::seconds(3));
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
let addresses: Vec<SocketAddr> = match mode {
|
||||
ResolutionMode::Ipv4 => resolved_addresses
|
||||
.into_iter()
|
||||
.filter(|a| a.is_ipv4())
|
||||
.collect(),
|
||||
|
||||
ResolutionMode::Ipv6 => resolved_addresses
|
||||
.into_iter()
|
||||
.filter(|a| a.is_ipv6())
|
||||
.collect(),
|
||||
|
||||
_ => resolved_addresses.collect(),
|
||||
};
|
||||
|
||||
debug!("Got addresses for {}: {:?}", &self.address, &addresses);
|
||||
debug!(
|
||||
"Resolved at {}",
|
||||
OffsetDateTime::now_utc()
|
||||
.format(&time::format_description::well_known::Rfc3339)
|
||||
.expect("Format")
|
||||
);
|
||||
|
||||
self.resolved_addresses = addresses;
|
||||
self.resolved_time = Some(Instant::now());
|
||||
self.ttl = Some(Duration::minutes(1));
|
||||
|
||||
Ok(self.resolved_addresses.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub(crate) enum ResolutionMode {
|
||||
#[default]
|
||||
Ipv4AndIpv6,
|
||||
Ipv4,
|
||||
Ipv6,
|
||||
}
|
||||
|
||||
impl From<&str> for ResolutionMode {
|
||||
fn from(value: &str) -> Self {
|
||||
match value {
|
||||
"tcp4" => ResolutionMode::Ipv4,
|
||||
"tcp6" => ResolutionMode::Ipv6,
|
||||
"tcp" => ResolutionMode::Ipv4AndIpv6,
|
||||
_ => panic!("This should never happen. Please check configuration parser."),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user