-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make it possible to forcibly RST a net.Socket #27428
Comments
Have you tried doing a |
Interesting! You're right, it's possible to make that work, but it ends up a little hacky. You can get close by translating the Python code and removing the delay, but you have a race to make sure you destroy after the request is sent but before the server response. To test I'm doing that with I'd like to leave this open, as I would much prefer to be able to explicitly send the RST myself on demand rather than depending on this. It's easy to imagine similar situations where you don't know that there's imminent incoming data from the server, so The resulting JS code for reference: const net = require('net');
const socket = new net.Socket();
socket.connect(8000, "127.0.0.1", () => {
socket.write(
`CONNECT example.com:80 HTTP/1.1
Host: example.com
GET / HTTP/1.1
Host: example.com
`
);
// If this is synchronous, it doesn't work
// If it waits for write(), but no longer, it 50% works
// Scheduling it immediately seems fairly reliable
setTimeout(() => socket.destroy(), 0);
}); |
Get rid of the setTimeout, its racy because Btw, you describe this as hacky, but I'm not sure that is fair. Many things can cause an RST, but most of them are TCP protocol violations, and faking a bug in the OS TCP stack is probably not something node tests need to do. The most common cause of an RST is exactly what you are doing: a socket is read-closed, but the peer continues to send data. |
Sadly I tested
I'm not sure about the reasons, but I'm seeing a fair few unexpected RST packets from end-user clients, in real-world HTTP traffic. My product is an HTTP debugger (httptoolkit.tech) - effectively a local HTTP proxy for developers - this is coming from my end-user error reporting, with RST packets being sent by whatever people are connecting to that. For me it'd be really useful to able to precisely reproduce that behaviour in my tests. |
Any client that does |
See libuv/libuv#1991 (comment), the main problem is the interaction between SO_LINGER and shutdown(). |
Since this suggestion, I'd still find this useful. I'm in the same situation again right now of trying to test certain kinds of error reporting & handling with RST packets, and some cases are still not testable in node without a separate tool (Python). |
@pimterry That's right. Pull request welcome, the places to look at are I'm inclined to leave out a forwarding method on |
I'd like to prepare PR, any suggestions on method name? |
@kolontsov Just spitballing: |
@bnoordhuis sounds great. ok. |
Any progress on that one? |
I've been investigating this for a while, although I'm a bit lost in the source code... Will update if I make any progress |
Any update on this issue? |
I haven't found any new ways, but if nodejs ever introduces a way to set socket options, the way to send a RST (on UNIX-like systems) is to use setsockopt(2) to enable SO_LINGER with a timeout of 0, and close(2) the socket. No idea for Windows though. |
Hi folks, Now I can reset a TCP socket in my Javascript code, using my own Node build. To achieve it, I added a wrap function Also, I have some suggestions and questions to ask:
|
make it possible to forcibly rest a tcp socket: * add a new method `Socket.prototype.resetAndDestroy` * add a new flag `resetAndClosing` to make `_destroy` calls the `reset` instead of close while destroying a Socket. * add new methods `TCPWrap::Reset` to be a wrap of `uv_tcp_close_reset` * change `HandleWrap::state_` from private to protected. This is essential for keeping the same behaviour between `TCPWrap::Reset` and `HandleWrap::Close` Fixes: nodejs#27428
#43112 |
make it possible to forcibly rest a tcp socket: * add a new method `Socket.prototype.resetAndDestroy` * add a new flag `resetAndClosing` to make `_destroy` calls the `reset` instead of close while destroying a Socket. * add new methods `TCPWrap::Reset` to be a wrap of `uv_tcp_close_reset` * change `HandleWrap::state_` from private to protected. This is essential for keeping the same behaviour between `TCPWrap::Reset` and `HandleWrap::Close` Fixes: nodejs#27428
make it possible to forcibly rest a tcp socket: * add a new method `Socket.prototype.resetAndDestroy` * add a new flag `resetAndClosing` to make `_destroy` calls the `reset` instead of close while destroying a Socket. * add new methods `TCPWrap::Reset` to be a wrap of `uv_tcp_close_reset` * change `HandleWrap::state_` from private to protected. This is essential for keeping the same behaviour between `TCPWrap::Reset` and `HandleWrap::Close` Fixes: nodejs#27428
make it possible to forcibly rest a tcp socket: * add a new method `Socket.prototype.resetAndDestroy` * add a new flag `resetAndClosing` to make `_destroy` calls the `reset` instead of close while destroying a Socket. * add new methods `TCPWrap::Reset` to be a wrap of `uv_tcp_close_reset` * change `HandleWrap::state_` from private to protected. This is essential for keeping the same behaviour between `TCPWrap::Reset` and `HandleWrap::Close` Fixes: nodejs#27428
make it possible to forcibly rest a tcp socket: * add a new method `Socket.prototype.resetAndDestroy` * add a new flag `resetAndClosing` to make `_destroy` calls the `reset` instead of close while destroying a Socket. * add new methods `TCPWrap::Reset` to be a wrap of `uv_tcp_close_reset` * change `HandleWrap::state_` from private to protected. This is essential for keeping the same behaviour between `TCPWrap::Reset` and `HandleWrap::Close` Fixes: nodejs#27428
Fixes: nodejs/node#27428 PR-URL: nodejs/node#43112 Reviewed-By: Paolo Insogna <paolo@cowtech.it> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
Is your feature request related to a problem? Please describe.
I'd like to forcibly reset a socket. Primarily for testing - I'm seeing unexpected RST packets in production, which is crashing my node HTTP proxy (my bug, that's fine), and I'd like to be able to write automated tests to ensure I've fixed correctly.
As far as I can tell it's only possible to cleanly close sockets with FIN, you can never intentionally RST.
Describe the solution you'd like
Something like
socket.reset()
would be great for my specific case, or alternatively low-level controls (e.g. the ability to set socket options as in the Python code below) would be equally useful.Describe alternatives you've considered
For now, I've implemented this in Python instead. This Python 2.7.1 code is working for me:
Obviously I'd much prefer to test my Node server with JavaScript though, instead of having to bring in another language.
The text was updated successfully, but these errors were encountered: