I want to use nginx as a caching proxy in front of an OCSP responder. 'An OCSP request using the POST method is constructed as follows: The Content-Type header has the value "application/ocsp-request" while the body of the message is the binary value of the DER encoding of the OCSPRequest.' (from RFC2560)
Hence, I configured nginx as follows:
proxy_cache_path /tmp/nginx/cache levels=1:2 keys_zone=my-cache:8m max_size=1000m inactive=600m;
server {
# Make site accessible from http://localhost/
server_name localhost;
location / {
proxy_pass http://213.154.225.237:80; #ocsp.cacert.org
proxy_cache my-cache;
proxy_cache_methods POST;
proxy_cache_valid 200 302 60m;
proxy_cache_valid 404 1m;
proxy_cache_key "$uri$request_body";
expires off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
)
I can access the OCSP responder through nginx and responses are received as expected - no issue.
The problem is that nginx doesn't cache the responses. Nonces are not being sent as part of the request. Using Wireshark I verified that all my requests are identical (on the HTTP layer). How to configure nginx that it caches the responses?
Note, I use the following command for testing:
openssl ocsp -issuer cacert.crt -no_nonce -CAfile CAbundle.crt -url http://localhost/ -serial <SERIAL>
There is a lot more to caching OCSP responses than just caching the DER they are made of. Look into the lightweight OCSP profile and make sure that your responder does include the necessary headers into the response.
I would recommend that you use a specially build OCSP proxy cache, there are many out there. For example Axway's Validation Authority Repeater is a good choice.
In the meanwhile I got the answer at the mailinglist which solved my problem:
You configuration doesn't contain proxy_cache_valid (see
http://nginx.org/r/proxy_cache_valid), and in the same time via
proxy_ignore_headers it ignores all headers which may be used to
set response validity based on response headers. That is, no
responses will be cached with the configuration above.
You probably want to add something like
proxy_cache_valid 200 1d;
to your configuration.
My complete configuration example(works with openca-ocsp):
nginx.conf:
proxy_cache_path /var/cache/nginx/ocsp levels=1:2 min_free=1024M keys_zone=ocsp:10m;
conf.d/ocsp.conf
server {
listen 80;
proxy_cache ocsp;
proxy_cache_valid 200 404 2m;
proxy_cache_min_uses 1;
proxy_ignore_headers X-Accel-Expires Expires Cache-Control;
proxy_cache_methods POST;
proxy_cache_key "$request_uri|$request_body";
add_header X-GG-Cache-Status $upstream_cache_status;
location = /ocsp {
# Allow only POST
limit_except POST {
deny all;
}
proxy_pass http://ocspd:2560/;
}
}
Related
I have got a Ubuntu instance with NGINX installed and configured as a forward proxy on one host for my application on a different host.
My app is making GET requests to NGINX which is making another GET requests to external server (URL to this server is specified in the request) and returning the response to the application.
NGINX is supposed to cache the response from the external server.
I need to respect the Cache-Control header from the response (cache the response that long as this header says) BUT! When there is no Cache-Control header in the response, it must be cached for 12h, what to do to achieve it?
Thanks! :)
Here is my actual config:
proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=my_cache:100m max_size=2m inactive=12h use_temp_path=off;
location ~* {
resolver xx.xx.x.xxx;
proxy_cache my_cache;
add_header X-Cache-Status $upstream_cache_status;
if ($http_x_example_use_https = '1') {
proxy_pass https://$host;
}
if ($http_x_example_use_https = '0') {
proxy_pass http://$host;
}
proxy_redirect off;
proxy_connect_timeout 4;
proxy_send_timeout 4;
proxy_read_timeout 4;
send_timeout 4;
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
proxy_cache_lock on;
}
PS Any thoughts to improve this config or change something? :)
I think I have solved my problem using:
proxy_cache_valid 200 12h;
And when the Cache-Control header is present, it shouldn't be overwritten by this directive above.
NGINX documentation:
Parameters of caching can also be set directly in the response header. This has higher priority than setting of caching time using the directive.
If the header does not include the “X-Accel-Expires” field, parameters of caching may be set in the header fields “Expires” or “Cache-Control”.
Case:
I have REST API via HTTPS and I want to configure a basic caching proxy service on my host to cache API requests and get the same information faster, as usual.
I have the following configuration of Nginx:
proxy_cache_path /tmp/cache levels=1:2 keys_zone=my_cache:10m max_size=10g
inactive=60m use_temp_path=off;
http {
server {
location /my_api/ {
proxy_redirect off;
proxy_buffering on;
proxy_ignore_headers X-Accel-Expires;
proxy_ignore_headers Expires;
proxy_ignore_headers Cache-Control;
proxy_cache my_cache;
proxy_pass https://example.com/myapi/;
}
}
}
And now I'm comparing the response time from REST API and my local proxy service, and it is the same for the REST API call to the remote service and to my local proxy service with caching, so, it means that caching doesn't work.
Also, the cache directory is empty.
The example or request to the real API (this is not the real case):
curl "https://example.com/myapi/?key=1"
Example of request to proxy:
curl "http://127.0.0.1:8080/myapi/?key=1"
In REST API headers I can see
cache-control: max-age=0, no-cache, no-store, must-revalidate
can Nginx ignore it somehow?
What should I change in the proxy configuration to see the boost for REST API?
I wonder if the issue can be related to HTTPS traffic? Or maybe the response from REST API has some NoChaching headers or the size of the response is too small for caching?
Finally found the way to configure caching for my REST API, here is the final configuration:
http {
proxy_cache_path /tmp/cache levels=1:2 keys_zone=my_cache:10m;
server {
listen 8080;
server_name localhost;
location /myapi {
proxy_buffering on;
proxy_ignore_headers Expires Cache-Control X-Accel-Expires;
proxy_ignore_headers Set-Cookie;
proxy_cache my_cache;
proxy_cache_valid 24h;
proxy_pass https://example.com/myapi;
}
}
In addition, if you are caching a REST api (e.g. GET and POST), I also suggest to add
proxy_cache_methods GET POST;
I have to set custom headers for outgoing request using nginx proxy, so basically I started with trying add_header and proxy_set_header directive in the conf file(snippet has been added), but in the outgoing request these headers were not being added using either of them. Please suggest me an approach to solve this problem.
server {
listen 8095;
access_log logs/host.access.log;
location / {
proxy_pass https://www.dummy-site.com/applications/1232;
proxy_set_header Authorization "some_authorisation";
proxy_set_header referer "referer";
proxy_pass_request_headers on;
}
}
I'm having a hard time configuring nginx to act as a proxy of a public S3 endpoint. My use case necessitates altering the status code of the S3 response, while preserving the response payload.
The possible status codes returned by S3 include 200 and 403. For my use case, I need to map those status codes to 503.
I have tried the following which does not work:
location ~* ^/.* {
[...]
proxy_intercept_errors on;
error_page 200 =503 $upstream_http_location
}
Nginx outputs the following error:
nginx: [emerg] value "200" must be between 300 and 599 in /etc/nginx/nginx.conf:xx
Here's a more complete snippet:
server {
listen 80;
location ~* ^/.* {
proxy_http_version 1.1;
proxy_method GET;
proxy_pass http://my-s3-bucket-endpoint;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Connection "";
proxy_set_header Host my-s3-bucket-endpoint;
proxy_set_header Authorization '';
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header Set-Cookie;
proxy_ignore_headers "Set-Cookie";
proxy_cache S3_CACHE;
proxy_cache_valid 200 403 503 1h;
proxy_cache_bypass $http_cache_purge;
add_header X-Cached $upstream_cache_status;
proxy_intercept_errors on;
error_page 200 =503 $upstream_http_location;
}
}
Is it possible to achieve what I need with nginx?
I found a more or less suitable solution. It's a bit hackish but it works.
The key was to set the index document of my S3 bucket to a non-existing filename. This causes requests to / on the S3 bucket endpoint to result in 403.
Since the nginx proxy maps all incoming requests to / on the S3 bucket endpoint, the result is always 403 which the nginx proxy can intercept. From there, the error_page directive tells it to respond by requesting a specific document (in this case error.json) in the S3 bucket endpoint and use 503 as the response status code.
location ~* ^/. {
proxy_intercept_errors on;
error_page 403 =503 /error.json;
}
This solution involves two requests being sent to the S3 bucket endpoint (/, /error.json) but at least caching seems to be enabled for both requests using the configuration in the more complete snippet above.
I have problem with Nginx acting as proxy serwer:
request -> NGINX PROXY -> app server (only one)
Proxy server is listening on port 443 and an application server on 80. Headers returned by upstream server are being removed by proxy. I was forced to use:
add_header 'Content-Length' $upstream_http_content_length;
It works ok for Content-Length, however it doesn't work with Last-Modified header. Curl request from Nginx proxy using private IP to upstream returns all the headers. Why does the Nginx proxy cut this header out even if it's return is specified using add_header?
I have following nginx.conf sample:
location /some-web-app {
proxy_pass http://backend/some-web-app;
proxy_redirect off;
proxy_redirect http $scheme;
proxy_set_header Host $host;
add_header 'Last-Modified' $upstream_http_last_modified;
add_header 'Content-Length' $upstream_http_content_length;
sub_filter 'codebase="http' 'codebase="https';
sub_filter_types application/x-java-jnlp-file;
access_log /var/log/nginx/some-web-app_access.log combined_jsession_upstream;
error_log /var/log/nginx/some-web-app_err.log;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htpasswd;
}
To forward returned last-modified header put following directive in location block:
sub_filter_last_modified on
To forward any other header use add_header with $upstream_http_${header}. Here I'll forward Content-Length header:
add_header 'Content-Length' $upstream_http_content_length;