COCPORN
COCPORN2mo ago

I need the remote IP address in queries/mutations/actions

SSIA. This is a potential showstopper for us. Would preferrably be available in a section of the ctx-object passed.
11 Replies
ampp
ampp2mo ago
It's fairly simple there is a session Wrapper for all the front end hooks and you send a custom session variable and hash it if you like. I mean its better to do it with clerk but assuming everyone is anonymous its a bit harder. But its just having rules and if they cheat the system then there are other counter measures you have to implment. We establish anonymous sessions by browser window, we can track all the ips and have a per ip rate limit too. Spoofing is so easy that's why most people use cloudflare and captia and establish a real user before they can even send the first message to a backend to create a handshake.
COCPORN
COCPORNOP2mo ago
I don't understand how it can conceivably be difficult to understand what I am asking for. I am not asking for session wrapping. I am not asking for user identity. I am not asking for rate limiting. I am asking for this: The remote IP address Disregard any usage pattern. I am asking for The remote IP address. I am not asking for spoofing protection. This is literally on the connecting socket, I am asking to have it passed on the context (or similar). Don't worry about the usage, I don't need solved problems I don't have.
ampp
ampp2mo ago
It's not available and you aren't the first one to ask for it. Using an ip to rate limit like you want is pre-2010 effectiveness, it stops a percentage of attacks i suppose. These hosted endpoints are controlled by aws and as i understand its some deep cloud infrastructure thing that if it was exposed it wouldn't actually mitigate the problem thus it is not, to keep us from wasting our time. Plus its safe to assume there is some intelligent ddos layers wrapping the whole aws network. So i wonder if someone has figured a way to expose it on self hosting. But basically, the simplest way to do it is to just include it in the args takes like 5 minutes
COCPORN
COCPORNOP2mo ago
Including it in the args leaves it up to the client to set it itself. Which makes it absolutely pointless. This is baffling to me. That explicity saying in #general that I am not only using it for rate-limiting and repeatedly saying I am not only using it for rate limiting still triggers "Using an ip to rate limit like you want is pre-2010 effectiveness" in your brain prompts me to ask to please leave this thread alone. If the explanation is "We cannot honor X-Forwarded-For"-headers for whatever reason, that's at least something. It's not like AWS makes it impossible to find remote IP-addresses. BTW, logging remote addresses is effectively required for a number of certifications, one of which we are seeking provided we get investor funding. So it doesn't help that the Convex platform itself is compliant with whatever if it is exorbitantly painful to create certifiable solutions with it. And, as I mentioned in #general, logging is one of the key areas I need this for. But arguing for it shouldn't be necessary, getting the remote IP address should be technically simple and not something one would need to explain to anyone why.
Jakov
Jakov2mo ago
I created a github issue: https://github.com/get-convex/convex-backend/issues/130 They aren't active on github issues. I don't think they will implement it soon.
GitHub
Remote IP address in queries/mutations/actions · Issue #130 · get...
Some compliance and certification processes (such as audit logging or user tracing) require logging the remote IP address of the client making the request. Currently, there doesn’t appear to be a b...
COCPORN
COCPORNOP2mo ago
This is great, it perfectly captures what I am looking for.
COCPORN
COCPORNOP2mo ago
So yeah, there's this in the local server now. The query is:
export const getRemoteInfo = query({
args: {
greeting: v.string(),
},
handler: async (ctx, args) => {
console.log("remoteIp", ctx.remoteIp);
return {
echo: args.greeting,
remoteIp: ctx.remoteIp,
requestId: ctx.requestId,
executionId: ctx.executionId,
isRoot: ctx.isRoot,
};
},
});
export const getRemoteInfo = query({
args: {
greeting: v.string(),
},
handler: async (ctx, args) => {
console.log("remoteIp", ctx.remoteIp);
return {
echo: args.greeting,
remoteIp: ctx.remoteIp,
requestId: ctx.requestId,
executionId: ctx.executionId,
isRoot: ctx.isRoot,
};
},
});
...returning...
TypeScript: Final query context:' {
db: {
get: [Function: get],
query: [Function: query],
normalizeId: [Function: normalizeId],
system: {
get: [Function: get],
query: [Function: query],
normalizeId: [Function: normalizeId],
table: [Function: table]
},
table: [Function: table]
},
auth: {
getUserIdentity: [Function: getUserIdentity]
},
storage: {
getUrl: [Function: getUrl],
getMetadata: [Function: getMetadata]
},
runQuery: [Function: runQuery],
requestId: '03385157a725240f',
executionId: '25f44a37-b6cb-4b0b-bc8b-b186ac7a5a57',
isRoot: true,
remoteIp: '127.0.0.1:61919',
testValue: 'HELLO_FROM_RUST',
parentScheduledJob: null,
parentScheduledJobComponentId: null
}
TypeScript: Final query context:' {
db: {
get: [Function: get],
query: [Function: query],
normalizeId: [Function: normalizeId],
system: {
get: [Function: get],
query: [Function: query],
normalizeId: [Function: normalizeId],
table: [Function: table]
},
table: [Function: table]
},
auth: {
getUserIdentity: [Function: getUserIdentity]
},
storage: {
getUrl: [Function: getUrl],
getMetadata: [Function: getMetadata]
},
runQuery: [Function: runQuery],
requestId: '03385157a725240f',
executionId: '25f44a37-b6cb-4b0b-bc8b-b186ac7a5a57',
isRoot: true,
remoteIp: '127.0.0.1:61919',
testValue: 'HELLO_FROM_RUST',
parentScheduledJob: null,
parentScheduledJobComponentId: null
}
...so I need to do some cleanup.
No description
COCPORN
COCPORNOP2w ago
That is, the code returns this:
{"echo":"hello","executionId":"25f44a37-b6cb-4b0b-bc8b-b186ac7a5a57","isRoot":true,"remoteIp":"127.0.0.1:61919","requestId":"03385157a725240f"}
{"echo":"hello","executionId":"25f44a37-b6cb-4b0b-bc8b-b186ac7a5a57","isRoot":true,"remoteIp":"127.0.0.1:61919","requestId":"03385157a725240f"}
So hopefully this can be iterated on. Also, it doesn't support X-Forwarded-For, but I don't think it needs to, we'll see. I am rewriting it to be zero overhead when it isn't used. It is probably not a very good implementation, but perhaps something that can be used as a starting point. https://github.com/get-convex/convex-backend/pull/132 Has this been looked at? A way to handle this is now a hard blocker on a project I am working on, where I adamantly recommended Convex. Please, paid customer here, I feel like I am being stonewalled. Even a "we're now making this" is OK, so I can consider changing access to the free part of the service, changing the signup UX or shifting away from Convex. I'm pinging you, @ballingt, as you were the last to respond to the PR. (Again, I am not asking to have the PR merged as is, I just really need an answer on this.)
ballingt
ballingt2w ago
It's on the tentative plan for the next 6 weeks, so nothing guaranteed still but we understand it's something people want Appreciate your PR @COCPORN, thanks for diving in to see how it's done My boss has said several times "hey can we add that yet?" and things keep coming up so I say no, but at least for actions and httpActions it's not controversial
COCPORN
COCPORNOP2w ago
I would appreciate it if you prioritized this. Not only for actions but for mutations and queries too. It is a blocker for us because we are going to be processing payments and we cannot be compliant without it. I am not going to do deep packet inspection before I route to Convex, then I'd rather just switch to another platform. Thanks for the update.
ballingt
ballingt2w ago
Queries is going to be delicate, but everything else is doable soon. For queries you fragment your cache key by accessing the client IP, so might say just use a mutation if you need this. But also possible. Thanks for the feedback, I'll highlight it internally.

Did you find this page helpful?