What port does Ruby's net/http use? - ruby

I am using Ruby's net/http library to send RESTful requests to my dev server. I've been having issues correctly parsing the data I'm sending in the request and so I'm not looking into ways to inspect the request I'm sending out through Ruby.
On another question I posted here, asking how JSON data was sent in an http request, I received a comment saying that I could possibly inspect the request by using TCPMon. In order to use TCPMon though to check the request, I need to know which port to look for the request on.
And that brings me here. What port does Ruby (and net/http) use to send out HTTP requests?

Unless otherwise specified, it will make requests to port 80 for http requests, and port 443 for https requests (the standard http/https ports).
However, you'll set up TCPMon to listen to requests on a certain port, and then forward them on to their destination. So if TCPMon is listening on 8080, you'll make the requests to port 8080.

The standard port for HTTP is port 80. If you don't specify a port in the URL, that's what it will use.
There's nothing special about port 80, it's just the standard for HTTP. You can run your server on any numeric port you want, test servers often run on something like 8080 or 8000, but you'll have to ensure your clients are connecting to that port.
Here's a list of standard TCP and UDP ports.

Related

Does http3/quic fall back to tls 1.2 if the browser doesn't support quic?

Even after lots of googling, I'm pretty naive about quic.
I'm specifically looking into lucasclemente/go-quic.
Should quic servers use 443? If so, will it fallback to http2 & tls 1.2?
I'm speaking generally. Not for that specific go package. But if you have specifics for that go package, that would be great.
Yes, I realize quic is still young and not necessary yet. I'm simply curious and couldn't find that specific answer. Thanks!
Quic servers can use any port they want; 443 is often used, but this is not necessary at all. Note we're talking about UDP ports, not TCP ports.
A QUIC server cannot fallback to HTTP2 or TLS 1.2, because if the client sends a QUIC request, the server can only respond with a QUIC response. If the browser doesn't support QUIC, it will not send a QUIC request in the first place, so there is no issue at all.
I think you are assuming that a QUIC server runs (or can run) on the same port as HTTPS and therefore has to generate either a QUIC or an HTTPS response; this is not the case, as QUIC is running over UDP, not over TCP (like HTTP and HTTPS do). TCP ports and UDP ports are different address spaces, so one can run an HTTPS server on tcp port 443 and simultaneously run another QUIC server on udp port 443.

Recording websocket messages

I need to extend a HTTP recorder to record websocket traffic. HTTP recorder is in C / unix platform.
I know HTTP traffic will be through port 80 or 443, hence I am able to record it. In HTTP message a new port is communicated, and through that port websocket traffic passes through. Since this port is dynamic, and HTTP messages will be different in different cases I can not parse and get port for websocket.
I think of below logic, not sure if that is going to work. Need your suggestion / pointers in this regard.
Make use of iptables
Forward all the traffic to a different port (where my application is listening) using iptable rules
Then my application should receive the data (hope it is possible)
Then my application should receive the destination information (when data is forwarded from iptables to my application, can I get actual destination ip/port).
Assuming, I get actual ip/port, then from my application, I can send data to actual destination.
I know, its a long way to go, will this approach work.

Shall I use WebSocket on ports other than 80?

