Tuesday, May 19, 2020

DNS record types needed for MTA server



Types of needed DNS resords (as example I'll use mysubd.webredirect.org):
  • A record points mysubd.webredirect.org to a hard coded IP address
  • MX record - point mysubd.webredirect.org to a mail server. These type of records are special for just mail servers, they can co-exist with A records, and their only use is for routing mail to a different location. All mail implementations check for this record first before attempting to route an e-mail message. If a MX record does not exist for a host, an e-mail delivery would be attempted directly to the IP that the hostname resolves to.
  • PTR record - used to perform a Reverse DNS lookup (match IP address t)
  • FCrDNS (Forward-Confirmed rDNS) - if you have A record for your subdomain (mail.mysubd.webredirect.org) and also PTR record pointing to the same subdomain-name, then you can say that you have reached FCrDNS
  • SPF record - advertise which machines are allowed to send mail on behalf of my domain
  • DKIM - is an email authentication technique that allows the receiver to check that an email was indeed sent and authorized by the owner of that domain.
  • DMARC - technical specification. Mail server decides itself which mail is good or bad using DMARC record. DMARC allows instructing a destination mail server what to do with senders that fail SPF and DKIM tests. Most notably it allows instructing them to reject such senders.


  • Adding DNS records

    Check that server IP address is not is a spammers list:
    https://mxtoolbox.com/blacklists.aspx
    https://www.senderscore.org/

    If you don't have your own url registered to DNS hosting, then register on https://www.dynu.com  (below are for Linux DNS but approach is general to all flavours of DNS).

    Add subdomains and needed records:

    A record:
    1. mail.mysubd.webredirect.org IN  A yourIPaddress
    2. Check:
      1. host mail.mysubd.webredirect.org
      2. dig -t A mail.mysubd.webredirect.org +short
    MX record:
    1. mysubd.webredirect.org. IN MX 10 mail.mysubd.webredirect.org.
    2. Check:
      1. dig -t MX mysubd.webredirect.org +short
    PTR record:
    1. yourIPaddress IN PTR mail.mysubd.webredirect.org
    2. But usually this must be set up on your ISP side
    3. Check:
      1. host yourIPaddress
    SPF record:
    1. not all servers understand SPF record (it's deprecated) so it's good to use both TXT and SPF records. Below I allow sending mail only from servers in my own subdomain:
      1. mysubd.webredirect.org.  IN TXT  "v=spf1 +mx -all"
      2. mysubd.webredirect.org.  IN SPF  "v=spf1 +mx -all"
      3. Options described:
        1. v=spf1 > use SPF v1
        2. + > allow
        3. mx > all servers in mysubd.webredirect.org MX records
        4. - > deny
        5. all > all servers not listed in SPF record
      4. Check:
        1. https://mxtoolbox.com/spf.aspx
    DKIM (create keys of length 1024 - longer keys are generally create problems because of not being supported by many hosts):
    1. create a directory to hold the keys:  mkdir -p /etc/mail/dkim
    2. Generate the keypair and extract the public key out of the private key
      1. openssl genrsa -out /etc/mail/dkim/mysubd.webredirect.org.key 1024
      2. openssl rsa -in /etc/mail/dkim/mysubd.webredirect.org.key -pubout -out /etc/mail/dkim/mysubd.webredirect.org.pub
    3. Add DKIM record:
      1. 20200514._domainkey.mysubd.webredirect.org. IN TXT "v=DKIM1;k=rsa;p=addContentOfPublicKeyHere;"
      2. ; is delimiter between parameters
      3. 20200514 - selector (I used just YYYY.MM.DD of cert generation but you can use anything you want)
    4. Check:
      1. https://dkimcore.org/tools/
    DMARC record:
    1. _dmarc.mysubd.webredirect.org.   IN TXT    "v=DMARC1;p=none;pct=100;rua=mailto:postmaster@mysubd.webredirect.org;"
      1. p > what to do (none - only for reporting / quarantine - adds to spam / reject - rejects mail)
      2. pct > percentage of mail to be filtered
      3. rua > daily report mail
    2. Check:
      1. https://dmarcian.com/dmarc-inspector/

    Thursday, May 14, 2020

    Mail server on CentOS7 (Postfix, Dovecot, Rspamd without DB)

    MTA (Mail Transport Agent) - send mail over SMTP protocol - Postfix, OpenSMTPD software (post office)
    MUA (Mail User Agent) - e-mail agent - Outlook, Thunderbird etc. (user of mailbox)
    MDA (Mail Delivery Agent) - sends mails to MUA using POP3 / IMAP protocols - Dovecot software (mailbox)

    For DNS records use https://it-tuff.blogspot.com/2020/05/dns-record-types-and-meaning-types-of.html

    mail.mysubd.webredirect.org - A / MX record
    vi /etc/hostname
    mail.mysubd.webredirect.org
    hostnamectl

    yum install postfix
    yum install dovecot

    Adding user for mail management:
    groupadd -g 5000 vmail
    useradd -s /usr/sbin/nologin -u 5000 -g 5000 vmail

    Add user postfix and dovecot to group vmail:
    usermod -aG vmail postfix
    usermod -aG vmail

    Add the folder the mails will be stored in and give rights to user vmail:
    mkdir -p /var/mail/vhosts/mysubd.webredirect.org
    chown -R vmail:vmail /var/mail/vhosts
    chmod -R 775 /var/mail/vhosts

    Create dovecot log file:
    touch /var/log/dovecot
    chgrp vmail /var/log/dovecot
    chmod 660 /var/log/dovecot

    Virtual mailboxes:
    /etc/postfix/vmailbox will be used for that job
    Make hash of this file:
    postmap /etc/postfix/vmailbox

    Virtual aliases:
    vi /etc/postfix/virtual # below example redirects all mails to mysubd.webredirect.org to the catch-all@mysubd.webredirect.org
    @mysubd.webredirect.org catch-all@mysubd.webredirect.org
    postmap /etc/postfix/virtual

    Virtual domains (if more than one domain is going to be supported then add a domain per line in the below file):
    vi /etc/postfix/virtual_domains
    mysubd.webredirect.org

    SSL certificate - choose one of below - either self signed certificate or Let's Encrypt certificate.

    Self signed certificate:
    mkdir /etc/dovecot/ssl
    cd /etc/dovecot/ssl
    openssl req -new -newkey rsa:3072 -nodes -keyout mailserver.key -days 9999 -x509 -out mailserver.crt
    country name > LT
    common name > mail.mysubd.webredirect.org

    Let's Encrypt certificate:
    allow 80 port:
    iptables -R INPUT 1 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
    install ACME (Automated Certificate Management Environment) protocol used to automate interactions between CA and users of certs:
    yum install certbot
    Generate certificate using certbot internal webservice (--standalone option) for communication with CA:
    certbot certonly --standalone -d mail.mysubd.webredirect.org
    Add default crontab entry for automatic renewal of certificates (each cert is valid for only 90 days):
    echo "0 0,12 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
    cat /etc/crontab
    Certs are added to /etc/letsencrypt/live/mail.mysubd.webredirect.org directory:
    public key is fullchain.pem (goes to smtpd_tls_cert_file)
    private key is privkey.pem (goes to smtpd_tls_key_file)

    /etc/postfix/main.cf
    smtpd_banner = $myhostname ESMTP
    biff = no
    append_dot_mydomain = no
    recipient_delimiter = +
    readme_directory = no
    #CHANGETHIS
    myhostname = mail.mysubd.webredirect.org
    #CHANGETHIS
    mydomain = mysubd.webredirect.org
    myorigin = $mydomain
    inet_interfaces = all
    # add additional domains to the list below if needed
    mydestination = localhost, $myhostname
    mynetworks = 127.0.0.0/8
    ##VIRTUAL DOMAIN##
    virtual_mailbox_domains = /etc/postfix/virtual_domains
    virtual_mailbox_base = /var/mail/vhosts
    virtual_mailbox_maps = hash:/etc/postfix/vmailbox
    virtual_alias_maps = hash:/etc/postfix/virtual
    virtual_minimum_uid = 100
    virtual_uid_maps = static:5000
    virtual_gid_maps = static:5000
    virtual_transport = virtual
    dovecot_destination_recipient_limit = 1
    mailbox_size_limit = 0
    ##SASL##
    smtpd_sasl_auth_enable = yes
    smtpd_sasl_type = dovecot
    smtpd_sasl_path = private/auth
    smtpd_sasl_security_options = noanonymous
    smtpd_sasl_local_domain = $mydomain
    broken_sasl_auth_clients = yes
    ##TLS##
    smtpd_use_tls=yes
    smtpd_tls_security_level = may
    smtpd_tls_auth_only = no
    smtpd_tls_cert_file=/etc/dovecot/ssl/mailserver.crt
    smtpd_tls_key_file=/etc/dovecot/ssl/mailserver.key
    smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
    smtpd_tls_received_header = yes
    tls_random_source = dev:/dev/urandom
    smtpd_tls_security_level = may
    smtp_tls_security_level = may
    ##restrictions##
    smtpd_helo_required=yes
    strict_rfc821_envelopes = yes
    disable_vrfy_command = yes
    smtpd_delay_reject = yes
    ##limit rate##
    anvil_rate_time_unit = 60s
    smtpd_client_connection_rate_limit = 5
    smtpd_client_connection_count_limit = 5
    smtpd_error_sleep_time = 5s
    smtpd_soft_error_limit = 2
    smtpd_hard_error_limit = 3
    ##################
    smtpd_helo_restrictions= reject_non_fqdn_hostname,
      reject_invalid_helo_hostname,
      reject_unknown_helo_hostname
    smtpd_client_restrictions = permit_mynetworks,
      permit_sasl_authenticated,
      reject_unknown_client_hostname,
      reject_unauth_pipelining,
      reject_rbl_client zen.spamhaus.org
    smtpd_sender_restrictions = reject_non_fqdn_sender,
      reject_unknown_sender_domain
    smtpd_recipient_restrictions = permit_mynetworks,
      permit_sasl_authenticated,
      reject_invalid_hostname,
      reject_non_fqdn_hostname,
      reject_non_fqdn_sender,
      reject_non_fqdn_recipient,
      reject_unauth_destination,
      reject_unauth_pipelining,
      reject_rbl_client zen.spamhaus.org,
      reject_rbl_client cbl.abuseat.org,
      reject_rbl_client dul.dnsbl.sorbs.net
    smtpd_recipient_limit = 250
    broken_sasl_auth_clients = yes
    #message_size_limit = 120480000
    ##remove IP header##
    # requires postfix-pcre (apt-get install postfix-pcre)
    #header_checks has the following content:
    #/^\s*(Received: from)[^\n]*(.*)/ REPLACE $1 [127.0.0.1] (localhost [127.0.0.1])$2
    #
    #smtp_header_checks = pcre:/etc/postfix/header_checks

    /etc/dovecot/dovecot.conf
    auth_mechanisms = plain login
    disable_plaintext_auth = no
    log_path = /var/log/dovecot
    mail_location = maildir:/var/mail/vhosts/%d/%n
    passdb {
      args = /var/mail/vhosts/%d/shadow
      driver = passwd-file
    }
    protocols = imap pop3
    service auth {
      unix_listener /var/spool/postfix/private/auth {
        group = vmail
        mode = 0660
        user = postfix
      }
      unix_listener auth-master {
        group = vmail
        mode = 0600
        user = vmail
      }
    }
    ssl_cert = </etc/dovecot/ssl/mailserver.crt
    ssl_key = </etc/dovecot/ssl/mailserver.key
    userdb {
      args = /var/mail/vhosts/%d/passwd
      driver = passwd-file
    }
    protocol lda {
      auth_socket_path = /var/run/dovecot/auth-master
      #CHANGETHIS
      hostname = mail.mysubd.webredirect.org
      mail_plugin_dir = /usr/libexec/dovecot
      mail_plugins = sieve
      #CHANGETHIS
      postmaster_address = postmaster@mysubd.webredirect.org
    }

    /etc/postfix/master.cf
    dovecot   unix  -       n       n       -       -       pipe
      flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}

    Script to add users:
    vi add_mail.sh
    #!/bin/bash
    USAGE="Usage: $0 EMAIL PASSWORD [BASEDIR]";
    #
    if [ ! -n "$2" ]
    then
      echo $USAGE;
      exit 1;
    fi
    #
    USERNAME=$(echo "$1" | cut -f1 -d@);
    DOMAIN=$(echo "$1" | cut -f2 -d@);
    ADDRESS=$1;
    PASSWD=$2;
    #
    if [ -n "$3" ]
    then
      if [ ! -d "$3" ]
      then
        echo $USAGE;
        echo "BASEDIR must be a valid directory!";
        echo "I would have tried, $(postconf | grep ^virtual_mailbox_base | cut -f3 -d' ')";
        exit 2;
      else
        BASEDIR="$3";
      fi
    else
      BASEDIR="$(postconf | grep ^virtual_mailbox_base | cut -f3 -d' ')";
    fi
    #
    if [ -f /etc/postfix/vmailbox ]
    then
    #
      echo "Adding Postfix user configuration..."
      echo $ADDRESS $DOMAIN/$USERNAME/ >> /etc/postfix/vmailbox
      postmap /etc/postfix/vmailbox
    #
      if [ $? -eq 0 ]
      then
        echo "Adding Dovecot user configuration..."
        echo $ADDRESS::5000:5000::$BASEDIR/$DOMAIN/$ADDRESS>> $BASEDIR/$DOMAIN/passwd
        echo $ADDRESS":"$(doveadm pw -p $PASSWD) >> $BASEDIR/$DOMAIN/shadow
        chown vmail:vmail $BASEDIR/$DOMAIN/passwd && chmod 775 $BASEDIR/$DOMAIN/passwd
        chown vmail:vmail $BASEDIR/$DOMAIN/shadow && chmod 775 $BASEDIR/$DOMAIN/shadow
        systemctl restart postfix
      fi
    #
    fi

    Add previously configured postmaster mail user

    Add a new mail user:
    ./add_mail.sh user@mysubd.webredirect.org Z123456z

    systemctl enable postfix
    systemctl start postfix
    systemctl enable dovecot
    systemctl start dovecot
    systemctl status dovecot
    systemctl status postfix


    Check that postfix setting made properly:
    postfix check

    Check mail queue:
    mailq

    Force mails from queue to be sent:
    postfix flush

    To check non-default settings:
    postconf -n
    dovecot -n

    iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 993 -j ACCEPT
    iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT

    To check all available settings of Postfix (you can use grep to filter output):
    postconf

    yum install mailx

    echo "This is message body" | mailx -s "This is Subject" -r "user<user@mysubd.webredirect.org>"  -a "attachment_file_name" somebody@gmail.com

    Also if you just want to send mail once then postfix configuration is too simple (uncomment or add below lines in /etc/postfix/main.cf and then systemctl restart postfix):
    inet_interfaces = all
    inet_protocols = all
    mynetworks=127.0.0./8

    To check mail in console use mail (-u key shows mail for specified user):
    mail -u root
    mail -u admin

    25 —  SMTP over STARTTLS;
    80 —  HTTP for Postfixadmin and Roundcube;
    110 — POP3 через STARTTLS;
    143 —IMAP через STARTTLS;
    443 — HTTPS for Postfixadmin and Roundcube;
    465 — secured SMTP over SSL/TLS;
    587 — secured SMTP over STARTTLS;
    993 — secured IMAP over SSL/TLS;
    995 — secured POP3 over SSL/TLS.

    Mail client configuration:
    SMTP, IMAP and POP3 server: mail.mysubd.webredirect.org
    SMTP Port: 25 (or 587, or 8080. In some networks, port 25 and 587 outgoing are blocked)
    IMAP Port: 143
    POP3 Port: 110
    Security type: SSL/TLS

    username: user@mysubd.webredirect.org
    (NOT just “user”)

    You will receive a warning message for the first time you connect to each, SMTP, IMAP and POP3, because you are using a self-signed certificate.


    For SMTPS support uncomment below lines in /etc/postfix/master.cf
    smtps     inet  n       -       n       -       -       smtpd
      -o syslog_name=postfix/smtps
      -o smtpd_tls_wrappermode=yes
      -o smtpd_sasl_auth_enable=yes
      -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
      -o smtpd_sasl_type=dovecot
      -o smtpd_sasl_path=private/auth

    systemctl restart postfix

    Test:
    ss -l4n

    iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 465 -j ACCEPT

    To enable port 587 (submission) uncomment below in master.cf:
    submission inet n       -       n       -       -       smtpd

    systemctl restart postfix

    Test:
    ss -l4n

    iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 587 -j ACCEPT

    To disable port 25 comment below in master.cf:
    #smtp      inet  n       -       n       -       -       smtpd

    systemctl restart postfix

    Test:
    ss -l4n


    TO TEST MAIL SERVER SETTINGS QUALITY USE: 


    Rspamd
    yum install epel-release
    yum install luajit
    curl https://rspamd.com/rpm-stable/centos-7/rspamd.repo > /etc/yum.repos.d/rspamd.repo
    rpm --import https://rspamd.com/rpm-stable/gpg.key 
    yum update 
    yum install redis
    systemctl start redis
    systemctl status redis

    yum install rspamd

    vi /etc/postfix/main.cf
    # Milter (Mail fILTER) setup
    smtpd_milters = inet:localhost:11332
    milter_default_action = accept
    milter_protocol = 6

    systemctl restart postfix
    systemctl enable rspamd 
    systemctl start rspamd

    Check that rspamd ports are up (especially 11332 used for rspamd_proxy - postfix milter)

    To configure Rspamd:
    rspamadm configwizard
    add controller pass
    add redis 
    add redis pass

    systemctl restart redis
    systemctl status redis
    systemctl restart rspamd

    vi /var/log/rspamd/rspamd.log

    cat /etc/rspamd/local.d/redis.conf
    password = "d123456D";
    write_servers = "127.0.0.1:6379";
    read_servers = "127.0.0.1:6379";

    systemctl restart redis
    systemctl status redis
    systemctl restart rspamd

    vi /etc/rspamd/local.d/dkim_signing.conf
    allow_username_mismatch = true;
    domain {
                 mysubd.webredirect.org {
                             path = "/etc/mail/dkim/mysubd.webredirect.org.key";
                             selector = "20200514";
                             }
    }

    systemctl restart rspamd
    systemctl status rspamd


    Outlook ports 993 and 465 (both SSL) + outgoing server needs authentication

    Script to delete user:
    del_mail.sh

    #!/bin/bash
    USAGE="Usage: $0 EMAIL [BASEDIR]";
    #
    if [ ! -n "$1" ]
    then
      echo $USAGE;
      exit 1;
    fi
    #
    USERNAME=$(echo "$1" | cut -f1 -d@);
    DOMAIN=$(echo "$1" | cut -f2 -d@);
    ADDRESS=$1;
    #
    if [ -n "$2" ]
    then
      if [ ! -d "$2" ]
      then
        echo $USAGE;
        echo "BASEDIR must be a valid directory!";
        echo "I would have tried, $(postconf | grep ^virtual_mailbox_base | cut -f3 -d' ')";
        exit 2;
      else
        BASEDIR="$2";
      fi
    else
      BASEDIR="$(postconf | grep ^virtual_mailbox_base | cut -f3 -d' ')";
    fi
    #
    echo $BASEDIR
    if [ -f /etc/postfix/vmailbox ]
    then
    #
      echo "Removing Postfix user configuration..."
      sed -i "/$USERNAME/d" /etc/postfix/vmailbox
      postmap /etc/postfix/vmailbox
    #
      if [ $? -eq 0 ]
      then
        echo "Removing Dovecot user configuration..."
        sed -i "/$USERNAME/d" $BASEDIR/$DOMAIN/passwd
        sed -i "/$USERNAME/d" $BASEDIR/$DOMAIN/shadow
        systemctl restart postfix
        echo "Removing user mail directory..."
        rm -rf $BASEDIR/$DOMAIN/$USERNAME
      fi
    #
    fi

    To check rspamd work:
     rspamd_stats --log /var/log/rspamd
    Ham - is normal mail
    Spam - sent to everyone, not wanted by anyone, sent out frequently, 
    Junk - sent to specific group, can be interesting for some and irritating for the others, sent out not so frequently, 

    Wednesday, May 13, 2020

    MiktoTik first steps through console


    Commands split into hierarchical groups. Commands can be executed by going to the needed place in hierarchy (for example "ip" , then "route", then "print") or directly (just type "ip route print").
    Prompt changes to show you current location inside hierarchy.
    .. and / can be used to execute commands from other levels.

    print command is used to show item names along with item numbers (interface print). Items are interfaces, ports etc. Item numbers are assigned on a per session basis, they will remain the same until you quit the console or until the next print command is executed.

    set command is used to change properties of items using item number or name. Also one set command allows using of comma separated list of item numbers (like: interface set 0,1,3 mtu=1400)

    Tab can be used to complete commands and command abbreviations are also allowed.

    Commands common to nearly all levels of menu are:
    1. print / set  / find / get / export / enable / disable / comment
    2. remove - removes item from the list
    3. add - same as set but adds new item with the specified number
    4. edit - associated with set command and used to edit values and properties containing large amount of text
    5. move - changes the order of items in list
    The console has a built-in help, which can be accessed by typing ?. Help topic shown is about item on the left of ? sign.

    You not need to save config. Config saved automatically when you click OK in winbox or press enter in terminal.

    MikroTik has Winbox utility for administering but because of many reports of hacker attacks it is safer to use setup over SSH console - if using default firewall rules. Or if want to use Winbox - change default Winbox port and remove default user (before that add other user with admin privileges) and also allow Winbox access only from trusted IP addresses.

    To enable or disable system port of MikroTIk:
    > ip service
    ip service> print
    ip service> set 0,2,5 disable=yes #disables
    ip service> set 3 disable=no #enables

    To view firewall rules:
    /ip firewall> filter print

    Add address to the needed address-list:
    /ip firewall address-list> add list=Needed_IP_list address=8.8.8.8

    Remove IP from the list:
    /ip firewall address-list>  remove 20

    Print IP addresses in a group:
    /ip firewall address-list>  print where list=Needed_IP_list





    Wednesday, May 6, 2020

    OpenVPN, Easy-RSA: cert, cert pass, user-pass (PAM)

    Overview and initial setup


    Security and encription in OpenVPN is done by OpenSSL library and TCP protocol TLS (Transport Layer Security).
    OpenVPN can use symmetric (one key for all users) and asymmetric (each user has it's own key).
    When asymmetric cryptography is used each user has private and public key.
    Public key is used for encryption and private for decryption. Private key must stay on host where it was created and only public keys must be transferred.
    Certification authority (CA) - used to verify identity of keys.
    Сertificate Revocation List (CRL) - file is used to store revoked certificates.

    sudo yum update -y
    sudo yum install epel-release -y
    sudo yum install -y openvpn wget
    wget -O /tmp/easyrsa https://github.com/OpenVPN/easy-rsa-old/archive/2.3.3.tar.gz
    tar xfz /tmp/easyrsa
    sudo mkdir /etc/openvpn/easy-rsa
    sudo cp -rf easy-rsa-old-2.3.3/easy-rsa/2.0/* /etc/openvpn/easy-rsa
    ll /etc/openvpn/easy-rsa/

    Use user other than root (ex. admin):
    sudo chown admin /etc/openvpn/easy-rsa/

    Copy sample config files (openvpn server.conf and openssl.conf) to the OpenVPN directories:
    sudo cp /usr/share/doc/openvpn-2.4.8/sample/sample-config-files/server.conf /etc/openvpn
    cp /etc/openvpn/easy-rsa/openssl-1.0.0.cnf  /etc/openvpn/easy-rsa/openssl.cnf


    Setup vars template


    cd /etc/openvpn/easy-rsa

    Change  /etc/openvpn/easy-rsa/vars file according to below (but don't delete other setting in that file), this file will be used as template when generating certificates:
    export DH_KEY_SIZE=2048
    export KEY_SIZE=4096
    export CA_EXPIRE=3650
    export KEY_EXPIRE=3650
    # Enter the two-letter abbreviation of the country of your residence
    export KEY_COUNTRY="US"
    # This should be the abbreviation of the state of your residence
    export KEY_PROVINCE="CA"
    # Enter the name of the city you live in.
    export KEY_CITY="SanFrancisco"
    # Enter the name of your organization or company
    export KEY_ORG="Fort-Funston"
    # Enter the email address that you want to be connected to the security certificate (more than one mail is allowed)
    export KEY_EMAIL="me@myhost.mydomain"
    export KEY_EMAIL=mail@host.domain
    # Enter the domain, subdomain that resolves to your server or an IP address of your server
    # For the purpose of OpenVPN server common name can be really anything
    export KEY_CN="www.xxx.yyy.zzz"
    # You should enter server here. If you enter something else, you would also have to update the configuration files that reference server.key and server.crt
    export KEY_NAME="server"
    # Enter the name of the “Organizational Unit” to which you belong, typically either the name of your department or team
    export KEY_OU=changeme

    Verify file contents:
    sudo grep -E "(^[a-z]|^[0-9])" /etc/openvpn/easy-rsa/vars

    Generating server keys and certs


    All below are done only once, when server is setup first time

    Add directory for key-cert storage:
    mkdir /etc/openvpn/easy-rsa/keys

    Use vars template:
    source ./vars

    Remove any keys and certificates already in the folder
    ./clean-all

    Generate CA. Some questions will appear and you can hit Enter for all because of using vars template:
    ./build-ca

    Generate key-cert for OpenVPN server itself. As with CA vars template is used and you can safely "Enter" and accept defaults. You'll be prompted to enter optional password, if specified clients will enter this password each time they try to connect to OpenVPN server:
    ./build-key-server server

    Generate Diffie-Hellman which necessary if TLS/SSL is used:
    ./build-dh

    Copy generated file to the /etc/openvpn:
    cp dh2048.pem ca.crt server.crt server.key /etc/openvpn/

    Generate static key for encrypting of TLS handshake between server and client:
    sudo openvpn --genkey --secret /etc/openvpn/myvpn.tlsauth


    server.conf file


    vi /etc/openvpn/server.conf # you also can use other options in server.conf (push options are used for routing)
    port 22222 #also iptables rule will be needed iptables - I INPUT -p udp -m state --state NEW -m udp --dport 22222 -j ACCEPT
    proto udp4 #udp will work faster on slow connections
    dev tun # TUN allows routing
    ca ca.crt
    cert server.crt
    key server.key  # This file should be kept secret
    dh dh2048.pem
    topology subnet
    server 10.8.0.0 255.255.255.0
    ifconfig-pool-persist ipp.txt # file used to store DHCP infinity bindings
    keepalive 10 120
    ;tls-auth ta.key 0 #comment this out in order to use tls-crypt
    tls-crypt myvpn.tlsauth
    cipher AES-256-CBC
    user nobody
    group nobody
    persist-key
    persist-tun
    status openvpn-status.log # info about currently connected users is here
    verb 3
    explicit-exit-notify 1
    remote-cert-eku "TLS Web Client Authentication" # ensures that a server will verify that the client certificate provided is truly a client certificate, and vice versa for the client which checks that the server certificate truly aimed for a server

    Verify:
    grep -E "(^[a-z]|^[0-9])" /etc/openvpn/server.conf

    Start and verify OpenVPN server:
    sudo systemctl -f enable openvpn@server.service
    sudo systemctl start openvpn@server.service
    sudo systemctl status openvpn@server.service

    Generating client keys and certs


    cd /etc/openvpn/easy-rsa/keys
    source ./vars
    ./build-key name.surname # CN must be equal username
    ls -1 name.surname*
    name.surname.crt
    name.surname.csr
    name.surname.key

    Also other types of client cert are, for example build-key-pass will generate cert with pass. Client will be asked for that pass every time trying to connect to the OpenVPN server.

    client side configuration file


    We'll use one file approach - name.surname.ovpn:
    client
    tls-client
    remote-cert-eku "TLS Web Server Authentication"
    proto udp
    remote www.xxx.yyy.zzz 22222 udp
    dev tun
    topology subnet
    pull
    user nobody
    group nobody
    persist-tun
    persist-key
    cipher AES-256-CBC
    keysize 256
    tun-mtu 1500
    auth-nocache
    <ca>
    ca.crt content goes here
    </ca>
    <cert>
    name.surname.crt content goes here
    </cert> 
    <key> 
    name.surname.key content goes here
    </key>
    <tls-crypt>
    /etc/openvpn/myvpn.tlsauth content goes here
    </tls-crypt>


    Using OpenVPN server as gateway


    Enable packet forwarding through OpenVPN server (here only ipv4 forwarding is enabled):
    vi /etc/sysctl.conf
    # Controls IP packet forwarding
    net.ipv4.ip_forward = 1
    sysctl -p

    If you want to "hide" OpenVPN client addresses while accessing network behind OpenVPN server (eth0 in example is gateway NIC on OpenVPN server):
    iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
    service iptables save

    If you want to redirect all client traffic to the OpenVPN server (Internet and all other traffic):
    push "redirect-gateway def1 bypass-dhcp"
    push "dhcp-option DNS 8.8.8.8"
    push "dhcp-option DNS 8.8.4.4"

    sudo systemctl restart openvpn@server.service
    sudo systemctl status openvpn@server.service

    Revoking user certificates


    To revoke user cert:
    source ./vars
    ./revoke-full name.username

    After that crl.pem is generated inside /etc/openvpn/easy-rsa/keys/ directory and also index.txt file is changed. index.txt file contains list of all generated certificates and information concerning their validity: V - valid or R - revoked.

    If revoke cert is not working verify than name.surname.crt file is not empty, if empty, then:
    grep name.surname index.txt
    Note number of needed user (ex. 07), then:
    cp keys/07.pem keys/name.surname.crt
    source ./vars
    ./revoke-full name.surname

    After that crl.pem must be copied to /etc/openvpn every time it is changed:
    cp crl.pem /etc/openvpn

    Also crl-verify crl.pem line must be added to the server.conf

    Then restart and verify OpenVPN server (restart is needed only first time after additon of crl-verify parameter):
    systemctl restart openvpn@server
    systemctl status openvpn@server

    By revoking the original certificate, it is possible to generate a new certificate/key pair with the user’s original common name.

    Using PAM authentication


    Using PAM (Pluggable Authentication Modules) authentication (/etc/pam.d/):

    1. add user with the same name as in your CN of the client certificate. This user will be without /home directory and ability to login: 
      1. useradd -M -s /sbin/nologin name.surname
      2. passwd name.surname
    2. edit /etcp/openvpn/server.conf and add:
      1.  plugin /etc/openvpn/openvpn-plugin-auth-pam.so login
    3. copy plugin to the /etc/openvpn :
      1. cp /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so /etc/openvpn
    4. systemctl restart openvpn@server
    5. sudo systemctl status openvpn@server
    6. on client side add auth-user-pass to the configuration
    7. now when trying to connect to the OpenVPN server you'll be prompted for (created above)) user-password