diff --git a/.gitignore b/.gitignore index e629ffb..927f10c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /bin/ /build/ -**/.idea/ +/.idea/ /assets/*.txt +/to-json/target/ /cmake-build-debug/ /cmake-build-release/ diff --git a/Dockerfile b/Dockerfile index 304cbcd..fad9e21 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,12 @@ ARG ALPINE="alpine:3.16" +ARG RUST="rust:1.64-alpine3.16" ARG GOLANG="golang:1.18-alpine3.16" FROM ${ALPINE} AS upx -RUN apk add build-base cmake git -RUN git clone https://github.com/dnomd343/upx.git --depth=1 -WORKDIR ./upx/ -RUN git submodule update --init && rm -rf ./.git/ +RUN apk add build-base cmake +ENV UPX="4.0.0" +RUN wget https://github.com/upx/upx/releases/download/v${UPX}/upx-${UPX}-src.tar.xz && tar xf upx-${UPX}-src.tar.xz +WORKDIR ./upx-${UPX}-src/ RUN make UPX_CMAKE_CONFIG_FLAGS=-DCMAKE_EXE_LINKER_FLAGS=-static WORKDIR ./build/release/ RUN strip upx && mv upx /tmp/ @@ -37,10 +38,10 @@ RUN env CGO_ENABLED=0 go build -v -trimpath -ldflags "-X main.VersionString=${DN COPY --from=upx /tmp/upx /usr/bin/ RUN upx -9 /tmp/dnsproxy -FROM ${GOLANG} AS toJSON -COPY ./toJSON/ /toJSON/ -WORKDIR /toJSON/ -RUN env CGO_ENABLED=0 go build -v -trimpath -ldflags "-s -w" && mv toJSON /tmp/ +FROM ${RUST} AS to-json +COPY ./to-json/ /to-json/ +WORKDIR /to-json/ +RUN cargo build --release && mv ./target/release/to-json /tmp/toJSON COPY --from=upx /tmp/upx /usr/bin/ RUN upx -9 /tmp/toJSON @@ -62,7 +63,7 @@ COPY --from=adguard /tmp/AdGuardHome /release/usr/bin/ COPY --from=overture /tmp/overture /release/usr/bin/ COPY --from=dnsproxy /tmp/dnsproxy /release/usr/bin/ COPY --from=cleardns /tmp/cleardns /release/usr/bin/ -COPY --from=toJSON /tmp/toJSON /release/usr/bin/ +COPY --from=to-json /tmp/toJSON /release/usr/bin/ FROM ${ALPINE} COPY --from=build /release/ / diff --git a/README.md b/README.md index 8b78036..2265587 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ ClearDNS 支持多种 DNS 协议,首先是常规 DNS ,即基于 UDP 或 TCP 当分流器接到请求时,若在 `chinalist.txt` 中有所匹配,则只请求国内组,若在 `gfwlist.txt` 匹配,则仅请求国外组;两者均未未匹配的情况下,将同时请求国内组与国外组,若国内组返回结果在 `china-ip.txt` 中,则证明 DNS 未被污染,采纳国内组结果,若返回国外 IP 地址,则可能已经被污染,将选取国外组结果。 -由于以上资源数据一直在变动,ClearDNS 内置了更新功能,支持自动获取新的资源文件;数据从多个上游项目收集,每天进行一次合并整理,整合数据的源码可见[此处](./assets/),您可以自由配置更新服务器,或者禁用更新。 +由于以上资源数据一直在变动,ClearDNS 内置了更新功能,支持自动获取新的资源文件;数据从多个上游项目收集,每天进行一次合并整理,整合数据的源码可见[此处](./assets),您可以自由配置更新服务器,或者禁用更新。 ## 配置格式 @@ -287,17 +287,17 @@ assets: ClearDNS 基于 Docker 网络有以下三种部署模式: -| | Host 模式 | Bridge 模式 | Macvlan 模式 | -| :-: | :-: | :-: | :-: | -| 网络原理 | 宿主机网络 | 桥接网络 | 虚拟独立 mac 网卡 | -| 服务 IP | 宿主机 IP | 宿主机 IP | 容器独立 IP | -| 宿主机 IP | 静态 IP 地址 | 静态 IP 地址 | 静态/动态 IP 地址 | -| 宿主机网络 | 无需改动网络配置 | Docker 自动适配 | 手动修改底层网络配置 | -| 宿主机端口 | 占用宿主机 53, 80, 4053, 5353, 6053 端口 | 占用宿主机 53 与 80 端口 | 不占用端口 | -| 管理完整性 | 完全 | 无法区分客户端 | 完全 | -| 宿主机耦合 | 强耦合 | 一般耦合 | 链路层以上完全分离 | -| 网络性能 | 相对较高 | 相对较低 | 相对适中 | -| 部署难度 | 简单 | 简单 | 复杂 | +| | Host 模式 | Bridge 模式 | Macvlan 模式 | +|:----------:|:----------------------------------------:|:------------------------:|:--------------------:| +| 网络原理 | 宿主机网络 | 桥接网络 | 虚拟独立 mac 网卡 | +| 服务 IP | 宿主机 IP | 宿主机 IP | 容器独立 IP | +| 宿主机 IP | 静态 IP 地址 | 静态 IP 地址 | 静态/动态 IP 地址 | +| 宿主机网络 | 无需改动网络配置 | Docker 自动适配 | 手动修改底层网络配置 | +| 宿主机端口 | 占用宿主机 53, 80, 4053, 5353, 6053 端口 | 占用宿主机 53 与 80 端口 | 不占用端口 | +| 管理完整性 | 完全 | 无法区分客户端 | 完全 | +| 宿主机耦合 | 强耦合 | 一般耦合 | 链路层以上完全分离 | +| 网络性能 | 相对较高 | 相对较低 | 相对适中 | +| 部署难度 | 简单 | 简单 | 复杂 | > 不熟悉 Linux 网络配置请勿使用 Macvlan 模式,新手建议选择 Bridge 或 Host 模式。 @@ -465,7 +465,7 @@ ClearDNS 会将数据持久化存储,以在重启 Docker 或宿主机后保留 > 国外组服务器切勿使用常规 DNS 服务,例如 `8.8.8.8` ,由于请求信息为明文,GFW 会抢答回复数据,导致内容仍然受到污染。 -在 `cleardns.yml` 中指定上游 DNS 服务器,国内组可指定国内公共 DNS 服务,国外组需指定可用的加密 DNS 服务,具体说明参考[关于DNS上游](#关于-dns-上游)部分。 +在 `cleardns.yml` 中指定上游 DNS 服务器,国内组可指定国内公共 DNS 服务,国外组需指定可用的加密 DNS 服务,具体说明参考[关于DNS上游](#关于-DNS-上游)部分。 > DNSCrypt 使用 `DNS Stamp` 封装,可以在[这里](https://dnscrypt.info/stamps)在线解析或生成链接内容。 diff --git a/include/constant.h b/include/constant.h index bc22c13..2168ad4 100644 --- a/include/constant.h +++ b/include/constant.h @@ -20,24 +20,24 @@ #define OVERTURE_BIN "overture" #define ADGUARD_BIN "AdGuardHome" -#define UPDATE_CRON "0 4 * * *" -#define ASSETS_PKG "/assets.tar.xz" - -#define ADGUARD_USER "admin" -#define ADGUARD_PASSWD "cleardns" - #define EXPOSE_DIR "/cleardns/" #define WORK_DIR "/etc/cleardns/" #define ASSETS_DIR "/cleardns/assets/" #define ADGUARD_DIR "/cleardns/adguard/" +#define ADGUARD_USER "admin" +#define ADGUARD_PASSWD "cleardns" + +#define UPDATE_CRON "0 4 * * *" +#define ASSETS_PKG "/assets.tar.xz" + #define ASSET_TTL "ttl.txt" #define ASSET_HOSTS "hosts.txt" #define ASSET_GFW_LIST "gfwlist.txt" #define ASSET_CHINA_IP "china-ip.txt" #define ASSET_CHINA_LIST "chinalist.txt" -#define EXIT_NORMAL 0 +#define EXIT_NORMAL 0 #define EXIT_FORK_ERROR 1 #define EXIT_EXEC_ERROR 2 #define EXIT_WAIT_ERROR 3 diff --git a/to-json/Cargo.lock b/to-json/Cargo.lock new file mode 100644 index 0000000..71b6233 --- /dev/null +++ b/to-json/Cargo.lock @@ -0,0 +1,91 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "serde" +version = "1.0.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" + +[[package]] +name = "serde_json" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d232d893b10de3eb7258ff01974d6ee20663d8e833263c99409d4b13a0209da" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "to-json" +version = "0.1.0" +dependencies = [ + "serde_json", + "serde_yaml", + "toml", +] + +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + +[[package]] +name = "unsafe-libyaml" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e5fa573d8ac5f1a856f8d7be41d390ee973daf97c806b2c1a465e4e1406e68" diff --git a/to-json/Cargo.toml b/to-json/Cargo.toml new file mode 100644 index 0000000..2fddb92 --- /dev/null +++ b/to-json/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "to-json" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde_json = "1.0.86" +serde_yaml = "0.9.14" +toml = "0.5.9" diff --git a/to-json/src/main.rs b/to-json/src/main.rs new file mode 100644 index 0000000..07bbabf --- /dev/null +++ b/to-json/src/main.rs @@ -0,0 +1,57 @@ +use std::io::Read; +use serde_json as json; +use serde_yaml as yaml; + +const FILE_ERROR: i32 = 1; // file open error +const PARSE_ERROR: i32 = 2; // parser error + +enum Format { + JSON(json::Value), + YAML(yaml::Value), + TOML(toml::Value), +} + +fn parser(content: &str) -> Option { + if let Ok(data) = json::from_str::(content) { // try JSON format + return Some(Format::JSON(data)); + } + if let Ok(data) = toml::from_str::(content) { // try TOML format + return Some(Format::TOML(data)); + } + if let Ok(data) = yaml::from_str::(content) { // try YAML format + return Some(Format::YAML(data)); + } + return None; // parse failed +} + +fn to_json(content: &str) -> String { // convert to JSON format + match parser(content) { + Some(data) => match data { + Format::JSON(dat) => json::to_string(&dat).unwrap(), + Format::YAML(dat) => json::to_string(&dat).unwrap(), + Format::TOML(dat) => json::to_string(&dat).unwrap(), + }, + None => std::process::exit(PARSE_ERROR), // error exit + } +} + +fn read_file(path: &str) -> String { // read file content + match std::fs::File::open(path) { + Ok(mut file) => { // file open success + let mut content = String::new(); + file.read_to_string(&mut content).unwrap(); // get file content + content + }, + Err(_) => std::process::exit(FILE_ERROR), // read failed + } +} + +fn main() { + let args: Vec = std::env::args().collect(); // input arguments + if args.len() < 2 { // missing arguments + println!("usage: toJSON [file]"); + std::process::exit(0); + } + let content = read_file(&args[1].clone()[..]); // read file content + println!("{}", to_json(&content[..])); // convert to JSON format +} diff --git a/toJSON/go.mod b/toJSON/go.mod deleted file mode 100644 index 77fd623..0000000 --- a/toJSON/go.mod +++ /dev/null @@ -1,8 +0,0 @@ -module toJSON - -go 1.18 - -require ( - github.com/BurntSushi/toml v1.2.0 - gopkg.in/yaml.v3 v3.0.1 -) diff --git a/toJSON/go.sum b/toJSON/go.sum deleted file mode 100644 index 9eb3253..0000000 --- a/toJSON/go.sum +++ /dev/null @@ -1,6 +0,0 @@ -github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= -github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/toJSON/main.go b/toJSON/main.go deleted file mode 100644 index cb3d6ff..0000000 --- a/toJSON/main.go +++ /dev/null @@ -1,40 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "github.com/BurntSushi/toml" - "gopkg.in/yaml.v3" - "os" -) - -func parser(raw []byte) (interface{}, interface{}) { - var object interface{} - if err := json.Unmarshal(raw, &object); err == nil { // try json - return object, nil // json format - } - if err := toml.Unmarshal(raw, &object); err == nil { // try toml - return object, nil // toml format - } - if err := yaml.Unmarshal(raw, &object); err == nil { // try yaml - return object, nil // yaml format - } - return nil, nil // parser error -} - -func main() { - if len(os.Args) < 2 { // without argument - fmt.Printf("usage: toJSON [file]\n") - os.Exit(0) - } - raw, err := os.ReadFile(os.Args[1]) - if err != nil { - os.Exit(2) // file open failed - } - if object, err := parser(raw); err == nil { - ret, _ := json.Marshal(object) - fmt.Println(string(ret)) - os.Exit(0) - } - os.Exit(1) // unmarshal failed -}