Compare commits

...

17 Commits

Author SHA1 Message Date
eum3l ba6e4f3a4c
Merge 40a1fb707d into 3ec5456e86 2024-05-08 16:35:09 +08:00
Toby 3ec5456e86
Merge pull request #135 from apernet/revert-pcap
Revert pcap
2024-05-07 23:46:46 -07:00
Toby b51ea5fa07 Revert "Merge pull request #134 from apernet/ci-cgo"
This reverts commit 5014523ae0, reversing
changes made to c453020349.
2024-05-07 23:44:00 -07:00
Toby 2ac8783eb6 Revert "Merge pull request #132 from eddc005/feat-pcap"
This reverts commit c453020349, reversing
changes made to 5723490a6c.
2024-05-07 23:43:54 -07:00
Toby 5014523ae0
Merge pull request #134 from apernet/ci-cgo
ci: enable cgo
2024-05-07 23:40:17 -07:00
Toby dabcc9566c ci: enable cgo 2024-05-07 23:38:28 -07:00
Toby c453020349
Merge pull request #132 from eddc005/feat-pcap
feat: add support for pcap replay
2024-05-07 23:18:03 -07:00
Toby 0daaa32fc6 ci: install pcap for build 2 2024-05-07 23:13:58 -07:00
Toby 5e15fd6dd9 ci: install pcap for build 2024-05-07 23:12:24 -07:00
Toby 76c0f47832 chore: do not default replay.realtime to true 2024-05-07 23:05:06 -07:00
Toby 70fee14103 chore: format 2024-05-07 22:50:58 -07:00
eddc005 abd7725fed close pcap properly and implement ProtectedDialContext 2024-05-07 21:50:06 +01:00
eddc005 f01b79e625 rebase and remove replayDelay 2024-05-06 23:04:54 +01:00
eddc005 94387450cf feat: add support for pcap replay 2024-05-06 22:53:11 +01:00
eum3l 40a1fb707d fix: allow unsupported systems; opengfw pname 2024-02-18 16:04:39 +01:00
eum3l 9edaba0f8f Provide for eachDefaultSystem (flake-utils); Add hydraJobs 2024-02-18 14:41:57 +01:00
eum3l aca830d189 feat: add Nix package and NixOS module 2024-02-17 20:34:01 +01:00
5 changed files with 475 additions and 0 deletions

130
flake.lock Normal file
View File

@ -0,0 +1,130 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1705309234,
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1705314449,
"narHash": "sha256-yfQQ67dLejP0FLK76LKHbkzcQqNIrux6MFe32MMFGNQ=",
"owner": "nix-community",
"repo": "gomod2nix",
"rev": "30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "gomod2nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1658285632,
"narHash": "sha256-zRS5S/hoeDGUbO+L95wXG9vJNwsSYcl93XiD0HQBXLk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5342fc6fb59d0595d26883c3cadff16ce58e44f3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1701282334,
"narHash": "sha256-MxCVrXY6v4QmfTwIysjjaX0XUhqBbxTWWB4HXtDYsdk=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "057f9aecfb71c4437d2b27d3323df7f93c010b7e",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "23.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"gomod2nix": "gomod2nix",
"nixpkgs": "nixpkgs_2"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

49
flake.nix Normal file
View File

@ -0,0 +1,49 @@
{
description = "OpenGFW is a flexible, easy-to-use, open source implementation of GFW on Linux.";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=23.11";
gomod2nix.url = "github:nix-community/gomod2nix";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = {
self,
nixpkgs,
gomod2nix,
flake-utils,
}:
flake-utils.lib.eachDefaultSystem (
system: let
pkgs = import nixpkgs {
inherit system;
config.allowUnsupportedSystem = true;
overlays = [
gomod2nix.overlays.default
];
};
in {
packages = rec {
opengfw = pkgs.callPackage ./nix/package.nix {};
default = opengfw;
};
devShells.default = pkgs.mkShell {
OPENGFW_LOG_LEVEL = "debug";
buildInputs = let
goEnv = pkgs.mkGoEnv {pwd = ./.;};
in [
goEnv
pkgs.gomod2nix
];
};
}
)
// {
nixosModules.opengfw = import ./nix/module.nix self.packages;
hydraJobs = {
inherit (self) packages;
};
};
}

