chilinux wroteDoing GeoIP blocking on a per packet basis in iptables can be costly in terms of performance.
If you are only trying to restrict TCP sessions such as to TCP 443 and TCP 943 then you can use the iptables --syn flag to limit the GeoIP lookups to just the initial connection attempt. In that case doing GeoIP via iptables is not too bad.
Thanks for that tip, I'll look into that.
chilinux wroteHowever, for UDP port 1194, it becomes more tricky. You can use the iptables state table to track "established" sessions from IPs that have already been GeoIP checked. However, iptables has a finite number of state table entries it allows. A small distributed denial of service can easily flood the state table resulting in all UDP VPN connection attempts failing for everyone during the length of the attack.
In our situation this is probably overkill. All employees must use the OpenVPN client so they make a connection with the API over HTTPS right? We have UDP flood detection and limits in place though and the machine has enough memory to increase nf_conntrack_max if necessary in case we would implement such a solution.
chilinux wroteTwo other places where GeoIP checking could be added instead is in the post_auth script and PAM support in OpenVPN AS.
I'd like to shield the web interface, post_auth and PAM are beyond that scope. But great tip, didn't know about the post-auth script possibilities!
chilinux wroteMaxMind provides a free service to getting their GeoLite2 database. They also provide a python module to query it which it should be possible to incorporate into the post_auth script.
Similar to the python module, there is also a package for the Pluggable Authentication Module system called pam_geoip. OpenVPN AS has minimal PAM support but I normally do not recommend using it. There is a glaring omission in the OpenVPN AS PAM support in that it gives no configuration options. The PAM API allows each application that supports PAM for authentication to provide a "Service Name." The system administrator can then specify a PAM stack that only impacts authentication from the designated app/service name. So, if you change the PAM stack for SSH to include use of pam_geoip but make a mistake, that will have no effect on being able to login via the console to correct it. The console login never uses the SSH PAM stack/service name. Likewise with other apps such as the mod_authnz_pam module for Apache. If you configure mod_authnz_pam to use a PAM service name of "wiki" then again it will never impact how other application logins work.
For whatever reason that baffles me, OpenVPN AS still doesn't include this typical configuration option for PAM (or even designate a PAM Service Name at all). As such, trying to use PAM with OpenVPN AS may have consequences for more than just OpenVPN AS. It is therefore my recommendation to be very careful/cautious when attempting to configure OpenVPN AS PAM support.
That's good to know because another step I'd like to take is to replace or supplement 2FA with an extra Yubikey authentication step. In our case it wouldn't be a real problem though if more services would be touched by implementing libpam-u2f for OpenVPN authentication.
chilinux wroteI would also agree with rob0 that it would help to understand what benefits you are seeking through GeoIP policies. A sufficiently motivated attacker will just use a proxy to appear from an allowed country.
There's the level below the motivated hacker I'd like to keep out:
Jul 21 16:14:29 servername openvpnas[3126]: [-] [WEB] OUT: '2021-07-21T16:14:29+0200 [twisted.python.log#info] "ip.add.re.ss" - - [21/Jul/2021:14:14:28 +0000] "GET /wp-admin/index.php HTTP/1.1" 404
I could of course look into something like fail2ban to prevent this but if I could do this from within OpenVPN AS I'd prefer that.
Best,
Jeremy