How to ignore Content Length in Nginx? - http

Faced with a problem: if GET request was supplied with non-zero Content-Length property and there is no body, nginx will not proxy this request. Example of how to reproduce it:
nginx version: nginx/1.10.3 (Ubuntu)
# conf.d/main.conf
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:5060;
}
}
When listen 5060 port via netcat: nc -l -p 5060
After, make CURL request:
curl -vvv -X GET http://example.com/ -H 'Content-Length: 1'
This request will be closed after default proxy_send_timeout 60s.
As i understand, Nginx see Content-Length and wait body before transmit request to proxy. How to resolve it, without changing the reqest header?
Please note: i tried to do it with Haproxy - it work despite non-zero Content-Length and zero body.

Related

Nginx sever block not function as expected

I'm using this config file with nginx:
server {
listen 80;
server_name harrybilney.co.uk;
location / {
proxy_pass http://localhost:8080;
}
}
server {
listen 80;
server_name kyra-mcd.co.uk;
location / {
proxy_pass http://localhost:8080;
}
}
Which is stored in /etc/nginx/sites-avaliable. The server block for the domain kyra-mcd.co.uk works perfectly as expected but the server block for harrybilney.co.uk does not and my browser cannot find the server for harrybilney.co.uk.
Both domains are hosted with GoDaddy and have the exact same DNS settings pointing towards my static IP (IPv4 and IPv6 with A and AAAA records).
Can anyone explain why I'm having this issue as I've tried changing the config but getting luck. I understand this is a very basic config file for nginx but for now I'm just trying to get both domains working on my 1 static IP before I add in anything complex.
Having both server blocks in a single file IS NO PROBLEM!
Here is a default.conf file:
server {
listen 80;
server_name harrybilney.co.uk;
location / {
return 200 "$host\n";
}
}
server {
listen 80;
server_name kyra-mcd.co.uk;
location / {
return 200 "Host should match kyra-mcd.co.uk = $host\n";
}
}
Test and reload your config by issuing sudo nginx -t && sudo nginx -s reload
The curl test:
$# curl -H "Host: kyra-mcd.co.uk" localhost
Host should match kyra-mcd.co.uk = kyra-mcd.co.uk
$# curl -H "Host: harrybilney.co.uk" localhost
harrybilney.co.uk
As you can see both servers are in a single file and the server_name taking care of finding the correct server-block based on the Host header.
Check your DNS one more time. Worh it:
kyra-mcd.co.uk. 600 IN A 90.255.228.109
harrybilney.co.uk. 3600 IN A 90.255.228.109
Looks good to me as well. So the traffic should hit the server.
So your configuration looks good for me. Make sure everything is loaded by issuing sudo nginx -T.
curl is working on my end. So looks like the problem is related to DNS on your end. Can you confirm curl is working from your end as well?

403 response when trying to redirect using nginx to API Gateway

I have the following API: https://kdhdh64g.execute-api.us-east-1.amazonaws.com/dev/user/${user-id} which proxies to a Lambda function.
When the user hits /user/1234 the function checks if 1234 exists and return the info for that user or a redirection to /users
What I want is to create is a redirection with nginx. For SEO, I want a simple 302: return 302 the-url. If someone goes to mySite.com it should redirect to https://kdhdh64g.execute-api.us-east-1.amazonaws.com/dev
No matter what I do, I always receive a 403 with the following:
x-amzn-errortype: MissingAuthenticationTokenException
x-amz-apigw-id: QrFd6GByoJHGf1g=
x-cache: Error from cloud-front
via: 1.1 dfg35721fhfsgdv36vs52fa785f5g.cloudfront.net (CloudFront)
I will appreciate help.
If you are using the reverse proxy set up in nginx, add the below line in the config file and restart or reload the nginx configuration.
proxy_set_header Host $proxy_host;
I run into the same issue trying to run a proxy on Nginx towards an API Gateway which triggers a Lambda function on AWS. When I read the error logs on Nginx, I noticed that it had to do with the SSL version which Nginx was using to connect to API Gateway, the error was the following:
*1 SSL_do_handshake() failed (SSL: error:1408F10B:SSL routines:ssl3_get_record:wrong version number) while SSL handshaking to upstream
I managed to fix it by adding this line:
proxy_ssl_protocols TLSv1.3;
I attach the complete Nginx configuration in case anyone wants to build a static IP proxy on Nginx that redirects traffic towards a Lambda function:
server {
listen 443 ssl;
server_name $yourservername;
location / {
proxy_pass https://$lambdafunctionaddress;
proxy_ssl_server_name on;
proxy_redirect off;
proxy_ssl_protocols TLSv1.3;
}
ssl_certificate /home/ubuntu/.ssl/ca-chain.crt;
ssl_certificate_key /home/ubuntu/.ssl/server.key;
}
Also it is important to consider that all required information must be included on the request:
curl -X POST https://$yourservername/env/functionname -H "Content-Type: application/json" -H "x-api-key: <yourapikey>" -d $payload

