I have a web client which has code such as:
for(i = 0; i < 10; i++) {
$.ajax({
url: "url",
type: "GET/POST",
data: {
...
}
}).done(function (data) {
...
});
}
So I'm making 10 requests to the same server url (java servlet with doGet, doPost methods)
In this case, will 10 different ports be used at the server side for 10 different 10 requests? Or will those requests share the same server port?
Assuming that these requests are made successively, this will result in 10 connections from the client to the server.
The client port will be different, likely incrementing, between port 1025 and port 65535. The server port will be the same; port 80 or 443, for example.
The client IP/client port/serverIP/server port make up the IP port pair that are used to key the connection, allowing the server to distinguish one from the other. Of course, over TCP, the sequence number is also involved in keying the communication, but the IP port pair is the primary distinguishing factor for the TCP/IP stack.
Related
Usage of the same TCP port for Rabbitmq 5672 and transfer requests to different namespaces/rabbitmq_service based on the host-based routing.
What works:
chart: nginx-git/ingress-nginx
version: 3.32.0
values:
- tcp:
5672: "cust1namespace/rabbitmq:5672"
Block reflected in nginx.conf:
server {
preread_by_lua_block {
ngx.var.proxy_upstream_name="tcp-cust1namespace-services-rabbitmq-5672";
}
listen :5672;
proxy_pass upstream_balancer;
}
Note: this will transfer all the requests coming to port 5672 to cust1namespace/rabbitmq:5672, irrespective of the client domain name and we want host-based routing based on domain name.
What is expected:
chart: nginx-git/ingress-nginx
version: 3.32.0
values:
- tcp:
cust1domainname:5672: "cust1namespace/rabbitmq:5672"
cust2domainname:5672: "cust2namespace/rabbitmq:5672"
Error:
Failed to render chart: exit status 1: Error: unable to build kubernetes objects from release manifest: error validating "": error validating data: [ValidationError(Service.spec.ports[3].port): invalid type for io.k8s.api.core.v1.ServicePort.port: got "string", expected "integer", ValidationError(Service.spec.ports[4].port): invalid type for io.k8s.api.core.v1.ServicePort.port: got "string", expected "integer"]
The final nginx.conf should look like:
server {
preread_by_lua_block {
ngx.var.proxy_upstream_name="tcp-cust1namespace-services-rabbitmq-5672";
}
listen cust1domainname:5672;
proxy_pass upstream_balancer;
}
server {
preread_by_lua_block {
ngx.var.proxy_upstream_name="tcp-cust2namespace-services-rabbitmq-5672";
}
listen cust2domainname:5672;
proxy_pass upstream_balancer;
}
A bit of theory
Approach you're trying to implement is not possible due to network protocols implementation and difference between them.
TCP protocol works on transport layer, it has source and destination IPs and ports, it does not have any hosts information within. In turn HTTP protocol works on application layer which seats on top of the TCP and it does have information about host where this request is intended to be sent.
Please get familiar with OSI model and protocols which works on these levels. This will help to avoid any confusion why this works this way and no other.
Also there's a good answer on quora about difference between HTTP and TCP protocols.
Answer
At this point you have two options:
Use ingress to work on application layer and let it direct traffic to services based on hosts which are presented in request body. All traffic should go through ingress endpoint (usually it's loadbalancer which is exposed outside of the cluster).
Please find examples with
two paths and services behind them
two different hosts and services behind them
Use ingress to work on transport layer and expose separate TCP ports for each service/customer. In this case traffic will be passed through ingress directly to services.
Based on your example it will look like:
chart: nginx-git/ingress-nginx
version: 3.32.0
values:
- tcp:
5672: "cust1namespace/rabbitmq:5672" # port 5672 for customer 1
5673: "cust2namespace/rabbitmq:5672" # port 5673 for customer 2
...
Hi I am setting up a server with multiple docker containers that are all running an application (Iperf3) that can only host one client at a time for a bandwidth test.
Using Nginx I would like to provide a dedicated link for a few seconds until a test is performed in point to point manner.
Right now my code (as shown below) is very simple, I am listening for tcp and udp on port 5201 and proxying the connections to 2 servers.
My first approach was to limit the number of connections per server to 1 so that only one client can connect at a time. However, each tests generates multiple connections so limiting the connections per server using the max_conns server parameter did not help me.
Since each test generates multiple connections and they need to be sent to the same server for the test to be successful I included hash $remote_addr consistent; so that there is client to server affinity.
The problem with my setup below is that Nginx will send multiple clients to the same servers and the request will be dropped by the server if it already performing a test with another client.
stream{
upstream iperf_backends {
hash $remote_addr consistent;
server 127.0.0.1:5202;
server 127.0.0.1:5203;
}
server{
listen 5201;
listen 5201 udp;
proxy_pass iperf_backends;
}
}
I'm trying to run two Minecraft servers on the same machine on two different ports. I want to reference them based on subdomains:
one.example.com -> <minecraft>:25500
two.example.com -> <minecraft>:25501
I have used nginx for things like this before, but it's not working with Minecraft. It's responding with http status 400. Here is a sample from my log:
192.168.0.1 - - [21/Apr/2013:17:25:40 -0700] "\x02<\x00\x0E\x00t\x00h\x00e\x00s\x00a\x00n\x00d\x00y\x00m\x00a\x00n\x001\x002\x003\x00\x1C\x00t\x00e\x00s\x00t\x00.\x00r\x00y\x00a\x00n\x00s\x00a\x00n\x00d\x00y\x00.\x00i\x00s\x00-\x00a\x00-\x00g\x00e\x00e\x00k\x00.\x00c\x00o\x00m\x00\x00c\xDD" 400 173 "-" "-"
Here is my nginx config:
upstream mine1 {
server 127.0.0.1:25500;
}
upstream mine2 {
server 127.0.0.1:25501;
}
server {
listen 25565;
server_name one.example.com;
access_log /var/log/nginx/one.access;
error_log /var/log/nginx/one.error;
location / {
proxy_pass http://mine1;
}
}
server {
listen 25565;
server_name two.example.com;
access_log /var/log/nginx/two.access;
error_log /var/log/nginx/two.error;
location / {
proxy_pass http://mine2;
}
}
If I'm reading this correctly, nginx is responding with 400. My guess is the Minecraft client is not sending valid HTTP headers and Nginx is tossing out the request. But I'm totally at a loss. Any help would be appreciated.
try this in your DNS records
A RECORD
Name one.example.com
Value <server_ip>
TTL 86400
Name two.example.com
Value <server_ip>
TTL 86400
SRV RECORD
Name _minecraft._tcp.one.example.com
Port 25500
Value one.example.com
Name _minecraft._tcp.two.example.com
Port 25501
Value two.example.com
As Dag Nabbit stated, a Minecraft server does not talk http. You would typically do this via NAT. A proxy server needs to know the protocol, because as the name suggests, it acts on behalf of the the client. Nginx knows various protocols, not just http, but Minecraft is not one of them. You can however write a proxy module for this protocol and use the existing nginx infrastructure. Since I'm not familiar with the protocol, I can't comment on the fact that this would have any advantages over NAT.
One thing to note for future readers, while yes nginx does pass connections off as a "proxy" to any server:port listing that is defined though the upstream definition in a socks proxy style of connection. This does not work when nginx itself is listening for HTTP communications. This is simply because nginx is is designed by default as a dead simple static http server.
Any sort of reverse proxing of TCP/UDP connections is more scalable at a lower OSI level (ie layer 3 or layer 2 instead of layer 6/7 as nginx is operating at). This is where Source and Destination NATs come into play which is better handled by a firewall or routing policy directive of your edge device.
DNS-RR is not the best solution as this, while yes lower level OSI layering, is only viable if the end applications (layer 7 OSI) understand the method. Minecraft (or just about any game server) at last check did not have this built into the game's networking code.
Now I did look into this and there is a few solutions for minecraft itself that one should look further into:
Transporter plugin
BungeeCord
Be sure to read all the documentation as these are very complex to configure and install. Hench the recommendation to just use NAT-ed network topology instead.
I tried to setup my multiple minecraft instances with SRV but that also doesn't work
nslookup of my srv records show:
C:\Users\Administrator>nslookup -type=SRV _minecraft._tcp.xxx.net
Server: mijnmodem.kpn
Address: 192.168.1.1
Non-authoritative answer:
_minecraft._tcp.xxx.net SRV service location:
priority = 5
weight = 5
port = 25565
svr hostname = camelot.xxx.net
_minecraft._tcp.xxx.net SRV service location:
priority = 5
weight = 5
port = 25566
svr hostname = cityworld.xxx.net
On my router(ZTE H369) port 25565 and 25566 are straight forwarded (TCP and UDP) to the IP wher the instances run. Accessing the urls (in Minecraft) gives io.netty.channel.Abstart$AnnotatedConnectException
Any suggestions how to investigate further?
Can someone explain the difference between the HTTP request and it handling and socket requests on 80 port. As I understood, HTTP server listen the 80 port and when someone sends an HTTP request on this port - server handle it. So when we place socket listener on port 80, and then write HTML formatted message to it - does it means that we send usual HTTP request? But as fiddler said - it false. What's the difference on a packet level? Or another lower than presentation-level between HTTP request and HTTP-formed writing to socket? Thanks.
First of all, port 80 is the default port for HTTP, it is not required. You can have HTTP servers listening on other ports as well.
Regarding the difference between "regular" HTTP requests and the ones you make yourself over a socket - there is no difference. The "regular" HTTP requests you are referring to (made by a web browser for example) are also implemented over sockets, just like you would do it manually yourself. And the same goes for the server. The implementation of the HTTP server listens for incoming socket connections and parses the data that passes there just like you would.
As long as you send in your socket valid HTTP protocol (according to the RFC), there should be no difference in the packet level (if the lower network stack is identical).
Keep in mind that the socket layer is just the layer the HTTP data always passes over. It doesn't really matter who put the data there, it just comes out from the other side the same way it was put in.
Please note that you have some degree of freedom when implementing an HTTP yourself. There are many optional fields and the order of the headers doesn't matter. So it is possible that two different HTTP implementations will be different in the packet level, but will behave basically the same.
The best way to actually see what's going on in the packet level, is by using a network sniffer - like wireshark or packetyzer. A sniffer actually records the packets of the network and shows you their content. So if you record several HTTP implementations (from various browsers) and your own socket implementation, you can make the required changes to make them identical in the packet level.
I have nginx running on my server, listening port 80 and 433. I know nginx has a number ways of port forwarding that allows me to forward request like: http://myserver:80/subdir1 to some address like: http://myserver:8888.
My question is it possible to configure nginx so that i can forward NON-http request (just those plain TCP connection) to some other port? It's very easy to test if it's a http request because the first bytes will be either "GET" or "POST". Here's the example.
The client connected to nginx .
The client send:
a. HTTP get request: "GET / HTTP 1.1": some rule for HTTP
b. Any bytes that can't be recognized as HTTP header: forward it to some other port, say, 888, 999, etc.
Is it technically possible? Or would you suggest a way to do this?
It is possible since nginx 1.9.0:
http://nginx.org/en/docs/stream/ngx_stream_core_module.html
Something along these lines (this goes on top level of nginx.conf):
stream {
upstream backend {
server backend1.example.com:12345;
}
server {
listen 12345;
proxy_pass backend;
}
}
This is technically possible for sure.
You can modify open source tcp proxies like nginx module called nginx_tcp_proxy_module or HAproxy.
Or you can write a nginx module similar to above one to do this for you.
if nginx remote proxying with HTTP, your client could use the HTTP CONNECT command, then it connects with the remote port and forwards all data as "raw" (or at least I think so).