simplify ipv6-mapped addresses, for easier reading and blocking
Massimo Melina committed
Apr 19, 2022 at 18:29 UTC
403b5656b1cd320b9f226f5e3ae9a628ed548d8c
4 files changed
+28
-21
server/src/adminApis.ts
+1
-1
@@ -86,7 +86,7 @@ export const adminApis: ApiHandlers = {
86
connectionClosed(conn: Connection) {
87
list.remove(serializeConnection(conn, true))
88
},
89
- connectionUpdated(conn: Connection, change: Partial<Connection>) {
89
+ connectionUpdated(conn: Connection, change: Partial<Omit<Connection,'ip'>>) {
90
if (change.ctx) {
91
Object.assign(change, fromCtx(change.ctx))
92
delete change.ctx
server/src/block.ts
+3
-4
@@ -7,8 +7,8 @@ import { Socket } from 'net'
7
8
subscribeConfig({ k: 'block', defaultValue: [] }, (rules: any) => {
9
compileBlock(rules)
10
- for (const { socket } of getConnections())
11
- applyBlock(socket)
10
+ for (const { socket, ip } of getConnections())
11
+ applyBlock(socket, ip)
12
})
13
14
type BlockFun = (x: string) => boolean
@@ -29,8 +29,7 @@ function compileBlock(rules: any) {
29
}
30
}
31
32
-export function applyBlock(socket: Socket) {
33
- const ip = socket.remoteAddress
32
+export function applyBlock(socket: Socket, ip=socket.remoteAddress) {
33
if (ip && blockFunctions.find(rule => rule(ip)))
34
return socket.destroy()
35
}
server/src/connections.ts
+22
-15
@@ -4,29 +4,36 @@ import { Socket } from 'net'
4
import events from './events'
5
import Koa from 'koa'
6
7
-export interface Connection {
8
- socket: Socket
9
- secure: boolean
10
- started: Date
11
- got: number
12
- sent: number
7
+export class Connection {
8
+ readonly started = new Date()
9
+ got = 0
10
+ sent = 0
11
+ alreadyEmitted = false // already communicated to
12
outSpeed?: number
13
ctx?: Koa.Context
15
- alreadyEmitted: boolean // already communicated to
14
+ private _cachedIp?: string
15
[rest:symbol]: any // let other modules add extra data, but using symbols to avoid name collision
16
+
17
+ constructor(readonly socket: Socket,readonly secure: boolean) {
18
+ all.push(this)
19
+ socket.on('data', data =>
20
+ this.got += data.length )
21
+ socket.on('close', () => {
22
+ all.splice(all.indexOf(this), 1)
23
+ events.emit('connectionClosed', this)
24
+ })
25
+ }
26
+
27
+ get ip() {
28
+ return this.ctx?.ip ?? (this._cachedIp = (this._cachedIp ?? this.socket.remoteAddress?.replace(/^::ffff:/,'')))
29
+ }
30
}
31
32
+
33
const all: Connection[] = []
34
35
export function newConnection(socket: Socket, secure:boolean=false) {
22
- const conn: Connection = { socket, secure, got: 0, sent: 0, alreadyEmitted: false, started: new Date() }
23
- all.push(conn)
24
- socket.on('data', data =>
25
- conn.got += data.length )
26
- socket.on('close', () => {
27
- all.splice(all.indexOf(conn), 1)
28
- events.emit('connectionClosed', conn)
29
- })
36
+ new Connection(socket, secure)
37
}
38
39
export function getConnections(): Readonly<typeof all> {
server/src/middlewares.ts
+2
-1
@@ -92,6 +92,7 @@ export const serveGuiAndSharedFiles: Koa.Middleware = async (ctx, next) => {
92
93
let proxyDetected = false
94
export const someSecurity: Koa.Middleware = async (ctx, next) => {
95
+ ctx.request.ip = ctx.ip.replace(/^::ffff:/,'') // simplify ipv6-mapped addresses
96
try {
97
let proxy = ctx.get('X-Forwarded-For')
98
// we have some dev-proxies to ignore
@@ -99,7 +100,7 @@ export const someSecurity: Koa.Middleware = async (ctx, next) => {
100
proxy = ''
101
if (dirTraversal(decodeURI(ctx.path)))
102
return ctx.status = 418
102
- if (applyBlock(ctx.socket))
103
+ if (applyBlock(ctx.socket, ctx.ip))
104
return
105
proxyDetected ||= proxy > ''
106
ctx.state.proxiedFor = proxy