How does two port numbers works at the same time? - http

Now i am getting super confused with how ports actually work ,
This is my understanding of ports. I know that port 80 is for HTTP protocol and port 443 is for HTTPS protocol, so whenever I access http://website.com [(name or ip)], it is converted to http://website.com:80 [(name or ip)], and when I access https://website.com [(name or ip)], it gets converted to https://website.com:443 [(name or ip)].
So, if i am accessing a website on another port, i.e, i have my local setup of either springboot or angular app, and they are HTTP endpoints,
and I access http://localhost:someportNumber (example: http://localhost:5000), how does that get translated to port, as I have explicitly specified port 5000, but HTTP works on port 80.
Can you please help me with my understanding of how ports works.
Till now I was clear on how ports work, but now when I think of it like this today, it challenges my understanding of ports.
I came across this conflict of understanding when I was learning about the services on Google Kubernetes Engine. In there I created a service of type nodeport, which had configs like
port: 443
targetPort: 443
nodePort: 31000
and when I accessed external ip address of one of the nodes https://[external-ip]:31000, it worked.
So I began to challenge my understanding and I can't wrap this around my head that how is it working.
PS:- It is not about the concept of NodePort/ClusterIP/LoadBalancer. But in general about how these ports work with protocol port http or https, with a port of application.

You can specify any port (such as 5000 in your example). The URI simply begins with http to indicate what protocol is used - it does not mandate the use of port 80. The address is then used to contact the host on the specified port (which will be port 80 unless a different port was specified). Upon successful connection, the client then expects the server to speak HTTP.
On the server side, there is just a program that is listening on a port, waiting for incoming connections.

In the old days, one wouldn't call a person at a company directly. Instead one would call the main company switchboard and ask for the person at some extension.
Operator: How can I help you?
You: Extension 123
Operator: Connecting you now
Think of a "port" like an extension at a company. The hostname/IP address is the phone number of the company, the port is the extension at that company.
Going back to the analogy, once you are connected to the phone extension, you have a conversation. Both parties have an expectation of the conversation to be had. For example, if I call the extension corresponding to sales, I can place an order while if I call the extension corresponding to recruitment, I can submit my resume. This relationship between the purpose of the call and the extension is by convention and is not implicit in the extension itself.
When you form a connection over the internet to some machine at port 80, the assumption is that we will be exchanging HTTP traffic. However if I form a connection to some machine at port 5000, then there is nothing to prevent THAT connection from also sending and receiving HTTP traffic. For example, if sales at my company can be contacted on extension 80 and you can place an order there may also be an additional extension (5000) which you can call to place other types of orders that aren't available at the 80 extension.
See also:
http://www.steves-internet-guide.com/tcpip-ports-sockets/

Related

If a website built without port 80, can other client access this website as usual?

