Postfix – rewrite From address and add Reply-to header with primary address

So I had an objective to create a mailing server with one DKIM key which would serve as mailing server for contact forms … Idea is, that you don’t need multiple DKIM keys as mail is sent from single domain, but in the same time, it should add reply-to header with primary email address so that when reply to this mail, user will send to real mail address.

I had problem rewriting From header and add reply-to header with primary mail address at the same time. I then discovered that you can’t define From in header_checks multiple times. Only first one will be processed. At first, I had an idea that first rule would add reply-to header with primary mail, then second rule would rewrite primary address with new domain part.

My wish was also, that first (user) part of email address should be kept and rewrote with new domain. I used sender_canonical for rewriting domain, but still no luck. In mail headers there was still old From mail and DKIM was not signed as domain didn’t match. What did the trick was adding local_header_rewrite_clients. This allowed postfix to rewrite headers to authenticated users and those defined in mynetworks.

Here is the whole configuration:

main.cf:
### rewrite domain & add reply-to & rewrite message-id
local_header_rewrite_clients = permit_sasl_authenticated, permit_mynetworks
canonical_classes = envelope_sender, header_sender
canonical_maps = regexp:/etc/postfix/sender_canonical
header_checks = regexp:/etc/postfix/header_checks

header_checks:
/^From:\s*(.*<)?([^@]+)@([^>]+)>?/ PREPEND Reply-To: <${2}@${3}>
/^Message-Id:\s+<(.*?)@([^>]+)>/ REPLACE Message-Id: <${1}@newdomain.com>

sender_canonical:
/^<?([^@]+)@[^> ]+>?$/ ${1}@newdomain.com
DKIM SigningTable:
*@newdomain.com newdomain.com

Then define your hostname of mailing server in your application to use as mailing service. In my case, user has to authenticate. If you send mail from username@mydomain.com, reply-to header with the same address would be added, From would be replaced with username@newdomain.com and DKIM would be successfully signed with newdomain.com. If end user replyes to this mail, Return-to is defined and mail would be sent to primary address username@mydomain.com and not non-existing username@newdomain.com.

Directadmin – building PHP 8.3 returns error: iconv does not support errno

I tried to install additional PHP version 8.3 and get this error:

directadmin checking if iconv supports errno… configure: error: iconv does not support errno

System is using old iconv version and Directadmin is not using its own libiconv anymore. You can use iconv version from /usr/local instead. Go to /usr/local/directadmin/custombuild/configure/php/configure.php83 and add this line:

--with-iconv=/usr/lib \

Then install new PHP version and it should work:

[root@server custombuild]# ./build php_expert 8.3 php-fpm

Icinga2 reporting error – Invalid filter / can’t generate report

I installed reporting module on our Icinga2 monitoring system, so I would be able to generate some SLA report for one of our client which has a lot of servers. I installed the module and wanted to make the filter so that the report would be generated only for hosts with “example” string in hostname.

In Icinga2 documentation, this is done simply with match function, like this:

match("*example*",host.name)

This gave me error:

