Hello.
How I can prevent hotlinking of video and images at server level for all websites ?
I don’t think you can do it at server level, I mean, globally for all domains changing just the main conf but you can do it modifying the template used by your sites or if you use Apache with an .htaccess file.
i tried but with no luck using custom templates:
NGINX:
server {
listen %ip%:%proxy_port%;
server_name %domain_idn% %alias_idn%;
error_log /var/log/%web_system%/domains/%domain%.error.log error;
include %home%/%user%/conf/web/%domain%/nginx.forcessl.conf*;
location ~ /\.(?!well-known\/|file) {
deny all;
return 404;
}
location / {
proxy_pass http://%ip%:%web_port%;
location ~* ^.+\.(%proxy_extensions%)$ {
try_files $uri @fallback;
root %docroot%;
access_log /var/log/%web_system%/domains/%domain%.log combined;
access_log /var/log/%web_system%/domains/%domain%.bytes bytes;
expires max;
}
}
location ~* \.(gif|jpg|jpeg|png|mp4|mkv|webm)$ {
valid_referers none blocked mydomain.com;
if ($invalid_referer) {
return 403;
}
root %docroot%;
access_log /var/log/%web_system%/domains/%domain%.log combined;
access_log /var/log/%web_system%/domains/%domain%.bytes bytes;
expires max;
}
location @fallback {
proxy_pass http://%ip%:%web_port%;
}
location /error/ {
alias %home%/%user%/web/%domain%/document_errors/;
}
include %home%/%user%/conf/web/%domain%/nginx.conf_*;
}
and in wp-content/upload htaccess:
# Begin Really Simple Security
<Files *.php>
Require all denied
</Files>
# End Really Simple Security
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^https://(www\.)?mydomain\.com/ [NC]
RewriteRule \.(gif|jpg|jpeg|png|mp4|mkv|webm)$ - [F,NC]
</IfModule>
<FilesMatch "\.(gif|jpg|jpeg|png|mp4|mkv|webm)$">
Require all denied
</FilesMatch>
Edit again the template, both, tpl and stpl, and remove the block you added.
This one:
location ~* \.(gif|jpg|jpeg|png|mp4|mkv|webm)$ {
valid_referers none blocked mydomain.com;
if ($invalid_referer) {
return 403;
}
root %docroot%;
access_log /var/log/%web_system%/domains/%domain%.log combined;
access_log /var/log/%web_system%/domains/%domain%.bytes bytes;
expires max;
}
And modify the block location ~* ^.+\.(%proxy_extensions%)$ {
like this:
location ~* ^.+\.(%proxy_extensions%)$ {
valid_referers none blocked %domain% *.%domain%;
if ($invalid_referer) {
return 403;
}
try_files $uri @fallback;
root %docroot%;
access_log /var/log/%web_system%/domains/%domain%.log combined;
access_log /var/log/%web_system%/domains/%domain%.bytes bytes;
expires max;
}
Once the template has been modified, rebuild your site (replace USER
and DOMAIN
with the actual data):
v-rebuild-web-domain USER DOMAIN yes
Thank you.
but I see only the page
Success!
Your new web server is ready to use.
custom .tpl
server {
listen %ip%:%proxy_port%;
server_name %domain_idn% %alias_idn%;
error_log /var/log/%web_system%/domains/%domain%.error.log error;
include %home%/%user%/conf/web/%domain%/nginx.forcessl.conf*;
location ~ /\.(?!well-known\/|file) {
deny all;
return 404;
}
location / {
proxy_pass https://%ip%:%web_ssl_port%;
}
location ~* ^.+\.(%proxy_extensions%)$ {
valid_referers none blocked %domain% *.%domain%;
if ($invalid_referer) {
return 403;
}
try_files $uri @fallback;
root %docroot%;
access_log /var/log/%web_system%/domains/%domain%.log combined;
access_log /var/log/%web_system%/domains/%domain%.bytes bytes;
expires max;
}
location @fallback {
proxy_pass http://%ip%:%web_port%;
}
location /error/ {
alias %home%/%user%/web/%domain%/document_errors/;
}
include %home%/%user%/conf/web/%domain%/nginx.conf_*;
}
STPL:
server {
listen %ip%:%proxy_ssl_port% ssl;
server_name %domain_idn% %alias_idn%;
error_log /var/log/%web_system%/domains/%domain%.error.log error;
ssl_certificate %ssl_pem%;
ssl_certificate_key %ssl_key%;
ssl_stapling on;
ssl_stapling_verify on;
# TLS 1.3 0-RTT anti-replay
if ($anti_replay = 307) { return 307 https://$host$request_uri; }
if ($anti_replay = 425) { return 425; }
include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*;
location ~ /\.(?!well-known\/|file) {
deny all;
return 404;
}
location / {
proxy_pass https://%ip%:%web_ssl_port%;
location / {
proxy_pass https://%ip%:%web_ssl_port%;
}
location ~* ^.+\.(%proxy_extensions%)$ {
valid_referers none blocked %domain% *.%domain%;
if ($invalid_referer) {
return 403;
}
try_files $uri @fallback;
root %docroot%;
access_log /var/log/%web_system%/domains/%domain%.log combined;
access_log /var/log/%web_system%/domains/%domain%.bytes bytes;
expires max;
}
location @fallback {
proxy_pass https://%ip%:%web_ssl_port%;
}
location /error/ {
alias %home%/%user%/web/%domain%/document_errors/;
}
proxy_hide_header Upgrade;
include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*;
}
But did you modify the template used by your site?
I mean, if you created a template named custom, is your site using that custom template?
Hi. yes if I select custom , hestia show me an empty website with:
Success!
Your new web server is ready to use.
If i return to the default templat on hestia i see normally the website
Ok, do this. Copy the actual nginx conf, change the template to custom and compare both conf files.
Note: replace YourUser
and YourDomain
by the actual data:
cp /home/YourUser/conf/web/YourDomain/nginx.conf /tmp/nginx-default.conf
Now change the template to custom and once done, show me the output of this command:
diff -u /tmp/nginx-default.conf /home/YourUser/conf/web/YourDomain/nginx.conf
Hi really thank you for the help, this is the output:
--- /tmp/nginx-default.conf 2024-05-31 10:23:36.768774660 +0000
+++ /home/josef/conf/web/mydomain.digital/nginx.conf 2024-05-31 10:24:35.509242989 +0000
@@ -1,42 +1,42 @@
-#=========================================================================#
-# Default Web Domain Template #
-# DO NOT MODIFY THIS FILE! CHANGES WILL BE LOST WHEN REBUILDING DOMAINS #
-# https://hestiacp.com/docs/server-administration/web-templates.html #
-#=========================================================================#
-
server {
- listen 192.168.1.120:80;
- server_name mydomain.digital www.mydomain.digital;
- error_log /var/log/apache2/domains/mydomain.digital.error.log error;
+ listen 192.168.1.120:80;
+ server_name mydomain.digital www.mydomain.digital;
+ error_log /var/log/apache2/domains/mydomain.digital.error.log error;
+
+ include /home/josef/conf/web/mydomain.digital/nginx.forcessl.conf*;
- include /home/josef/conf/web/mydomain.digital/nginx.forcessl.conf*;
+ location ~ /\.(?!well-known\/|file) {
+ deny all;
+ return 404;
+ }
- location ~ /\.(?!well-known\/|file) {
- deny all;
- return 404;
- }
+ location / {
+ proxy_pass https://192.168.1.120:8443;
+ }
- location / {
- proxy_pass http://192.168.1.120:8080;
+ location ~* ^.+\.(jpg|jpeg|webp|gif|png|ico|svg|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|odt|ods|odp|odf|tar|wav|bmp|rtf|js|mp3|avi|mpeg|flv|html|htm|woff|woff2|ttf)$ {
+ valid_referers none blocked mydomain.digital *.mydomain.digital;
+ if ($invalid_referer) {
+ return 403;
+ }
- location ~* ^.+\.(jpg|jpeg|webp|gif|png|ico|svg|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|odt|ods|odp|odf|tar|wav|bmp|rtf|js|mp3|avi|mpeg|flv|html|htm|woff|woff2|ttf)$ {
- try_files $uri @fallback;
+ try_files $uri @fallback;
- root /home/josef/web/mydomain.digital/public_html;
- access_log /var/log/apache2/domains/mydomain.digital.log combined;
- access_log /var/log/apache2/domains/mydomain.digital.bytes bytes;
+ root /home/josef/web/mydomain.digital/public_html;
+ access_log /var/log/apache2/domains/mydomain.digital.log combined;
+ access_log /var/log/apache2/domains/mydomain.digital.bytes bytes;
- expires max;
- }
- }
+ expires max;
+ }
- location @fallback {
- proxy_pass http://192.168.1.120:8080;
- }
+ location @fallback {
+ proxy_pass http://192.168.1.120:8080;
+ }
- location /error/ {
- alias /home/josef/web/mydomain.digital/document_errors/;
- }
+ location /error/ {
+ alias /home/josef/web/mydomain.digital/document_errors/;
+ }
- include /home/josef/conf/web/mydomain.digital/nginx.conf_*;
+ include /home/josef/conf/web/mydomain.digital/nginx.conf_*;
}
+
But you are mixing templates tpl ↔ stpl
Create again the custom template.
cd /usr/local/hestia/data/templates/web/nginx/
cp default.tpl custom.tpl
cp default.stpl custom.stpl
Now edit custom.tpl
and custom.stpl
modify them to include the hotlinking protection and rebuild again your site.
Thankyou.
website rebuild ok, but the protection doesn’t work, I can include an url in another website and works and also direct access to the file it’s not denied…
Thankyou.
website rebuild ok, but the protection doesn’t work, I can include an url in another website and works and also direct access to the file it’s not denied…
I’m sorry , after cleaning the nginx cache I have verified that direct access it’s not allowed therefore “it works”, but if I first visit the website normally that will run some videos, after if I paste the direct url the content is shown, if instead i use a link of a video on the website that was not loaded previously in a normal page, the access is correctly denied!
so… how to deny direct url access also when the url was previously loaded from a legitimate web page?
If you want to deny that kind of access to your files then you must remove the none
argument from valid_referers
Before:
valid_referers none blocked %domain% *.%domain%;
After:
valid_referers blocked %domain% *.%domain%;
And rebuild your site to apply the changes.
done but doesn’t work I can load the files with direct url (cleaned nginx cache, brwoser cache and tested with incognito browser session)
Please, share a link so I can test it.
Also, remember to restart nginx
yes already done
So, i have disabled cloudfalre cache with a custom rules…now are blocked (with ```
valid_referers none blocked %domain% *.%domain%;
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^https://(www\.)?maindomain\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^https://(sub\.)?otherdomain\.com/ [NC]
RewriteRule \.(gif|jpg|jpeg|png|mp4|mkv|webm)$ - [F,NC]
also if I use
valid_referers blocked %domain% *.%domain%;
Editors like elementor or divi doesn’t run correctly the editing page and even i set a domain that can embed the content remotely in another website, it is always blocked…
what i mean is that RewriteCond %{HTTP_REFERER} !^https://(sub.)?otherdomain.com/ [NC] doesn’t work for the allowed remote site to include content.