block supports now CIDR and wildcard
Massimo Melina committed
Apr 19, 2022 at 17:18 UTC
3332e72fe8268b29af6760ddd80c2846db3b93b9
7 files changed
+254
-21
README.md
+2
-1
@@ -239,11 +239,12 @@ Supported entries are:
239
- `cert` use this file for https certificate. Minimum to start https is to give a cert and a private_key. Default is none.
240
- `private_key` use this file for https private key. Default is none.
241
- `allowed_referer` you can decide what domains can link to your files. Wildcards supported. Default is any.
242
-- `block` a list of rules that will block connections. At the moment only `ip` rules are supported. E.g.:
242
+- `block` a list of rules that will block connections. E.g.:
243
```
244
block:
245
- ip: 192.168.0.90
246
```
247
+ Syntax supports, other than simple address, `*` as wildcard and CIDR format.
248
- `plugins_config` this is a generic place where you can find/put configuration for each plugin, at least those that need configuration.
249
- `custom_header` provide HTML code to be put at the top of your Frontend. Default is none.
250
- `localhost_admin` should Admin be accessed without credentials when on localhost. Default is true.
admin/src/ConfigPage.ts
+1
-1
@@ -109,7 +109,7 @@ export default function ConfigPage() {
109
keyLabel: "Files", keyWidth: 7,
110
valueLabel: "Mime type", valueWidth: 4
111
},
112
- { k: 'block', label: "Blocked IPs", multiline: true, minRows:3, helperText: "Enter an IP address for each line",
112
+ { k: 'block', label: "Blocked IPs", multiline: true, minRows:3, helperText: "Enter an IP address for each line. CIDR and * are supported.",
113
fromField: (all:string) => all.split('\n').map(s => s.trim()).filter(Boolean).map(ip => ({ ip })),
114
toField: (all: any) => !Array.isArray(all) ? '' : all.map(x => x?.ip).filter(Boolean).join('\n')
115
},
package-lock.json
+212
-4
@@ -6136,6 +6136,34 @@
6136
"dev": true,
6137
"license": "MIT"
6138
},
6139
+ "node_modules/cidr-regex": {
6140
+ "version": "3.1.1",
6141
+ "resolved": "https://registry.npmjs.org/cidr-regex/-/cidr-regex-3.1.1.tgz",
6142
+ "integrity": "sha512-RBqYd32aDwbCMFJRL6wHOlDNYJsPNTt8vC82ErHF5vKt8QQzxm1FrkW8s/R5pVrXMf17sba09Uoy91PKiddAsw==",
6143
+ "dependencies": {
6144
+ "ip-regex": "^4.1.0"
6145
+ },
6146
+ "engines": {
6147
+ "node": ">=10"
6148
+ }
6149
+ },
6150
+ "node_modules/cidr-tools": {
6151
+ "version": "4.3.0",
6152
+ "resolved": "https://registry.npmjs.org/cidr-tools/-/cidr-tools-4.3.0.tgz",
6153
+ "integrity": "sha512-Conidfn8svry8txRhW63SkaRMYJWJSvCT5kRCovIzlD0A3wzaV3gVFNxmAFJo5rxx3KHeYnJxCe7bUKFr1wxHA==",
6154
+ "dependencies": {
6155
+ "ip-address": "^8.1.0",
6156
+ "ip-cidr": "^3.0.4",
6157
+ "ipv6-normalize": "^1.0.1",
6158
+ "is-cidr": "^4.0.2",
6159
+ "is-ip": "^3.1.0",
6160
+ "jsbn": "^1.1.0",
6161
+ "string-natural-compare": "^3.0.1"
6162
+ },
6163
+ "engines": {
6164
+ "node": ">=10"
6165
+ }
6166
+ },
6167
"node_modules/cjs-module-lexer": {
6168
"version": "1.2.2",
6169
"dev": true,
@@ -9834,6 +9862,60 @@
9862
"dev": true,
9863
"license": "MIT"
9864
},
9865
+ "node_modules/ip-address": {
9866
+ "version": "8.1.0",
9867
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-8.1.0.tgz",
9868
+ "integrity": "sha512-Wz91gZKpNKoXtqvY8ScarKYwhXoK4r/b5QuT+uywe/azv0/nUCo7Bh0IRRI7F9DHR06kJNWtzMGLIbXavngbKA==",
9869
+ "dependencies": {
9870
+ "jsbn": "1.1.0",
9871
+ "sprintf-js": "1.1.2"
9872
+ },
9873
+ "engines": {
9874
+ "node": ">= 12"
9875
+ }
9876
+ },
9877
+ "node_modules/ip-address/node_modules/sprintf-js": {
9878
+ "version": "1.1.2",
9879
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
9880
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
9881
+ },
9882
+ "node_modules/ip-cidr": {
9883
+ "version": "3.0.7",
9884
+ "resolved": "https://registry.npmjs.org/ip-cidr/-/ip-cidr-3.0.7.tgz",
9885
+ "integrity": "sha512-0cBBICDnmmpAdULMbMVdi4f0mSG+VWY/QBPL/OIIjuom14x7Y63VhpS/uSAOycasXOeGXah5y0eu//PDU51aNw==",
9886
+ "dependencies": {
9887
+ "ip-address": "^7.1.0",
9888
+ "jsbn": "^1.1.0"
9889
+ },
9890
+ "engines": {
9891
+ "node": ">=10.0.0"
9892
+ }
9893
+ },
9894
+ "node_modules/ip-cidr/node_modules/ip-address": {
9895
+ "version": "7.1.0",
9896
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-7.1.0.tgz",
9897
+ "integrity": "sha512-V9pWC/VJf2lsXqP7IWJ+pe3P1/HCYGBMZrrnT62niLGjAfCbeiwXMUxaeHvnVlz19O27pvXP4azs+Pj/A0x+SQ==",
9898
+ "dependencies": {
9899
+ "jsbn": "1.1.0",
9900
+ "sprintf-js": "1.1.2"
9901
+ },
9902
+ "engines": {
9903
+ "node": ">= 10"
9904
+ }
9905
+ },
9906
+ "node_modules/ip-cidr/node_modules/sprintf-js": {
9907
+ "version": "1.1.2",
9908
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
9909
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
9910
+ },
9911
+ "node_modules/ip-regex": {
9912
+ "version": "4.3.0",
9913
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz",
9914
+ "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==",
9915
+ "engines": {
9916
+ "node": ">=8"
9917
+ }
9918
+ },
9919
"node_modules/ipaddr.js": {
9920
"version": "2.0.1",
9921
"dev": true,
@@ -9842,6 +9924,11 @@
9924
"node": ">= 10"
9925
}
9926
},
9927
+ "node_modules/ipv6-normalize": {
9928
+ "version": "1.0.1",
9929
+ "resolved": "https://registry.npmjs.org/ipv6-normalize/-/ipv6-normalize-1.0.1.tgz",
9930
+ "integrity": "sha1-GzJYKQ02X6gyOeiZB93kWS52IKg="
9931
+ },
9932
"node_modules/is-arrayish": {
9933
"version": "0.2.1",
9934
"license": "MIT"
@@ -9905,6 +9992,17 @@
9992
"is-ci": "bin.js"
9993
}
9994
},
9995
+ "node_modules/is-cidr": {
9996
+ "version": "4.0.2",
9997
+ "resolved": "https://registry.npmjs.org/is-cidr/-/is-cidr-4.0.2.tgz",
9998
+ "integrity": "sha512-z4a1ENUajDbEl/Q6/pVBpTR1nBjjEE1X7qb7bmWYanNnPoKAvUCPFKeXV6Fe4mgTkWKBqiHIcwsI3SndiO5FeA==",
9999
+ "dependencies": {
10000
+ "cidr-regex": "^3.1.1"
10001
+ },
10002
+ "engines": {
10003
+ "node": ">=10"
10004
+ }
10005
+ },
10006
"node_modules/is-class-hotfix": {
10007
"version": "0.0.6",
10008
"license": "MIT"
@@ -10011,6 +10109,17 @@
10109
"url": "https://github.com/sponsors/sindresorhus"
10110
}
10111
},
10112
+ "node_modules/is-ip": {
10113
+ "version": "3.1.0",
10114
+ "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz",
10115
+ "integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==",
10116
+ "dependencies": {
10117
+ "ip-regex": "^4.0.0"
10118
+ },
10119
+ "engines": {
10120
+ "node": ">=8"
10121
+ }
10122
+ },
10123
"node_modules/is-module": {
10124
"version": "1.0.0",
10125
"dev": true,
@@ -11829,6 +11938,11 @@
11938
"js-yaml": "bin/js-yaml.js"
11939
}
11940
},
11941
+ "node_modules/jsbn": {
11942
+ "version": "1.1.0",
11943
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
11944
+ "integrity": "sha1-sBMHyym2GKHtJux56RH4A8TaAEA="
11945
+ },
11946
"node_modules/jsdom": {
11947
"version": "16.7.0",
11948
"dev": true,
@@ -16446,8 +16560,7 @@
16560
"node_modules/string-natural-compare": {
16561
"version": "3.0.1",
16562
"resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz",
16449
- "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==",
16450
- "dev": true
16563
+ "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw=="
16564
},
16565
"node_modules/string-width": {
16566
"version": "4.2.3",
@@ -18662,6 +18775,7 @@
18775
"@koa/router": "^10.1.1",
18776
"@node-rs/crc32": "^1.3.1",
18777
"buffer-crc32": "https://github.com/rejetto/buffer-crc32.git",
18778
+ "cidr-tools": "^4.3.0",
18779
"fast-glob": "^3.2.7",
18780
"find-process": "^1.4.7",
18781
"koa": "^2.13.4",
@@ -20160,6 +20274,7 @@
20274
"@types/node": "^16.11.12",
20275
"axios": "^0.24.0",
20276
"buffer-crc32": "https://github.com/rejetto/buffer-crc32.git",
20277
+ "cidr-tools": "^4.3.0",
20278
"fast-glob": "^3.2.7",
20279
"find-process": "^1.4.7",
20280
"koa": "^2.13.4",
@@ -22655,6 +22770,28 @@
22770
"version": "2.0.0",
22771
"dev": true
22772
},
22773
+ "cidr-regex": {
22774
+ "version": "3.1.1",
22775
+ "resolved": "https://registry.npmjs.org/cidr-regex/-/cidr-regex-3.1.1.tgz",
22776
+ "integrity": "sha512-RBqYd32aDwbCMFJRL6wHOlDNYJsPNTt8vC82ErHF5vKt8QQzxm1FrkW8s/R5pVrXMf17sba09Uoy91PKiddAsw==",
22777
+ "requires": {
22778
+ "ip-regex": "^4.1.0"
22779
+ }
22780
+ },
22781
+ "cidr-tools": {
22782
+ "version": "4.3.0",
22783
+ "resolved": "https://registry.npmjs.org/cidr-tools/-/cidr-tools-4.3.0.tgz",
22784
+ "integrity": "sha512-Conidfn8svry8txRhW63SkaRMYJWJSvCT5kRCovIzlD0A3wzaV3gVFNxmAFJo5rxx3KHeYnJxCe7bUKFr1wxHA==",
22785
+ "requires": {
22786
+ "ip-address": "^8.1.0",
22787
+ "ip-cidr": "^3.0.4",
22788
+ "ipv6-normalize": "^1.0.1",
22789
+ "is-cidr": "^4.0.2",
22790
+ "is-ip": "^3.1.0",
22791
+ "jsbn": "^1.1.0",
22792
+ "string-natural-compare": "^3.0.1"
22793
+ }
22794
+ },
22795
"cjs-module-lexer": {
22796
"version": "1.2.2",
22797
"dev": true
@@ -25070,10 +25207,61 @@
25207
"version": "1.1.5",
25208
"dev": true
25209
},
25210
+ "ip-address": {
25211
+ "version": "8.1.0",
25212
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-8.1.0.tgz",
25213
+ "integrity": "sha512-Wz91gZKpNKoXtqvY8ScarKYwhXoK4r/b5QuT+uywe/azv0/nUCo7Bh0IRRI7F9DHR06kJNWtzMGLIbXavngbKA==",
25214
+ "requires": {
25215
+ "jsbn": "1.1.0",
25216
+ "sprintf-js": "1.1.2"
25217
+ },
25218
+ "dependencies": {
25219
+ "sprintf-js": {
25220
+ "version": "1.1.2",
25221
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
25222
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
25223
+ }
25224
+ }
25225
+ },
25226
+ "ip-cidr": {
25227
+ "version": "3.0.7",
25228
+ "resolved": "https://registry.npmjs.org/ip-cidr/-/ip-cidr-3.0.7.tgz",
25229
+ "integrity": "sha512-0cBBICDnmmpAdULMbMVdi4f0mSG+VWY/QBPL/OIIjuom14x7Y63VhpS/uSAOycasXOeGXah5y0eu//PDU51aNw==",
25230
+ "requires": {
25231
+ "ip-address": "^7.1.0",
25232
+ "jsbn": "^1.1.0"
25233
+ },
25234
+ "dependencies": {
25235
+ "ip-address": {
25236
+ "version": "7.1.0",
25237
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-7.1.0.tgz",
25238
+ "integrity": "sha512-V9pWC/VJf2lsXqP7IWJ+pe3P1/HCYGBMZrrnT62niLGjAfCbeiwXMUxaeHvnVlz19O27pvXP4azs+Pj/A0x+SQ==",
25239
+ "requires": {
25240
+ "jsbn": "1.1.0",
25241
+ "sprintf-js": "1.1.2"
25242
+ }
25243
+ },
25244
+ "sprintf-js": {
25245
+ "version": "1.1.2",
25246
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
25247
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
25248
+ }
25249
+ }
25250
+ },
25251
+ "ip-regex": {
25252
+ "version": "4.3.0",
25253
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz",
25254
+ "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q=="
25255
+ },
25256
"ipaddr.js": {
25257
"version": "2.0.1",
25258
"dev": true
25259
},
25260
+ "ipv6-normalize": {
25261
+ "version": "1.0.1",
25262
+ "resolved": "https://registry.npmjs.org/ipv6-normalize/-/ipv6-normalize-1.0.1.tgz",
25263
+ "integrity": "sha1-GzJYKQ02X6gyOeiZB93kWS52IKg="
25264
+ },
25265
"is-arrayish": {
25266
"version": "0.2.1"
25267
},
@@ -25110,6 +25298,14 @@
25298
"ci-info": "^2.0.0"
25299
}
25300
},
25301
+ "is-cidr": {
25302
+ "version": "4.0.2",
25303
+ "resolved": "https://registry.npmjs.org/is-cidr/-/is-cidr-4.0.2.tgz",
25304
+ "integrity": "sha512-z4a1ENUajDbEl/Q6/pVBpTR1nBjjEE1X7qb7bmWYanNnPoKAvUCPFKeXV6Fe4mgTkWKBqiHIcwsI3SndiO5FeA==",
25305
+ "requires": {
25306
+ "cidr-regex": "^3.1.1"
25307
+ }
25308
+ },
25309
"is-class-hotfix": {
25310
"version": "0.0.6"
25311
},
@@ -25163,6 +25359,14 @@
25359
"is-path-inside": "^3.0.2"
25360
}
25361
},
25362
+ "is-ip": {
25363
+ "version": "3.1.0",
25364
+ "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz",
25365
+ "integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==",
25366
+ "requires": {
25367
+ "ip-regex": "^4.0.0"
25368
+ }
25369
+ },
25370
"is-module": {
25371
"version": "1.0.0",
25372
"dev": true
@@ -26426,6 +26630,11 @@
26630
"esprima": "^4.0.0"
26631
}
26632
},
26633
+ "jsbn": {
26634
+ "version": "1.1.0",
26635
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
26636
+ "integrity": "sha1-sBMHyym2GKHtJux56RH4A8TaAEA="
26637
+ },
26638
"jsdom": {
26639
"version": "16.7.0",
26640
"dev": true,
@@ -29328,8 +29537,7 @@
29537
"string-natural-compare": {
29538
"version": "3.0.1",
29539
"resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz",
29331
- "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==",
29332
- "dev": true
29540
+ "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw=="
29541
},
29542
"string-width": {
29543
"version": "4.2.3",
server/package.json
+1
@@ -13,6 +13,7 @@
13
"@koa/router": "^10.1.1",
14
"@node-rs/crc32": "^1.3.1",
15
"buffer-crc32": "https://github.com/rejetto/buffer-crc32.git",
16
+ "cidr-tools": "^4.3.0",
17
"fast-glob": "^3.2.7",
18
"find-process": "^1.4.7",
19
"koa": "^2.13.4",
server/src/block.ts
new
+36
@@ -0,0 +1,36 @@
1
+import { subscribeConfig } from './config'
2
+import { getConnections } from './connections'
3
+import { onlyTruthy, with_ } from './misc'
4
+import cidr from 'cidr-tools'
5
+import _ from 'lodash'
6
+import { Socket } from 'net'
7
+
8
+subscribeConfig({ k: 'block', defaultValue: [] }, (rules: any) => {
9
+ compileBlock(rules)
10
+ for (const { socket } of getConnections())
11
+ applyBlock(socket)
12
+})
13
+
14
+type BlockFun = (x: string) => boolean
15
+let blockFunctions: BlockFun[] = [] // "compiled" versions of the rules in config.block
16
+
17
+function compileBlock(rules: any) {
18
+ blockFunctions = !Array.isArray(rules) ? []
19
+ : onlyTruthy(rules.map(rule => !rule ? null
20
+ : with_(rule.ip, ip => typeof ip !== 'string' ? null
21
+ : ip.includes('/') ? x => cidr.contains(ip, x)
22
+ : ip.includes('*') ? with_(ipMask2regExp(ip), re => x => re.test(x) )
23
+ : x => x === ip
24
+ )
25
+ ))
26
+
27
+ function ipMask2regExp(ipMask: string) {
28
+ return new RegExp(_.escapeRegExp(ipMask).replace(/\\\*/g, '.*'))
29
+ }
30
+}
31
+
32
+export function applyBlock(socket: Socket) {
33
+ const ip = socket.remoteAddress
34
+ if (ip && blockFunctions.find(rule => rule(ip)))
35
+ return socket.destroy()
36
+}
server/src/middlewares.ts
+2
-14
@@ -13,10 +13,9 @@ import { serveFileNode } from './serveFile'
13
import { serveGuiFiles } from './serveGuiFiles'
14
import mount from 'koa-mount'
15
import { Readable } from 'stream'
16
+import { applyBlock } from './block'
17
import { getAccount, getCurrentUsername } from './perm'
17
-import { getConfig, subscribeConfig } from './config'
18
-import { getConnections, socket2connection, updateConnection } from './connections'
19
-import { Socket } from 'net'
18
+import { socket2connection, updateConnection } from './connections'
19
20
export const gzipper = compress({
21
threshold: 2048,
@@ -115,17 +114,6 @@ export const someSecurity: Koa.Middleware = async (ctx, next) => {
114
export function getProxyDetected() {
115
return proxyDetected
116
}
118
-
119
-subscribeConfig({ k: 'block', defaultValue: [] }, () => {
120
- for (const { socket } of getConnections())
121
- applyBlock(socket)
122
-})
123
-
124
-function applyBlock(socket: Socket) {
125
- if (getConfig('block').find((rule:any) => rule.ip === socket.remoteAddress))
126
- return socket.destroy()
127
-}
128
-
117
export const prepareState: Koa.Middleware = async (ctx, next) => {
118
// calculate these once and for all
119
ctx.state.account = getAccount(getCurrentUsername(ctx))
todo.md
-1
@@ -17,7 +17,6 @@
17
- command line help --help
18
- download-counter: expose results on admin
19
- frontend: make a "login" route, and link it in side the 404's suggest-login message
20
-- block to support masks and CIDR
20
- whitelist di ip
21
- plugin to show country by ip in admin/monitor
22
- log filter option