Invalid filter "match("*example*",host.name)", unexpected ( at pos 6 (Parser.php:561)

#0 /usr/share/icinga-php/ipl/vendor/ipl/web/src/Filter/Parser.php(285): ipl\Web\Filter\Parser->parseError()
#1 /usr/share/icinga-php/ipl/vendor/ipl/web/src/Filter/Parser.php(88): ipl\Web\Filter\Parser->readFilters()
#2 /usr/share/icinga-php/ipl/vendor/ipl/web/src/Filter/QueryString.php(44): ipl\Web\Filter\Parser->parse()
...

I also tried “host.name=*example*” with empty response.
To do this properly, you must create your filter like below and it should work:

host.name~*example*

Zimbra/Carbonio – ERROR: zclient.IO_ERROR (Read timed out) (cause: java.net.SocketTimeoutException Read timed out

I was moving emails from old Zimbra installation on new Carbonio and was getting this error when trying to import user from tgz archive:

root@mail:/opt/backup# /opt/zextras/bin/zmmailbox -z -m mymail@mydomain.com postRestURL '//?fmt=tgz&resolve=skip' /opt/backup/mymail@mydomain.com.tgz
ERROR: zclient.IO_ERROR (Read timed out) (cause: java.net.SocketTimeoutException Read timed out)

There was a timeout causing this. So after quick googling around I found this solution that works:

root@mail:/opt/backup# su - zextras
zextras@mail:~$ zmlocalconfig -e socket_so_timeout=3000000

Then your restore command should work without timeout. At the end, you can reset socket_so_timeout value:

root@mail:/opt/backup# su - zextras
zmlocalconfig -u socket_so_timeout


Directadmin – server-<YOUR IP>.da.direct was skipped due to unreachableDirectadmin

I just migrated Directadmin server to a new one. On the new one, there was some temporary hostname, that I guess Directadmin provides. It was http://server-<IP ADDRESS>.da.direct. I changed hostname of machine and did everything, but wasn’t able to generate Letsencrypt certificate for my directadmin server hostname. 

When try to generate certificate I was getting error below. I rewrite configs, run changehostname.sh, did all sort of things, but wasn’t able to get pass this error:

[root@da scripts]# ./letsencrypt.sh request `hostname` 4096
Setting up certificate for a hostname: my.dahostname.com
server-1-1-1-1da.direct was skipped due to unreachable http://server-1-1-1-1.da.direct/.well-known/acme-challenge/ file.
No domains pointing to this server to generate the certificate for.

After an hour, I found this answer from gentleman named “zEitEr”. I guess, when I setup new Directadmin server on temporary IP, acme account for letsencrypt was created with directadmins temporary hostname – server-<MY IP ADDRESS>.da.direct. What I did, was removed all letsencrypt accounts and regenerated them:

[root@da ~]# rm -rf /usr/local/directadmin/data/.lego/*
[root@da scripts]# ./letsencrypt.sh request `hostname` 4096
Setting up certificate for a hostname: my.dahostname.com
2024/02/16 13:31:42 No key found for account admin@my.dahostname.comGenerating a 4096 key.
2024/02/16 13:31:45 Saved key to /usr/local/directadmin/data/.lego/accounts/acme-v02.api.letsencrypt.org/admin@my.dahostname.com/keys/admin@my.dahostname.com.key
2024/02/16 13:31:45 [INFO] acme: Registering account for admin@my.dahostname.com
!!!! HEADS UP !!!!

Your account credentials have been saved in your Let's Encrypt
configuration directory at "/usr/local/directadmin/data/.lego/accounts".

You should make a secure backup of this folder now. This
configuration directory will also contain certificates and
private keys obtained from Let's Encrypt so making regular
backups of this folder is ideal.
2024/02/16 13:31:45 [INFO] [my.dahostname.com] acme: Obtaining SAN certificate
2024/02/16 13:31:46 [INFO] [my.dahostname.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/315898412537
...
Certificate for my.dahostname.com has been created successfully!
DirectAdmin certificate has been setup.
Setting up cert for Exim...
...

Hope that helps to save some nerves. Thanks to zEitEr

Nginx Proxy Manager – lock administration on IP or password

Nginx Proxy Manager is a great tool for managing proxy vhosts. Specially useful when dealing with Docker containers. By default, you can access administration from everywhere through default port 81. Here is how you can simply lock it with password or limit it so that is accessible from specified IPs.

First login into admin panel and create Access List which will contain access rules:

You can limit to be accessible from IPS:

or with password:

Then, create a new Proxy Host that will have backend set to nginx proxy manager administration. In my case, “proxy-manager” is the host of my nginx proxy manager container. Don’t forget to set Access List to the one that we created in the previous step.

Then change value  in your docker-compose file so that port 81 will be on localhost only:

version: '4.3'
services:
proxy-manager:
image: 'jc21/nginx-proxy-manager:latest'
container_name: proxy-manager
restart: always
ports:
- "80:80" # Public HTTP Port
- "443:443" # Public HTTPS Port
- "127.0.0.1:81:81" # Admin Web Port 

Administration is now reachable through subdomain https://admin.domain.com/ and only from IPs that we set in above step – or with password. It is advisable that you make some random URL like https://siudhfoisdiishjw0ion094ioejvn.domain.com when creating administration access.

Calculate average memory consumption of php-fpm processes

Here is one liner which gives you average memory consumption of php-fpm processes.

 ps --no-headers -o "rss,cmd" -C "php-fpm" |  awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'

If you have more pools, you can grep for specific pool and get average for that one:

 ps --no-headers -o "rss,cmd" -C "php-fpm" | grep <mypool2> |  awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'

SSH: Server refused public-key signature despite accepting key!

This will be quick one :). If you are trying to connect to a server via SSH with Putty in combination with Pageant, and you are expecting an error message in the title of this post, chances are, your version of Pageant is too old. Upgrade your Pageant to the latest version and you should be good to go.

Apache “require ip” is not working when behind proxy. How to limit website access to IP when Apache is behind proxy.

I had a case where Apache did not respect the directives in .htaccess with ‘require ip‘ and I couldn’t limit the website to certain addresses. The problem is that when Apache is behind a proxy ( HAProxy in this case ), the ‘require ip‘ will not pass the correct IP address. The correct IP address of the visitor is located in the ‘X-Forwarded-For’ variable. Therefore, .htaccess needs to be modified so that instead of ‘require ip’, it will respect another variable into which we will pass the values of ‘X-Forwarded-For’.

Below is an example of how it was solved in a case where it was necessary to request a password only if the website visitor did not come from a specific IP address which is added to the exceptions.”

Example:

<If "%{HTTP_HOST} == 'this.isnowworking.com'">
SetEnv IF_MATCHES_HOST true
AuthUserFile /etc/httpd/.htpasswd
AuthType Basic
AuthName "Restricted access"

SetEnvIF X-Forwarded-For "1.1.1.1" AllowIP
SetEnvIF X-Forwarded-For "2.2.2.2" AllowIP
SetEnvIF X-Forwarded-For "3.3.3.3" AllowIP

<RequireAny>
Require valid-user
Require env AllowIP
</RequireAny>
</If>

Directadmin – build GeoIP2 in Directadmin’s NGINX and create country blocking for vhosts.

GeoIP is super helpful if you have troubles with a lot of nasty requests from some nasty countries :). Or, sometimes, you just want to lock some website or part of it ( administration ), so that it is accessible only from your country.

Things are a little different when you are using Directadmin control panel. I had this Directadmin with NGINX reverse proxy, so all NGINX is first point for requests made on your websites. Besides SSL offloading, you can also do filtering, country blocking … before request ends on backend ( Apache ).

So, here is how you can build GeoIP2 extension into your NGINX on Directadmin. I my case, I have Nginx as reverse proxy with Apache.

Check which NGINX version is installed on your server

[root@da nginx]# nginx -v
nginx version: nginx/1.23.1

Continue Reading

© 2025 geegkytuts.net
Hosted by SIEL


About author