Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow list images from specified domains #314

Closed
thesohodigital opened this issue Oct 24, 2021 · 5 comments
Closed

Allow list images from specified domains #314

thesohodigital opened this issue Oct 24, 2021 · 5 comments
Assignees
Labels
question Further information is requested

Comments

@thesohodigital
Copy link

If self hosting, is there a way to allow only images from a list of domains I specify?

eg. if the &url value is not on the allow list, then a 404 is returned.

@andrieslouw
Copy link
Member

The easiest way is to specify your own resolver in the NGINX config:

resolver 8.8.8.8; # Use Google's open DNS server

and let that resolver only respond to specific domains. It is the way we use to filter ourselves.

We use Unbound as a local(host) resolver, which forwards the requests to OpenDNS, and adds some of our own blocklists for our public service. But it should be easy to let Unbound only respond to specific domains.

@andrieslouw andrieslouw added the question Further information is requested label Oct 24, 2021
@andrieslouw andrieslouw self-assigned this Oct 24, 2021
@kleisauke
Copy link
Member

If there's only one domain you want to allow, you can also use proxy_pass in combination with the weserv filter directive. For example, to process only images from Imgur:

location /imgur {
    weserv filter;

    proxy_pass https://i.imgur.com:443/;
    proxy_redirect off;

    # Enable SNI on the upstream connection
    proxy_ssl_server_name on;

    # Use a custom user agent
    proxy_set_header User-Agent "Mozilla/5.0 (compatible; ImageFetcher/9.0; +http://images.weserv.nl/)";

    # Set upstream host
    proxy_ssl_name "i.imgur.com";
    proxy_set_header Host "i.imgur.com";

    # Enable the upstream persistent connection
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}
$ curl -s -o /dev/null -w "%{http_code}" http://localhost/imgur/FY1AbSo.gif?w=512
200

@kleisauke
Copy link
Member

I hope this information helped. Please feel free to re-open if questions remain.

@kleisauke
Copy link
Member

Another option is to use the ngx_http_secure_link_module module to check the authenticity of requested links and protect resources from unauthorized access. This module is included by default in the Dockerfile (see commit ce4ea86).

For example:

FROM ghcr.io/weserv/images:5.x

ARG SECRET

RUN cp ngx_conf/imagesweserv-secure-link.conf /etc/nginx/imagesweserv.conf \
    && sed -i "s/<SECRET>/$SECRET/g" /etc/nginx/imagesweserv.conf
$ docker build --build-arg SECRET=mysecret -t weserv/images .
$ docker run -d -p 8080:80 --shm-size=1gb --name=weserv weserv/images
$ echo -n 'url=https://wsrv.nl/lichtenstein.jpg&w=100 mysecret' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =
hqx4I-j6fhgY6LVhGTbHdw
$ curl -s -o /dev/null -w "%{http_code}" "localhost:8080/s/hqx4I-j6fhgY6LVhGTbHdw/?url=https://wsrv.nl/lichtenstein.jpg&w=100"
200
$ curl -s -o /dev/null -w "%{http_code}" "localhost:8080/s/hqx4I-j6fhgY6LVhGTbHdw/?url=https://wsrv.nl/lichtenstein.jpg&w=1000"
403

(ensure that you change mysecret to something else)

@adamJLev
Copy link

adamJLev commented Oct 9, 2024

I've achieved this with some nginx.conf tweaks

# Extract domain out of ?url= param
map $arg_url $url_domain {
    default "";
    ~^(https?://|https?%3A%2F%2F)?([^/%]+) $2;
}

# Validate that image url to transform in is from one of our whitelisted domains
map $url_domain $is_domain_whitelisted {
    hostnames;
    default 0;

    "" 1; # allow empty `url` param
    yourdomain.com 1;
}

and inside the location / {} directive:

        if ($is_domain_whitelisted = 0) {
            # Prevent caching of 400 responses
            add_header Cache-Control "no-cache, no-store, must-revalidate" always;
            return 400 "Invalid url domain - not in allowlist";
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Development

No branches or pull requests

4 participants