Is it possible to have a multi-line log in nginx?

I'm sending logs to an nginx server and want to dump these logs to a file. When sending one log at a time, I was able to do this using the NginxEchoModule to force nginx to read the body like so:
http {
log_format log_dump '$request_body';
server {
listen 80 default_server;
listen [::]:80 default_server;
access_log /logs/dump log_dump;
location /logs {
echo_read_request_body;
}
}
}
This works fine when I send one log at a time:
POST /logs HTTP/1.1
Host: www.example.com
123456 index.html was accessed by 127.0.0.1
POST /logs HTTP/1.1
Host: www.example.com
123457 favicon.ico was accessed by 127.0.0.1
However when I try to batch logs (to avoid both connection overhead and HTTP header overhead):
POST /logs HTTP/1.1
Host: www.example.com
123456 index.html was accessed by 127.0.0.1
123457 favicon.ico was accessed by 127.0.0.1
This is what shows up in my log file:
123456 index.html was accessed by 127.0.0.1\x0A123457 favicon.ico was accessed by 127.0.0.1
Now my assumption is that because one nginx log line is intended to be one line, it's encoding my new-line characters to ensure this. Is there a way to allow multi-line nginx logs?
Actually got the answer from one of the more experienced engineers at my work this time:
log_format log_dump escape=none '$request_body';
This requires nginx version 1.13.10, but prevents nginx from escaping new-lines in the logs:
$> curl http://localhost/logs -d "Words
dquote> More words"
$> cat /logs/dump
Words
More words
$>

Nginx Stripping POST body on proxy_pass

I have a server running behind a firewall, with a single external IP, which therefore has requests proxied by domain through via an Nginx box.
When I run cURL behind the firewall, everything goes to plan:
HTTP/1.1 200 OK
The cURL is:
curl -H "Content-Type: application/json" -X POST --data #test.json 111.111.111.111/endpoint/ -i
As soon as I run this in Postman/Hurl.it/whatever from outside the network, I get 400 errors. The code throws a 400 when it is missing the POST body (JSON). Echoing this out shows that no JSON is being received.
The relevant Nginx configuration is thus:
server {
listen 80;
server_name domain.co;
location / {
proxy_pass http://111.111.111.111/;
proxy_set_header Host $host;
}
}
The domain does sit behind CloudFlare, and I've switched it to DNS only and tried that - I'd be very surprised if that was the issue.
I've had a look at other solutions, and tried some stuff out but I'm not really sure what I'm doing wrong here, unless I fundamentally misunderstand how proxy_pass works?

Why nginx $request_uri contains only one parameter?

My nginx config:
server {
listen 80;
server_name test.app;
location / {
echo $request_uri;
}
}
Then i perform GET request via curl and i can see only first parameter. All others are lost:
# curl http://test.app?p1=v1&p2=v2
> /?p1=v1
As i understand, $request_uri should contains all GET arguments. Why they are lost?
Nginx is installed via apt-get.
You have to escape the & if you do a curl on the command line otherwise you will do curl http://test.app?p1=v1 and send it to the background.
curl http://test.app?p1=v1\&p2=v2 should do the trick.

Resources