I know port 80 is one of well-know-port, but I am confused that if I build the website server process on other port except of 80, would it works when other client try to access this website server?
Port 80 is the default port for http. So connecting to http://domain would in essence send you to http://domain:80 (by default).
Port 443 is the default for https and would work the same way as stated for http above.
Any other port would require the you to do url:port to connect to. There are definitely ways to get around this (like forwarding) but I don't see the need for it and I think it causes more issues than anything.
You would also need to make sure that the new port is open, forwarded and can receive connections.
(Source for the first 2 paragraphs https://developer.mozilla.org/en-US/docs/Glossary/Port)

Map DNS entry to specific port

Let's say I have this DNS entry: mysite.sample. I am developing, and have a copy of my website running locally in http://localhost:8080. I want this website to be reachable using the (fake) DNS: http://mysite.sample, without being forced to remember in what port this site is running. I can setup /etc/hosts and nginx to do proxing for that, but ... Is there an easier way?
Can I somehow setup a simple DNS entry using /etc/hosts and/or dnsmasq where also a non-standard port (something different than :80/:443) is specified? Without the need to provide extra configuration for nginx?
Or phrased in a simpler way: Is it possible to provide port mappings for dns entries in /etc/hosts or dnsmasq?
DNS has nothing to do with the TCP port. DNS is there to resolv names (e.g. mysite.sample) into IP addresses - kind of like a phone book.
So it's a clear "NO". However, there's another solution and I try to explain it.
When you enter http://mysite.sample:8080 in your browser URL bar, your client (e.g. browser) will first try to resolve mysite.sample (via OS calls) to an IP address. This is where DNS kicks in, as DNS is your name resolver. If that happened, the job of DNS is finished and the browser continues.
This is where the "magic" in HTTP happens. The browser is connecting to the resolved IP address and the desired port (by default 80 for http and 443 for https), is waiting for the connection to be accepted and is then sending the following headers:
GET <resource> HTTP/1.1
Host: mysite.sample:8080
Now the server reads those headers and acts accordingly. Most modern web servers have something called "virtual hosts" (i.e. Apache) or "sites" (i.e. nginx). You can configure multiple vhosts/sites - one for each domain. The web server will then provide the site matching the requested host (which is retreived by the browser from the URL bar and passed to the server via Host HTTP header). This is pure HTTP and has nothing to do with TCP.
If you can't change the port of your origin service (in your case 8080), you might want to setup a new web server in front of your service. This is also called reverse proxy. I recommend reading the NGINX Reverse Proxy docs, but you can also use Apache or any other modern web server.
For nginx, just setup a new site and redirect it to your service:
location mysite.example {
proxy_pass http://127.0.0.1:8080;
}
There is a mechanism in DNS for discovering the ports that a service uses, it is called the Service Record (SRV) which has the form
_service._proto.name. TTL class SRV priority weight port target.
However, to make use of this record you would need to have an application that referenced that record prior to making the call. As Dominique has said, this is not the way HTTP works.
I have written a previous answer that explains some of the background to this, and why HTTP isn't in the standard. (the article discusses WS, but the underlying discussion suggested adding this to the HTTP protocol directly)
Edited to add -
There was actually a draft IETF document exploring an official way to do this, but it never made it past draft stage.
This document specifies a new URI scheme called http+srv which uses a DNS SRV lookup to locate a HTTP server.
There is an specific SO answer here which points to an interesting post here

Avoiding framed forwarding for web app on port 8080 with DNS

I have a play application running on port 8080. I currently forward to this by using
http://ip_address:8080
as my 'URL to forward to' in my forwarding service control panel.
The problem with this is: frame forwarding is used and I think this may be stopping Google Analytic for working.
I have control over DNS
A, CNAME, AAAA, TXT and NS records
&
DNS Service records
For other websites in the past running on port 80 I have simply created an A record with the destination as the server IP address, however because I am using port 8080 in this case, this does not work.
What is the best way to go about getting away from framed forwarding?
You can't put port numbers into the DNS resource record (there's a notable exception, namely SRV records, but as client support for those is rather spotty, those won't be much help). A nameserver commonly resolves hostnames to ip addresses - no directory/file names, no port numbers.
You can use a permanent redirect, which is a webserver facility, used to tell web clients to contact a different webhost. In order to use that, you need a webserver which responds to requests on port 80, and knows that requests concerning your zone must be redirected to your actual webserver. Very similar to the iframe solution you've been already using, but a permanent redirect instead of iframe.
If your reason for dropping the current iframe approach isn't that you, for example, want to get rid of decorative framing, ads, "branding" etc (with those, a permanent redirect would help), but want to cease using an intermediate webserver, adding another level of indirection to the queries, there's little you can do:
your firewall may be able to do port redirection, meaning that the incoming requests will hit your gateway/firewall on port 80, where the request is sent on to port 8080 where the webserver is actually listening. Another possibility could be, but requiring again another webserver, listening to port 80, to set up proxying: incoming requests to that webserver will be served from a cache on that server, which is populated and occasionally refreshed as result of that webserver querying your webserver on port 8080.
Even though with the latter suggestion an additional webserver will be existing, there'd be no visible indirection, as it would be transparent to clients: The web files are produced by the first server which is hit, even if they are once every so often taken from another server.

Is it possible to delegate an HTTP request transparently?

Suppose computer A sends an HTTP request to a server B, and B wants C to answer it. Is it possible for C to send a response back to A without B intervention and without specific actions from A (as with a 3xx redirection)? Suppose C may not have a public IP address.
That's what a reverse proxy would do. Depending what platform you are on, there are a lot of options.
One way that works on many platforms is e.g. node-http-proxy that you could start on server B. In the most simple case, this one-liner would do:
require('http-proxy').createServer(81, 'serverb').listen(80);
It listens on port 80 and redirects to port 81 on serverb.
See https://github.com/nodejitsu/node-http-proxy for more options.
Of course, there are lots of well-established proxies with a lot more bells and whistles (although node-http-proxy can do https tunneling etc. as well), but configuring those can be more challenging that running this one-liner. It all depends on your use case.
Edit: Reading your comment, this can be done using direct routing. Your question is about HTTP (layer 7), and as direct routing works on a lower layer, higher-level protocols like HTTP work as well. Quote from http://horms.net/projects/has/html/node9.html:
Direct Routing: Packets from clients are forwarded directly to the
back-end server. The IP packet is not modified, so the back-end
servers must be configured to accept traffic for the virtual server's
IP address. This can be done using a dummy interface, or packet
filtering to redirect traffic addressed to the virtual server's IP
address to a local port. The back-end server may send replies directly
back to the client. That is if a host based layer 4 switch is used, it
may not be in the return path.

split HTTP and TCP-only (non-HTTP) traffic

I have web application that runs on Tomcat (and gets HTTP requests) and some other backend standalone application that gets only TCP. For some reasons, I can use outside only port 8080. So, I need to get all TCP requests (from outside) to port 8080 and forward HTTP ones to web application on Tomcat and all TCP pure requests (that are not HTTP) - to standalone application. Internal forwarding could be done to any port, e.g. 8181 on Tomcat and 8282 on standalone application. Is it possible to setup such configuration? How it could be done?
Thanks in advance.
TCP and HTTP are protocols in different networking stack layer. If you want to use some application to filter HTTP requests, your application should deal with Application-Layer information, not Network-Layer(like TCP/UDP).
I don't see how this can be possible generally. You could look packet-by-packet, but the middle of an http body can be arbitary so you can't just look at the data of each packet
If any particular client will send you either http or general TCP but not both, can you do this by source-IP address? Do you know the addresses of either the servers that will send you http requests or the ones that will send you TCP requests?
If you don't know the source IPs, you could heuristically look at the first packet from some previously unknown IP and see if it looks like http, then tag that address as containing http traffic.
What is the content/format ot the TCP communication? Is there any pattern you can detect in that?
Y
Perhaps you could do something like this using iptables + L7 filter. Of course this will only work if you run Linux on your box. Also I don't know how recently l7 filter project has been updated.
Java servlet technology is not limited to Http. The servlet interface lets you read in the incoming input stream via ServletRequest.getInputStream(). So you can create an implementation of Servlet interface and map it in web.xml and you are all set to receive any TCP traffic.
Once you have the read the input stream to sniff the content you will want to forward HTTP requests to an HttpServlet. To do this you will need to make sure that the input stream you pass on is positioned at the very beginning of the input.
EDIT: On reading your question once again, I noticed that you don't plan to expose the Tomcat directly on external port as I originally thought. If you are willing to make the tomcat listen on the external port, you can try the approach described above

Resources