117
gomod2nix.toml Normal file
View File

@ -0,0 +1,117 @@
schema = 3
[mod]
[mod."github.com/bwmarrin/snowflake"]
version = "v0.3.0"
hash = "sha256-mOU/CgyC9W8XwuinYTPOH69wJY/f+nFVZjZ8lAr9fGM="
[mod."github.com/coreos/go-iptables"]
version = "v0.7.0"
hash = "sha256-6zG74a2qK8NnmKGL3Cv1IGDP/MSY/PYZpEcJT8bl7JU="
[mod."github.com/davecgh/go-spew"]
version = "v1.1.2-0.20180830191138-d8f796af33cc"
hash = "sha256-fV9oI51xjHdOmEx6+dlq7Ku2Ag+m/bmbzPo6A4Y74qc="
[mod."github.com/expr-lang/expr"]
version = "v1.15.7"
hash = "sha256-mQ8LOe+9hu72XTlQdymBrUsMBA7JB7S1G7Nob9hZNfo="
[mod."github.com/florianl/go-nfqueue"]
version = "v1.3.2-0.20231218173729-f2bdeb033acf"
hash = "sha256-KErxiIfDWHXrvJp0yweQ59M6lwmsY2McyKFaNVD6ifg="
[mod."github.com/fsnotify/fsnotify"]
version = "v1.7.0"
hash = "sha256-MdT2rQyQHspPJcx6n9ozkLbsktIOJutOqDuKpNAtoZY="
[mod."github.com/google/go-cmp"]
version = "v0.5.9"
hash = "sha256-lQc4O00R3QSMGs9LP8Sy7A9kj0cqV5rrUdpnGeipIyg="
[mod."github.com/google/gopacket"]
version = "v1.1.19"
hash = "sha256-EueA6b+c7SWJjII3HiFnMMKj3mIbAdzboJo6HBZnkkc="
[mod."github.com/hashicorp/golang-lru/v2"]
version = "v2.0.7"
hash = "sha256-t1bcXLgrQNOYUVyYEZ0knxcXpsTk4IuJZDjKvyJX75g="
[mod."github.com/hashicorp/hcl"]
version = "v1.0.0"
hash = "sha256-xsRCmYyBfglMxeWUvTZqkaRLSW+V2FvNodEDjTGg1WA="
[mod."github.com/inconshreveable/mousetrap"]
version = "v1.1.0"
hash = "sha256-XWlYH0c8IcxAwQTnIi6WYqq44nOKUylSWxWO/vi+8pE="
[mod."github.com/josharian/native"]
version = "v1.0.0"
hash = "sha256-ub4WrKNlMAvgn+OPuJYeJJYLyjqeTGDHA97RTzUC6+Y="
[mod."github.com/magiconair/properties"]
version = "v1.8.7"
hash = "sha256-XQ2bnc2s7/IH3WxEO4GishZurMyKwEclZy1DXg+2xXc="
[mod."github.com/mdlayher/netlink"]
version = "v1.6.0"
hash = "sha256-hFm39JacQH6ed6l/Xn10eP8pFVO0BK8a9phdgtj89f8="
[mod."github.com/mdlayher/socket"]
version = "v0.1.1"
hash = "sha256-g3GB7weGxxw8eJmD6VDY6os+zRJEZrmOLVscHGbDVXs="
[mod."github.com/mitchellh/mapstructure"]
version = "v1.5.0"
hash = "sha256-ztVhGQXs67MF8UadVvG72G3ly0ypQW0IRDdOOkjYwoE="
[mod."github.com/pelletier/go-toml/v2"]
version = "v2.1.0"
hash = "sha256-0u6oV8YMM26y2bw1oe3gLmEJc/whpNaFtEe4yOkN24c="
[mod."github.com/pmezard/go-difflib"]
version = "v1.0.1-0.20181226105442-5d4384ee4fb2"
hash = "sha256-XA4Oj1gdmdV/F/+8kMI+DBxKPthZ768hbKsO3d9Gx90="
[mod."github.com/sagikazarmark/locafero"]
version = "v0.4.0"
hash = "sha256-7I1Oatc7GAaHgAqBFO6Tv4IbzFiYeU9bJAfJhXuWaXk="
[mod."github.com/sagikazarmark/slog-shim"]
version = "v0.1.0"
hash = "sha256-F92BQXXmn3mCwu3mBaGh+joTRItQDSDhsjU6SofkYdA="
[mod."github.com/sourcegraph/conc"]
version = "v0.3.0"
hash = "sha256-mIdMs9MLAOBKf3/0quf1iI3v8uNWydy7ae5MFa+F2Ko="
[mod."github.com/spf13/afero"]
version = "v1.11.0"
hash = "sha256-+rV3cDZr13N8E0rJ7iHmwsKYKH+EhV+IXBut+JbBiIE="
[mod."github.com/spf13/cast"]
version = "v1.6.0"
hash = "sha256-hxioqRZfXE0AE5099wmn3YG0AZF8Wda2EB4c7zHF6zI="
[mod."github.com/spf13/cobra"]
version = "v1.8.0"
hash = "sha256-oAE+fEaRfZPE541IPWE0GMeBBYgH2DMhtZNxzp7DFlY="
[mod."github.com/spf13/pflag"]
version = "v1.0.5"
hash = "sha256-w9LLYzxxP74WHT4ouBspH/iQZXjuAh2WQCHsuvyEjAw="
[mod."github.com/spf13/viper"]
version = "v1.18.2"
hash = "sha256-MXYbK6w1LEaoZ2/L/STF3WU1tbK+7NwGVxUCLKPkwks="
[mod."github.com/stretchr/testify"]
version = "v1.8.4"
hash = "sha256-MoOmRzbz9QgiJ+OOBo5h5/LbilhJfRUryvzHJmXAWjo="
[mod."github.com/subosito/gotenv"]
version = "v1.6.0"
hash = "sha256-LspbjTniiq2xAICSXmgqP7carwlNaLqnCTQfw2pa80A="
[mod."go.uber.org/multierr"]
version = "v1.11.0"
hash = "sha256-Lb6rHHfR62Ozg2j2JZy3MKOMKdsfzd1IYTR57r3Mhp0="
[mod."go.uber.org/zap"]
version = "v1.26.0"
hash = "sha256-EUQnALSDtoJryWp01K/PMbRUvQYG1uDbqGnlJ/7thE4="
[mod."golang.org/x/exp"]
version = "v0.0.0-20230905200255-921286631fa9"
hash = "sha256-CyeVwjp12Wqh4ptqfi3KHCWPzOFhE8fSrP3sMjMXvec="
[mod."golang.org/x/net"]
version = "v0.19.0"
hash = "sha256-3M5rKEvJx4cO/q+06cGjR5sxF5JpnUWY0+fQttrWdT4="
[mod."golang.org/x/sync"]
version = "v0.5.0"
hash = "sha256-EAKeODSsct5HhXPmpWJfulKSCkuUu6kkDttnjyZMNcI="
[mod."golang.org/x/sys"]
version = "v0.15.0"
hash = "sha256-n7TlABF6179RzGq3gctPDKDPRtDfnwPdjNCMm8ps2KY="
[mod."golang.org/x/text"]
version = "v0.14.0"
hash = "sha256-yh3B0tom1RfzQBf1RNmfdNWF1PtiqxV41jW1GVS6JAg="
[mod."google.golang.org/protobuf"]
version = "v1.31.0"
hash = "sha256-UdIk+xRaMfdhVICvKRk1THe3R1VU+lWD8hqoW/y8jT0="
[mod."gopkg.in/ini.v1"]
version = "v1.67.0"
hash = "sha256-V10ahGNGT+NLRdKUyRg1dos5RxLBXBk1xutcnquc/+4="
[mod."gopkg.in/yaml.v3"]
version = "v3.0.1"
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="