Shall I use WebSocket on non-80 ports? Does it ruin the whole purpose of using existing web/HTTP infrastructures? And I think it no longer fits the name WebSocket on non-80 ports.
If I use WebSocket over other ports, why not just use TCP directly? Or is there any special benefits in the WebSocket protocol itself?
And since current WebSocket handshake is in the form of a HTTP UPGRADE request, does it mean I have to enable HTTP protocol on the port so that WebSocket handshake can be accomplished?
Shall I use WebSocket on non-80 ports? Does it ruin the whole purpose
of using existing web/HTTP infrastructures? And I think it no longer
fits the name WebSocket on non-80 ports.
You can run a webSocket server on any port that your host OS allows and that your client will be allowed to connect to.
However, there are a number of advantages to running it on port 80 (or 443).
Networking infrastructure is generally already deployed and open on port 80 for outbound connections from the places that clients live (like desktop computers, mobile devices, etc...) to the places that servers live (like data centers). So, new holes in the firewall or router configurations, etc... are usually not required in order to deploy a webSocket app on port 80. Configuration changes may be required to run on different ports. For example, many large corporate networks are very picky about what ports outbound connections can be made on and are configured only for certain standard and expected behaviors. Picking a non-standard port for a webSocket connection may not be allowed from some corporate networks. This is the BIG reason to use port 80 (maximum interoperability from private networks that have locked down configurations).
Many webSocket apps running from the browser wish to leverage existing security/login/auth infrastructure already being used on port 80 for the host web page. Using that exact same infrastructure to check authentication of a webSocket connection may be simpler if everything is on the same port.
Some server infrastructures for webSockets (such as socket.io in node.js) use a combined server infrastructure (single process, one listener) to support both HTTP requests and webSockets. This is simpler if both are on the same port.
If I use WebSocket over other ports, why not just use TCP directly? Or
is there any special benefits in the WebSocket protocol itself?
The webSocket protocol was originally defined to work from a browser to a server. There is no generic TCP access from a browser so if you want a persistent socket without custom browser add-ons, then a webSocket is what is offered. As compared to a plain TCP connection, the webSocket protocol offers the ability to leverage HTTP authentication and cookies, a standard way of doing app-level and end-to-end keep-alive ping/pong (TCP offers hop-level keep-alive, but not end-to-end), a built in framing protocol (you'd have to design your own packet formats in TCP) and a lot of libraries that support these higher level features. Basically, webSocket works at a higher level than TCP (using TCP under the covers) and offers more built-in features that most people find useful. For example, if using TCP, one of the first things you have to do is get or design a protocol (a means of expressing your data). This is already built-in with webSocket.
And since current WebSocket handshake is in the form of a HTTP UPGRADE
request, does it mean I have to enable HTTP protocol on the port so
that WebSocket handshake can be accomplished?
You MUST have an HTTP server running on the port that you wish to use webSocket on because all webSocket requests start with an HTTP request. It wouldn't have to be heavily featured HTTP server, but it does have to handle the initial HTTP request.
Yes - Use 443 (ie, the HTTPS port) instead.
There's little reason these days to use port 80 (HTTP) for anything other than a redirection to port 443 (HTTPS), as certification (via services like LetsEncrypt) are easy and free to set up.
The only possible exceptions to this rule are local development, and non-internet facing services.
Should I use a non-standard port?
I suspect this is the intent of your question. To this, I'd argue that doing so adds an unnecessary layer of complication with no obvious benefits. It doesn't add security, and it doesn't make anything easier.
But it does mean that specific firewall exceptions need to be made to host and connect to your websocket server. This means that people accessing your services from a corporate/school/locked down environment are probably not going to be able to use it, unless they can somehow convince management that it is mandatory. I doubt there are many good reasons to exclude your userbase in this way.
But there's nothing stopping you from doing it either...
In my opinion, yes you can. 80 is the default port, but you can change it to any as you like.

SocketIO tries to connect using same port as the browser used to get web page

I am serving content locally, accessible through http://0.0.0.0:4000. That works ok, I get a correct webpage, which contains the following line inside a script:
var socket = io('http://example.com');
i.e. I am referencing an external server. Now my browser shows the followoing error:
GET http://example.com:4000/socket.io/?EIO=3&transport=polling&t=1417447089410-1 net::ERR_CONNECTION_REFUSED
That is, the browser is trying to connect using the same port that it used to get the original page.
Everything works fine when both the SocketIO server and the web server listen on the same port.
Am I missing something? Is this a bug? Is there a workaround? Thank you.
You can read here about how a plain webSocket is initially set up. It all starts with a somewhat standard HTTP GET request, but one that has some special headers set:
GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
The interchange may also allow the host to enforce requests only from web pages on certain origins. While this header can be spoofed from non-web-browser agents (so the server has to be prepared for that), it will likely be correct when the OP is using a real browser (assuming no proxy is modifying it).
If the server accepts the incoming request, it will then return an HTTP response that looks something like this:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
At this point, the socket which used to be an HTTP socket is now a webSocket and both endpoints have agreed that they're going to use the webSocket data format from now on. This initial connection may be followed by some form of authentication or new or existing cookies can also be used in the authentication during the initial HTTP portion of the connection.
socket.io adds some enhancements on top of this by initially requesting a particular path of /socket.io and adding some parameters to the URL. This allows socket.io to negotiate whether it's going to use long polling or a webSocket so there are some exchanges between client/server with socket.io before the above webSocket is initialized.
So, back to your question. The socket.io server simply spies at all incoming web requests on the normal web port (and looks for both it's special path and for special headers to indicate a webSocket initiation rather than a classic HTTP request). So, it runs over the same port as the web server. This is done for a bunch of reasons, all of which provide convenience to the server and server infrastructure since they don't have to configure their network to accept anything other than the usual port 80 they were already accepting (or whatever port they were already using for web requests).
By default in socket.io, the domain and port will default to the same domain and port as the web page you are on. So, if you don't specify one or the other in your connect call, it will use the domain or port from the web page you are on. If you want to use both a different domain and port, then you must specify both of them.

Play Framework HTTPS Proxy

I have a Play! Application which needs to use HTTP and HTTPS. The application is running behind a proxy server (using Apache) that forwards web requests to the play application.
The proxy is using one port for HTTP requests, and another port that is intended for HTTPs requests. Note that the ports on the proxy are not the same ports as the ones used by the Play application (this is due to provider restrictions!).
The Play application is using the "standard" ports 9000 for HTTP and 9443 for HTTPs. The proxy receives HTTP requests on Port 8080 and forwards them to Play's port 9000. The proxy receives HTTPs requests on Port 8090 and forwards them to Play's port 9443.
My problem is that when I use the secure() method of making pages appear in Play, Play's logic causes the app to attempt to use 9443 as the port for HTTPs. This causes the request to be lost because the proxy is using a different port.
The same appears to happen when I want to switch from HTTPs to HTTP. I cannot seem to make the system go to the port used by the proxy.
Somehow I need to make the system go to the ports known to the proxy server, without screwing up my routes. Is there some way to do this?
Thanks in advance for any help/insights.
I have found my own "answer", though it is somewhat of a cludge.
It turns out that, based on what I can ascertain from the documentation, there really is no way to tell Play to switch between ports when a Play application is behind a proxy. This is because while Play does recognize the port that a request comes in on, it has no way of telling what proxy port it should use when going between secure and unsecure ports. It knows, for example, that an HTTP request comes through a proxy port 8080, and it knows that subsequent requests to its port 9000 will come from that proxy port. What it does not know to do is to switch to another proxy port when someone attempts to use https to access its port 9443. Consequently, if you have a page like
http://toproxy:8080/links that has one or more links that use the secure() method to activate https, then Play will resolve the link to be https://toproxy:8080 -- despite the fact that the proxy server may want to use port 8090 for HTTPS requests. Because proxy port 8080 is redirected to Play's port 9000, use of that port for HTTPS requests always fails. This is true in Play 2.0 as well as Play 1.X.
I believe that Play needs some standard configuration parameter that can tell it to map proxy ports to its HTTP and HTTPS ports. That way, when it is behind a proxy server a developer can use the secure() method and Play will be able to resolve the URL to the correct proxy port. This capability should be available in 1.X as well as Version 2.
Until someone actually implements this (I might if I ever get the time, but with all that I am committed to do people shouldn't hold their breath), my cludge is to simply use the rediirect() method to switch between HTTP and HTTPS proxy ports. The redirect() method apparently allows us to enter full URLs, so I simply call the full URL of the page that I switch requests on.
For example: in the aforementioned page http://toproxy:8080/links, I may have a link to a login page that I want to protect using HTTPS. To do this I create two actions: one for the redirect to the proxy HTTPS port (for this example, call it gotoLogin()) and another for actually rendering the login page (for this example, call it loginPage() and give it a route of /loginpage).
In gotoLogin() I redirect to loginPage in the following manner:
redirect("https://toproxy:8090/loginpage");
This makes Play come in on proxy port 8090, which is redirected to Play's port 9443.
When the user properly logs in, my authentication action simply uses another redirect() call:
redirect("http://toproxy:8080/destination_page");
This causes Play to go back to the proper proxy port for unsecured requests.
This is not the best solution for this problem. There is a possibility that the proxy server can be somehow configured to make the proper switch between HTTP and HTTPS ports, but investigating this may take some time for someone not an expert in proxy server configuration (which describes me!). Of course, the best solution would be to implement in Play the kind of proxy port handling that I have previously described.
But this solution works and can be adapted to many different situations. Unless someone comes up with another better solution, this solution is the one I am using.
Play should recognise the port the request is coming from, and use that port. It is possible your apache config is not set up correctly.
Have you put the following line in your apache config?
ProxyPreserveHost on
You may also need XForwardedSupport=127.0.0.1 depending on your server configuration.

Resources