-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathruleset.lua
140 lines (125 loc) · 5.2 KB
/
ruleset.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
-- [[ ruleset.lua: code with rule table example ]] --
_G.libruleset = require("libruleset")
_G.agent = require("agent")
agent.peername = "peer0"
agent.conns = {
-- "api.neosocksd.internal:80" should be available over { proxy1, proxy2, ... }
{ "socks4a://127.0.32.1:1080" },
{ "socks4a://127.0.32.1:1080", "socks4a://127.0.32.2:1080" },
{ "socks4a://127.0.33.1:1080" },
}
-- route "peer0.internal" to current peer
agent.hosts = { "peer0" }
-- [[ configurations ]] --
local ruleset = {}
ruleset.enable_until = nil
local function is_disabled()
local now = os.time()
if ruleset.enable_until and now < ruleset.enable_until then
return false
end
local date = os.date("*t", now)
if not (2 <= date.wday and date.wday <= 6) then
return true
end
return not (9 <= date.hour and date.hour < 18)
end
local API_ENDPOINT = "api.neosocksd.internal:80"
local INTERNAL_DOMAIN = ".internal"
-- 1. _G.redirect*: match the raw request "host:port"
-- in {matcher, action, optional log tag}
-- matching stops after a match is found
-- _G.redirect_name: for requests with name string
_G.redirect_name = {
-- rule.redirect(addr, proxy1, proxy2, ...)
{ match.exact("peer0.lan:22"), rule.redirect("host-gateway:22"), "ssh" },
{ match.exact("peer0.lan:80"), rule.redirect("nginx:80"), "web" },
{ match.exact("peer0.lan:443"), rule.redirect("nginx:443"), "web" },
-- access local sites directly
{ match.domain({ ".lan", ".local" }), rule.direct(), "lan" },
-- ".internal" assignment
{ match.exact(API_ENDPOINT), rule.redirect("127.0.1.1:9080") },
{ match.agent(), rule.agent() }, -- agent relay
{ match.exact("peer0.internal:22"), rule.redirect("host-gateway:22"), "ssh" },
{ match.domain(INTERNAL_DOMAIN), rule.reject(), "unknown" },
-- global condition
{ is_disabled, rule.reject(), "off" },
-- dynamically loaded big domains list, rule.proxy(proxy1, proxy2, ...)
{ composite.maybe(_G, "biglist"), rule.proxy("socks4a://proxy.lan:1080"), "biglist" },
-- if in _G.hosts, go to _G.route/_G.route6
-- otherwise, go to _G.route_default
}
-- _G.redirect: for requests with IPv4 address
_G.redirect = {
-- redirect TCP DNS to local cache
{ match.exact("1.1.1.1:53"), rule.redirect("127.0.0.53:53") },
{ match.exact("1.0.0.1:53"), rule.redirect("127.0.0.53:53") },
-- global condition
{ is_disabled, rule.reject(), "off" },
-- go to _G.route
}
-- _G.redirect6: for requests with IPv6 address
_G.redirect6 = {
-- global condition
{ is_disabled, rule.reject(), "off" },
-- go to _G.route6
}
-- 2. _G.hosts: map unmatched hosts
_G.hosts = {
["gateway.region1.lan"] = "192.168.32.1",
["host123.region1.lan"] = "192.168.32.123",
["gateway.region2.lan"] = "192.168.33.1",
["host123.region2.lan"] = "192.168.33.123"
}
-- 3. _G.route*: match the IP address
_G.route = {
-- reject loopback or link-local
{ inet.subnet("127.0.0.0/8"), rule.reject() },
{ inet.subnet("169.254.0.0/16"), rule.reject() },
-- region1 proxy
{ inet.subnet("192.168.32.0/24"), rule.proxy("socks4a://192.168.32.1:1080"), "region1" },
-- jump to region2 through region1 proxy (for a fancy demo)
{ inet.subnet("192.168.33.0/24"), rule.proxy("socks4a://192.168.32.1:1080", "socks4a://192.168.33.1:1080"), "region2" },
-- access other lan addresses directly
{ inet.subnet("192.168.0.0/16"), rule.direct(), "lan" },
-- dynamically loaded big IP ranges list
{ composite.maybe(_G, "biglist4"), rule.direct(), "biglist" },
-- go to _G.route_default
}
_G.route6 = {
-- reject loopback or link-local
{ inet6.subnet("::1/128"), rule.reject() },
{ inet6.subnet("fe80::/10"), rule.reject() },
{ inet6.subnet("::ffff:127.0.0.0/104"), rule.reject() },
{ inet6.subnet("::ffff:169.254.0.0/112"), rule.reject() },
-- dynamically loaded big IP ranges list
{ composite.maybe(_G, "biglist6"), rule.direct(), "biglist" },
-- go to _G.route_default
}
-- 4. the global default applies to any unmatched requests
-- in {action, optional log tag}
_G.route_default = { rule.proxy("socks5://user:[email protected]:1080"), "internet" }
function ruleset.stats(dt, q)
local w = list:new()
if is_disabled and is_disabled() then
w:insertf("%-20s: %s", "Status", "(service disabled)")
else
w:insertf("%-20s: %s", "Status", "running")
end
w:insert(libruleset.stats(dt))
w:insert(agent.stats(dt))
w:insert("")
return w:concat("\n")
end
local function main(...)
pcall(collectgarbage, "generational")
neosocksd.setinterval(60.0)
-- inherit undefined fields from libruleset
return setmetatable(ruleset, {
__index = function(_, k)
return _G.libruleset[k]
end
})
end
evlogf("ruleset loaded, interpreter: %s", _VERSION)
return main(...)