147
nix/module.nix Normal file
View File

@ -0,0 +1,147 @@
packages: {
lib,
pkgs,
config,
...
}: let
inherit (lib) mkOption types mkIf;
cfg = config.services.opengfw;
settings =
if cfg.settings != {}
then (pkgs.formats.yaml {}).generate "OpenGFW-Config.yaml" cfg.settings
else cfg.settingsFile;
rules =
if cfg.rules != []
then (pkgs.formats.yaml {}).generate "OpenGFW-Rules.yaml" cfg.rules
else cfg.rulesFile;
in {
options.services.opengfw = {
enable = lib.mkEnableOption (lib.mdDoc "A flexible, easy-to-use, open source implementation of GFW on Linux.");
package = lib.mkPackageOption packages.${pkgs.system} "opengfw" {
default = "opengfw";
};
user = mkOption {
default = "opengfw";
type = types.singleLineStr;
};
dir = mkOption {
default = "/var/lib/opengfw";
type = types.singleLineStr;
};
rulesFile = mkOption {
default = null;
type = types.nullOr types.path;
};
settingsFile = mkOption {
default = null;
type = types.nullOr types.path;
};
settings = mkOption {
default = {};
type = types.attrs;
example = {
io = {
queueSize = 1024;
local = true;
};
workers = {
count = 4;
queueSize = 16;
tcpMaxBufferedPagesTotal = 4096;
tcpMaxBufferedPagesPerConn = 64;
udpMaxStreams = 4096;
};
};
};
rules = mkOption {
default = [];
type = types.listOf types.attrs;
description = ''
OpenGFW supports the actions 'allow', 'block', 'drop' and 'modify'
as listed on https://github.com/apernet/OpenGFW?tab=readme-ov-file#supported-actions.
It uses Expr Language (https://expr-lang.org/docs/language-definition).
Properties of the analyzers are documented here: https://github.com/apernet/OpenGFW/blob/master/docs/Analyzers.md.
'';
example = [
{
name = "block v2ex http";
action = "block";
expr = ''string(http?.req?.headers?.host) endsWith "v2ex.com"'';
}
{
name = "block google socks";
action = "block";
expr = ''string(socks?.req?.addr) endsWith "google.com" && socks?.req?.port == 80'';
}
{
name = "v2ex dns poisoning";
action = "modify";
modifier = {
name = "dns";
args = {
a = "0.0.0.0";
aaaa = "::";
};
};
expr = ''dns != nil && dns.qr && any(dns.questions, {.name endsWith "v2ex.com"})'';
}
];
};
};
config = mkIf cfg.enable {
security.wrappers.OpenGFW = {
owner = cfg.user;
group = cfg.user;
capabilities = "cap_net_admin+ep";
source = "${cfg.package}/bin/OpenGFW";
};
systemd = {
services.opengfw = let
cu = "${pkgs.coreutils}/bin";
in {
description = "OpenGFW";
wantedBy = ["multi-user.target"];
after = ["network.target"];
environment.PATH = lib.mkForce "${cu}:${pkgs.iptables}/bin";
preStart = mkIf ((cfg.rules != [] && cfg.settings != {}) || (cfg.rulesFile != null && cfg.settingsFile != null)) ''
${cu}/ln -sf ${settings} config.yaml
${cu}/ln -sf ${rules} rules.yaml
'';
serviceConfig = {
WorkingDirectory = cfg.dir;
ExecStart = "${config.security.wrapperDir}/OpenGFW -c config.yaml rules.yaml";
ExecReload = "${cu}/kill -HUP $MAINPID";
Restart = "always";
User = cfg.user;
};
};
tmpfiles.rules = [
"d '${cfg.dir}' 0660 ${cfg.user} ${cfg.user} - -"
];
};
users = {
users.${cfg.user} = {
description = "opengfw user";
isNormalUser = true;
group = cfg.user;
home = cfg.dir;
};
groups.${cfg.user} = {};
};
};
}

32
nix/package.nix Normal file
View File

@ -0,0 +1,32 @@
{
lib,
pkgs,
}:
pkgs.buildGoApplication rec {
pname = "opengfw";
version = "0.1.1";
pwd = ../.;
src = ../.;
buildPhase = ''
go build
'';
installPhase = ''
mkdir -p $out/bin
cp OpenGFW $out/bin
'';
meta = with lib; {
description = "A flexible, easy-to-use, open source implementation of GFW on Linux.";
longDescription = ''
OpenGFW is a flexible, easy-to-use, open source implementation of GFW on Linux
that's in many ways more powerful than the real thing.
It's cyber sovereignty you can have on a home router.
'';
homepage = "https://github.com/apernet/OpenGFW";
license = licenses.mpl20;
mainProgram = "OpenGFW";
platforms = [ "x86_64-linux" "aarch64-linux" ];
};
}