diff --git a/account/accountpersistence.js b/account/accountpersistence.js index 000a365..b2873cf 100644 --- a/account/accountpersistence.js +++ b/account/accountpersistence.js @@ -22,14 +22,7 @@ module.exports = ( fastify, opts, done ) => { }, }, async ( request, response ) => { - - let clientIp = request.ip - - // pull the client ip address from a custom header if one is specified - if (process.env.CLIENT_IP_HEADER && request.headers[process.env.CLIENT_IP_HEADER]) - clientIp = request.headers[process.env.CLIENT_IP_HEADER] - - // check if account exists + // check if account exists let account = await accounts.AsyncGetPlayerByID( request.query.id ) if ( !account ) return null @@ -37,12 +30,12 @@ module.exports = ( fastify, opts, done ) => { // if the client is on their own server then don't check this since their own server might not be on masterserver if ( account.currentServerId == "self" ) { // if the ip sending the request isn't the same as the one that last authed using client/origin_auth then don't update - if ( clientIp != account.lastAuthIp ) + if ( request.ip != account.lastAuthIp ) return null } else { let server = GetGameServers()[ request.query.serverId ] // dont update if the server doesnt exist, or the server isnt the one sending the heartbeat - if ( !server || clientIp != server.ip || account.currentServerId != request.query.serverId ) + if ( !server || request.ip != server.ip || account.currentServerId != request.query.serverId ) return null } diff --git a/cfaddresses.txt b/cfaddresses.txt new file mode 100644 index 0000000..b2035b7 --- /dev/null +++ b/cfaddresses.txt @@ -0,0 +1,24 @@ +# ipv4 +173.245.48.0/20 +103.21.244.0/22 +103.22.200.0/22 +103.31.4.0/22 +141.101.64.0/18 +108.162.192.0/18 +190.93.240.0/20 +188.114.96.0/20 +197.234.240.0/22 +198.41.128.0/17 +162.158.0.0/15 +104.16.0.0/13 +104.24.0.0/14 +172.64.0.0/13 +131.0.72.0/22 +# ipv6 +2400:cb00::/32 +2606:4700::/32 +2803:f800::/32 +2405:b500::/32 +2405:8100::/32 +2a06:98c0::/29 +2c0f:f248::/32 diff --git a/client/clientauth.js b/client/clientauth.js index c2fd1fa..740a364 100644 --- a/client/clientauth.js +++ b/client/clientauth.js @@ -62,13 +62,7 @@ module.exports = ( fastify, opts, done ) => { let authToken = crypto.randomBytes( 16 ).toString( "hex" ) accounts.AsyncUpdateCurrentPlayerAuthToken( account.id, authToken ) - let clientIp = request.ip - - // pull the client ip address from a custom header if one is specified - if (process.env.CLIENT_IP_HEADER && request.headers[process.env.CLIENT_IP_HEADER]) - clientIp = request.headers[process.env.CLIENT_IP_HEADER] - - accounts.AsyncUpdatePlayerAuthIp( account.id, clientIp ) + accounts.AsyncUpdatePlayerAuthIp( account.id, request.ip ) return { success: true, diff --git a/dev.env b/dev.env index 03b9a0a..eb16b52 100644 --- a/dev.env +++ b/dev.env @@ -5,14 +5,11 @@ LISTEN_IP=0.0.0.0 LISTEN_PORT=8080 REQUIRE_SESSION_TOKEN= -# if the proxy provides a custom header to get the client's ip address -# (example: cloudflare uses CF-Connecting-IP) -CLIENT_IP_HEADER= - # not used for dev SSL_KEY_PATH= SSL_CERT_PATH= TRUST_PROXY= +TRUST_PROXY_LIST_PATH= # ratelimit USE_RATELIMIT=1 @@ -27,4 +24,4 @@ REQ_PER_MINUTE__SERVER_ADDSERVER=5 REQ_PER_MINUTE__SERVER_HEARTBEAT=60 REQ_PER_MINUTE__SERVER_UPDATEVALUES=20 REQ_PER_MINUTE__SERVER_REMOVESERVER=5 -REQ_PER_MINUTE__ACCOUNT_WRITEPERSISTENCE=50 \ No newline at end of file +REQ_PER_MINUTE__ACCOUNT_WRITEPERSISTENCE=50 diff --git a/index.js b/index.js index 77f9bb9..1499724 100644 --- a/index.js +++ b/index.js @@ -7,6 +7,12 @@ else const fs = require( "fs" ) const path = require( "path" ) +let trustProxy = !!(process.env.TRUST_PROXY) +if(trustProxy && process.env.TRUST_PROXY_LIST_PATH) { + let addressList = fs.readFileSync( process.env.TRUST_PROXY_LIST_PATH ).toString(); + trustProxy = addressList.split("\r\n").map(a => a.trim()).filter(a => !a.startsWith("#") && a != '') +} + let fastify = require( "fastify" ) if ( process.env.USE_HTTPS ) { @@ -16,14 +22,14 @@ if ( process.env.USE_HTTPS ) key: fs.readFileSync( process.env.SSL_KEY_PATH ), cert: fs.readFileSync( process.env.SSL_CERT_PATH ) }, - trustProxy: !!(process.env.TRUST_PROXY) + trustProxy }) } else { fastify = fastify({ logger: process.env.USE_FASTIFY_LOGGER || false, - trustProxy: !!(process.env.TRUST_PROXY) + trustProxy }) } diff --git a/server/gameserver.js b/server/gameserver.js index fa2653c..400747c 100644 --- a/server/gameserver.js +++ b/server/gameserver.js @@ -14,13 +14,6 @@ async function SharedTryAddServer( request ) { // check server's verify endpoint on their auth server, make sure it's fine // in the future we could probably check the server's connect port too, with a c2s_connect packet or smth, but atm this is good enough - - let clientIp = request.ip - - // pull the client ip address from a custom header if one is specified - if (process.env.CLIENT_IP_HEADER && request.headers[process.env.CLIENT_IP_HEADER]) - clientIp = request.headers[process.env.CLIENT_IP_HEADER] - let hasValidModInfo = true let modInfo @@ -36,7 +29,7 @@ async function SharedTryAddServer( request ) let authServerResponse = await asyncHttp.request( { method: "GET", - host: clientIp, + host: request.ip, port: request.query.authPort, path: "/verify" }) @@ -80,7 +73,7 @@ async function SharedTryAddServer( request ) let name = filter.clean( request.query.name ) let description = request.query.description == "" ? "" : filter.clean( request.query.description ) - let newServer = new GameServer( name, description, playerCount, request.query.maxPlayers, request.query.map, request.query.playlist, clientIp, request.query.port, request.query.authPort, request.query.password, modInfo ) + let newServer = new GameServer( name, description, playerCount, request.query.maxPlayers, request.query.map, request.query.playlist, request.ip, request.query.port, request.query.authPort, request.query.password, modInfo ) AddGameServer( newServer ) return { @@ -130,16 +123,9 @@ module.exports = ( fastify, opts, done ) => { } }, async ( request, reply ) => { - - let clientIp = request.ip - - // pull the client ip address from a custom header if one is specified - if (process.env.CLIENT_IP_HEADER && request.headers[process.env.CLIENT_IP_HEADER]) - clientIp = request.headers[process.env.CLIENT_IP_HEADER] - let server = GetGameServers()[ request.query.id ] // dont update if the server doesnt exist, or the server isnt the one sending the heartbeat - if ( !server || clientIp != server.ip || !request.query.id )// remove !request.playerCount as if playercount==0 it will trigger skip heartbeat update + if ( !server || request.ip != server.ip || !request.query.id )// remove !request.playerCount as if playercount==0 it will trigger skip heartbeat update { return null } @@ -156,16 +142,10 @@ module.exports = ( fastify, opts, done ) => { // updates values shown on the server list, such as map, playlist, or player count // no schema for this one, since it's fully dynamic and fastify doesnt do optional params fastify.post( '/server/update_values', - { + { config: { rateLimit: getRatelimit("REQ_PER_MINUTE__SERVER_UPDATEVALUES") }, // ratelimit - }, + }, async ( request, reply ) => { - let clientIp = request.ip - - // pull the client ip address from a custom header if one is specified - if (process.env.CLIENT_IP_HEADER && request.headers[process.env.CLIENT_IP_HEADER]) - clientIp = request.headers[process.env.CLIENT_IP_HEADER] - if ( !( "id" in request.query ) ) return null @@ -176,7 +156,7 @@ module.exports = ( fastify, opts, done ) => { { return SharedTryAddServer( request ) } - else if ( clientIp != server.ip ) // dont update if the server isnt the one sending the heartbeat + else if ( request.ip != server.ip ) // dont update if the server isnt the one sending the heartbeat return null // update heartbeat @@ -214,7 +194,7 @@ module.exports = ( fastify, opts, done ) => { async ( request, reply ) => { let server = GetGameServers()[ request.query.id ] // dont remove if the server doesnt exist, or the server isnt the one sending the heartbeat - if ( !server || clientIp != server.ip ) + if ( !server || request.ip != server.ip ) return null RemoveGameServer( server )