OpenSSLを使ったOpenVPN構築ガイド
2024年05月15日
TechOpenVPNOpenSSLセキュリティネットワーク自己署名証明書
OpenSSLを利用した中間証明書付きの実用的なOpenVPNサーバの構築方法を解説します。
OpenSSLを使ったOpenVPN構築ガイド
はじめに
OpenSSLを利用した中間証明書ありの実用化できるOpenVPNサーバの構築方法する手順について記載します。また、easyrsaは使用しないで自分で証明書の作成から行っていくため、easyrsaの場合は別のやり方をするほうがいいかもしれません。
※プロトコルやファイルの中身のことについてはあまり詳しく触れませんのでご了承ください
フォルダ・ファイルの作成
まずは必要なディレクトリとファイルを作成します。
cd /opt
mkdir -p pki/{RootCA,InterCA}/newcerts
mkdir -p pki/{configs,Server,Client}
cd pki/RootCA
echo "01" > serial
echo "00" > crlnumber
touch index.txt
cd /opt/pki/InterCA
echo "01" > serial
echo "00" > crlnumber
touch index.txt
ここまで出来たら、初期ファイル構成はとりあえずOKです。
OpenSSLのコンフィグファイル作成
次に、OpenSSLの設定ファイルを作成します。
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = ./
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
new_certs_dir = $dir/newcerts
serial = $dir/serial
crlnumber = $dir/crlnumber
crl = $dir/crl.pem
RANDFILE = $dir/.rand
name_opt = ca_default
cert_opt = ca_default
default_days = 365
default_crl_days= 30
default_bits = 2048
default_md = sha256
preserve = no
policy = policy_match
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 2048
default_md = sha256
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca
string_mask = nombstr
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ server ]
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
[ client ]
basicConstraints=CA:FALSE
keyUsage = digitalSignature
extendedKeyUsage = clientAuth
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
EC Private key作成スクリプト
以下のスクリプトを使用して、EC Private keyを作成します。
#!/bin/bash
# EC Private key作成スクリプト
CURVE="prime256v1"
if [ $# -lt 2 ]; then
echo "Usage: $0 <output_file> <name>"
exit 1
fi
OUTPUT_FILE=$1
NAME=$2
# Generate EC private key
openssl ecparam -genkey -name ${CURVE} | openssl ec -out ${OUTPUT_FILE} -aes256 -passout pass:${NAME}
ルート証明書の作成
ルート証明書を作成するためのスクリプトを用意します。
#!/bin/bash
cd /opt/pki/RootCA
# Generate Root CA private key
openssl genrsa -aes256 -out private/ca.key.pem 4096
# Generate Root CA certificate
openssl req -config ../configs/openssl_sign.cnf \
-key private/ca.key.pem \
-new -x509 -days 7300 -sha256 -extensions v3_ca \
-out certs/ca.cert.pem
中間証明書の作成(任意)
セキュリティ強化のために中間証明書を作成します。
#!/bin/bash
cd /opt/pki/InterCA
# Generate Intermediate CA private key
openssl genrsa -aes256 -out private/intermediate.key.pem 4096
# Generate Intermediate CA CSR
openssl req -config ../configs/openssl_sign.cnf -new -sha256 \
-key private/intermediate.key.pem \
-out csr/intermediate.csr.pem
# Sign Intermediate CA certificate with Root CA
cd ../RootCA
openssl ca -config ../configs/openssl_sign.cnf -extensions v3_intermediate_ca \
-days 3650 -notext -md sha256 \
-in ../InterCA/csr/intermediate.csr.pem \
-out ../InterCA/certs/intermediate.cert.pem
サーバ証明書の作成
OpenVPNサーバ用の証明書を作成します。
#!/bin/bash
cd /opt/pki/Server
# Generate Server private key
openssl genrsa -out private/server.key.pem 2048
# Generate Server CSR
openssl req -config ../configs/openssl_sign.cnf \
-key private/server.key.pem \
-new -sha256 -out csr/server.csr.pem
# Sign Server certificate with Intermediate CA
cd ../InterCA
openssl ca -config ../configs/openssl_sign.cnf -extensions server \
-days 375 -notext -md sha256 \
-in ../Server/csr/server.csr.pem \
-out ../Server/certs/server.cert.pem
クライアント証明書の作成
OpenVPNクライアント用の証明書を作成します。
#!/bin/bash
CLIENT_NAME=$1
if [ -z "$CLIENT_NAME" ]; then
echo "Usage: $0 <client_name>"
exit 1
fi
cd /opt/pki/Client
# Generate Client private key
openssl genrsa -out private/${CLIENT_NAME}.key.pem 2048
# Generate Client CSR
openssl req -config ../configs/openssl_sign.cnf \
-key private/${CLIENT_NAME}.key.pem \
-new -sha256 -out csr/${CLIENT_NAME}.csr.pem
# Sign Client certificate with Intermediate CA
cd ../InterCA
openssl ca -config ../configs/openssl_sign.cnf -extensions client \
-days 375 -notext -md sha256 \
-in ../Client/csr/${CLIENT_NAME}.csr.pem \
-out ../Client/certs/${CLIENT_NAME}.cert.pem
証明書の配置
生成した証明書を適切に配置します。
#!/bin/bash
# OpenVPN server configuration directory
OPENVPN_DIR="/etc/openvpn"
# Create necessary directories
mkdir -p ${OPENVPN_DIR}/certs
mkdir -p ${OPENVPN_DIR}/keys
mkdir -p ${OPENVPN_DIR}/client-configs/files
# Copy certificates and keys
cp /opt/pki/Server/certs/server.cert.pem ${OPENVPN_DIR}/certs/
cp /opt/pki/Server/private/server.key.pem ${OPENVPN_DIR}/keys/
cp /opt/pki/InterCA/certs/intermediate.cert.pem ${OPENVPN_DIR}/certs/
cp /opt/pki/RootCA/certs/ca.cert.pem ${OPENVPN_DIR}/certs/
# Create certificate chain file
cat /opt/pki/RootCA/certs/ca.cert.pem /opt/pki/InterCA/certs/intermediate.cert.pem > ${OPENVPN_DIR}/certs/ca-chain.cert.pem
# Generate Diffie-Hellman parameters
openssl dhparam -out ${OPENVPN_DIR}/dh2048.pem 2048
# Generate TLS authentication key
openvpn --genkey --secret ${OPENVPN_DIR}/ta.key
OpenVPN Server設定
サーバーの設定ファイルを作成します。
# OpenVPN Server Configuration
port 1194
proto udp
dev tun
ca /etc/openvpn/certs/ca-chain.cert.pem
cert /etc/openvpn/certs/server.cert.pem
key /etc/openvpn/keys/server.key.pem
dh /etc/openvpn/dh2048.pem
tls-auth /etc/openvpn/ta.key 0
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist /etc/openvpn/ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
keepalive 10 120
cipher AES-256-CBC
auth SHA256
user nobody
group nobody
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
verb 3
OpenVPN Client設定
クライアント設定ファイルのテンプレートを作成します。
# OpenVPN Client Configuration
client
dev tun
proto udp
remote your-server-ip-or-domain 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
auth SHA256
key-direction 1
verb 3
<ca>
# CA chain certificate will be inserted here
</ca>
<cert>
# Client certificate will be inserted here
</cert>
<key>
# Client private key will be inserted here
</key>
<tls-auth>
# TLS authentication key will be inserted here
</tls-auth>
自動化の設定
クライアント設定ファイル生成を自動化するスクリプトを作成します。
#!/bin/bash
# First argument is the client name
CLIENT_NAME=$1
# Exit if client name is not provided
if [ -z "$CLIENT_NAME" ]; then
echo "Usage: $0 <client_name>"
exit 1
fi
# Variables
BASE_DIR="/etc/openvpn"
OUTPUT_DIR="${BASE_DIR}/client-configs/files"
TEMPLATE_FILE="${BASE_DIR}/client-configs/base.conf"
CA_CHAIN_FILE="${BASE_DIR}/certs/ca-chain.cert.pem"
TA_KEY_FILE="${BASE_DIR}/ta.key"
CLIENT_CERT_FILE="/opt/pki/Client/certs/${CLIENT_NAME}.cert.pem"
CLIENT_KEY_FILE="/opt/pki/Client/private/${CLIENT_NAME}.key.pem"
# Make sure output directory exists
mkdir -p ${OUTPUT_DIR}
# Generate client config
cat ${TEMPLATE_FILE} \
<(echo -e '<ca>') \
${CA_CHAIN_FILE} \
<(echo -e '</ca>\n<cert>') \
${CLIENT_CERT_FILE} \
<(echo -e '</cert>\n<key>') \
${CLIENT_KEY_FILE} \
<(echo -e '</key>\n<tls-auth>') \
${TA_KEY_FILE} \
<(echo -e '</tls-auth>') \
> ${OUTPUT_DIR}/${CLIENT_NAME}.ovpn
echo "Client config file created at: ${OUTPUT_DIR}/${CLIENT_NAME}.ovpn"
これで、OpenSSLを利用した中間証明書付きのOpenVPNサーバの構築が完了です。セキュリティ対策として、定期的に証明書を更新することをお勧めします。