caddy icon indicating copy to clipboard operation
caddy copied to clipboard

bytes_read for hijacked connections?

Open Mygod opened this issue 1 year ago • 22 comments

Is there anyway to add bytes_read to the entry if the connection is hijacked, like in forwardproxy? lengthReader is not exported. 🤔

Mygod avatar Aug 10 '23 05:08 Mygod

This could probably be done, but it will take some careful work :)

mholt avatar Aug 10 '23 18:08 mholt

I guess I will just use reflection meanwhile. :)

Mygod avatar Sep 09 '23 00:09 Mygod

I guess we can probably export lengthReader. I don't see why not. The only harm that could be done is some module manipulated Length when it shouldn't but why would a module shoot itself in the foot by doing that lol

francislavoie avatar Sep 09 '23 01:09 francislavoie

While we are on this, can you also export responseRecorder.size and have a way to extract Conn from hijacked connection? For proxies this is useful since this way io.Copy will be able to use splice and do everything in kernel space. (No more userspace buffers!)

Mygod avatar Sep 09 '23 01:09 Mygod

Exporting caddyhttp.responseRecorder struct should not be necessary because we already export the caddyhttp.ResponseRecorder interface which has a Size() function.

francislavoie avatar Sep 09 '23 09:09 francislavoie

Yes but that is read-only. I am trying to add to the counter...

Mygod avatar Sep 09 '23 17:09 Mygod

https://man7.org/linux/man-pages/man2/splice.2.html

Linux syscall splice takes fds directly and returns copied bytes. It is not feasible to use responseRecorder.

Mygod avatar Sep 09 '23 17:09 Mygod

Yes but that is read-only. I am trying to add to the counter...

Ah, that makes sense. We could maybe add an IncrementSize(int n) method? :thinking:

Linux syscall splice takes fds directly and returns copied bytes. It is not feasible to use responseRecorder.

I'm not sure I understand, are you saying "nevermind I don't need it actually" with that?

francislavoie avatar Sep 09 '23 21:09 francislavoie

Quite the opposite. I was explaining why I needed those. Currently I am using reflection like this.

Mygod avatar Sep 09 '23 22:09 Mygod

Okay. Would IncrementSize(int n) work for you?

It's awkward, we can't rename caddyhttp.responseRecorder to caddyhttp.ResponseRecorder because it already exists as an interface (name conflict) so it would have to be renamed as something else and I can't think of a name that would work. We also probably shouldn't rename the interface because it's already exported and "part of the API" (even if I doubt many plugins actually use it right now).

francislavoie avatar Sep 09 '23 22:09 francislavoie

Yes that would work, and I also would like an API for getting the underlying Conn returned from hijacked connection. 😅

Mygod avatar Sep 09 '23 22:09 Mygod

I'm not sure I understand, your code is what calls Hijack(). It becomes your code's responsibility to handle the Conn.

francislavoie avatar Sep 10 '23 02:09 francislavoie

That is indeed what my code is doing. I am just wondering if the reflection part I highlighted above can be replaced with stable API. :)

Mygod avatar Sep 10 '23 02:09 Mygod

I wonder, should we be counting the bytes written even after a hijack?

mholt avatar Sep 10 '23 03:09 mholt

I wonder, should we be counting the bytes written even after a hijack?

It would be a good idea not to for the reasons I specified above (kernel space io.Copy). Exposing a separate interface for logging bytes is preferred?

Mygod avatar Oct 23 '23 15:10 Mygod

I'm lost at this point. What's the status quo? Do we still need https://github.com/caddyserver/caddy/pull/5807? Is it useful?

francislavoie avatar Jan 13 '24 21:01 francislavoie

I think #5807 needs also support for updating read bytes...

Mygod avatar Jan 13 '24 22:01 Mygod

It's exported, you can just increment .Length :thinking:

francislavoie avatar Jan 13 '24 23:01 francislavoie

That's written bytes. I think the API for bytes read is .size. I'm currently doing this reflection as workaround.

Mygod avatar Jan 14 '24 15:01 Mygod

Ah, so you're asking for responseRecorder as well.

https://github.com/caddyserver/caddy/blob/master/modules%2Fcaddyhttp%2Fresponsewriter.go#L61-L69

@mholt are you ok with exporting that too?

francislavoie avatar Jan 14 '24 17:01 francislavoie

If we do, we'd essentially be replacing the interface with a concrete type:

https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/responsewriter.go#L266

I don't know anywhere that we use the interface with another type, so that should be fine.

mholt avatar Jan 17 '24 00:01 mholt

@mholt I'm trying to do that now, but I get errors all over, like:

cannot use rr (variable of type ResponseRecorder) as io.Writer value in argument to io.Copy: ResponseRecorder does not implement io.Writer (method Write has pointer receiver) compiler(InvalidIfaceAssign)

I don't quite understand how to do this, apparently it can't be an io.Writer because we're using a pointer receiver, which is necessary to update size while writing :thinking:

francislavoie avatar Jan 17 '24 01:01 francislavoie

@Mygod at this point I don't think I'll be able to finish this, so it might make more sense if you write the PR for this.

francislavoie avatar Mar 06 '24 15:03 francislavoie

@Mygod size is already updated when writing and Reading From. The only things left are WriteTo and number of bytes read.

If you really want to use the underlying net.Conn to do splice, checkout caddyhttp.ConnCtxKey. Though I guess you already know you need to Hijack first to use it safely and handling already buffered data.

WeidiDeng avatar Mar 15 '24 00:03 WeidiDeng