1. 博客/

httpd+svn服务器部署

·1765 字·9 分钟
Svn Httpd Openssl

本文主要介绍https双向认证httpd + 用户Basic Authorization + svn的部署

安装配置svn
#

[root@test] ~$ yum -y install subversion
[root@test] ~$ mkdir /data/repos

创建一个仓库 myhub

[root@test] repos$ svnadmin create /data/repos/myhub
[root@test] repos$ cd /data/repos/myhub
[root@test] myhub$ ls
conf  db  format  hooks  locks  README.txt

配置svn

[root@test] myhub$ cd conf/
[root@test] conf$ ls
authz  passwd  svnserve.conf

[root@test] conf$ grep -v "^#\|^$" svnserve.conf
[general]
anon-access = none
auth-access = write
password-db = httpdPasswd
authz-db = authz
realm = myhub
[sasl]
  • anon-access: 匿名用户访问仓库的权限,取值范围为 “write”,“read”,“none”
  • auth-access:认证用户访问仓库的权限,取值范围为 “write”,“read”,“none”
  • password-db: 用户认证密码库文件
  • authz-db: 基于路径的访问权限控制的规则库文件
  • realm: 登录svn时提示的认证域名称,如果两个仓库使用相同的认证域,那么认证密码库文件应该一致,反之亦然

配置lisa用户有读写权限,并创建认证密码库文件

[root@test] conf$  grep -v "^#\|^$" authz
[aliases]
[groups]
[/]
lisa = rw
[myhub:/]
lisa = rw

[root@test] conf$ htpasswd -c -m httpdPasswd lisa
New password:
Re-type new password:
Adding password for user lisa

启动svn

[root@test] conf$ cat /etc/sysconfig/svnserve
# OPTIONS is used to pass command-line arguments to svnserve.
#
# Specify the repository location in -r parameter:
OPTIONS="-r /data/repos --listen-host 127.0.0.1 --listen-port 3690"

[root@test] conf$ systemctl start svnserve

httpd配置
#

安装httpd及模块
#

[root@test] ~$ yum install -y httpd mod_ssl mod_dav_svn
[root@test] ~$ httpd -t -D DUMP_MODULES|grep -E "ssl|svn"
 ssl_module (shared)
 dav_svn_module (shared)
 authz_svn_module (shared)

自签名CA根证书
#

[root@test] cert$ pwd
/data/cert

# 创建CA根证书私钥
[root@test] cert$ openssl genrsa -out root_ca.key 2048
Generating RSA private key, 2048 bit long modulus
.....................+++
.+++
e is 65537 (0x10001)

[root@test] cert$ cat openssl.cnf
[ req ]
# 证书主体的各属性信息使用的section配置,如通用名(CN)、组织单位(OU)
distinguished_name = req_distinguished_name
# 创建自签名证书请求时,使用扩展section配置
x509_extensions	= v3_ca

[req_distinguished_name]

[v3_ca]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
# basicConstraints 指证书的基本约束(基本限制)扩展字段
# 该证书具备签发其他证书的能力,可以作为CA证书使用
basicConstraints = CA:true

# X509证书签发时使用的v3扩展section配置,For Server
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
# 证书主体CN别名使用的section配置
subjectAltName = @mysvn

[ mysvn ]
DNS.1 = ffu.com
IP.1 = 192.168.83.127

# X509证书签发时使用的扩展section配置,For Client
[ usr_cert ]
basicConstraints=CA:true
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

# 创建CA根证书
[root@test] cert$ openssl req -x509 -new -nodes -key root_ca.key -subj "/CN=FFU ROOT CA" -days 36500  -config openssl.cnf  -out root_ca.crt

[root@test] cert$  openssl x509 -in root_ca.crt -noout -text -certopt no_validity,no_sigdump,no_pubkey,no_serial
Certificate:
    Data:
        Version: 3 (0x2)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=FFU ROOT CA
        Subject: CN=FFU ROOT CA
        X509v3 extensions:
            X509v3 Subject Key Identifier:
            X509v3 Authority Key Identifier:
            X509v3 Basic Constraints:
                CA:TRUE

服务端证书生成
#

# 创建服务端证书私钥
[root@test] cert$ openssl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus
......+++
.....+++
e is 65537 (0x10001)

# 创建服务端证书请求文件
[root@test] cert$ openssl req -new -key server.key  -out server.csr -config openssl.cnf -subj "/CN=*.mysvn.com"
openssl x509签发
#

opessl x509 -req 命令可以签发证书,但是没有维护历史签发证书记录,也不支持吊销证书

# 签发服务器证书
# -extfile openssl.cnf: 指定包含扩展配置的文件名
# -extensions v3_req: 指定使用扩展配置中的v3_req扩展来生成证书
[root@test] cert$ openssl x509 -req -in server.csr -CA root_ca.crt -CAkey root_ca.key -CAcreateserial  -out server.crt -days 36500 -extensions v3_req -extfile openssl.cnf
Signature ok
subject=/CN=*.mysvn.com
Getting CA Private Key

[root@test] cert$ openssl x509 -in server.crt -noout  -text -certopt no_header,no_version,no_serial,no_signame,no_validity,no_pubkey,no_sigdump,no_aux
        Issuer: CN=FFU ROOT CA
        Subject: CN=*.mysvn.com
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Key Usage:
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Subject Alternative Name:
                DNS:mysvn.com, IP Address:192.168.83.127
openssl ca签发
#

openssl ca 命令根据指定配置文件中[ ca ] 的相关配置项,维护本地签发证书的索引数据库,便于管理,也支持吊销证书

openssl.cnf文件新增配置,如下

[root@test] cert$ mkdir /data/cert/myCA && cd myCA
[root@test] cert$ cat myCA/openssl.cnf
# openss ca命令使用的配置section
[ ca ]
default_ca	= CA_default

[ CA_default ]
# 工作目录
dir		= .
# 签发证书存放目录
certs		= $dir/certs
# 吊销证书列表文件存放目录
crl_dir		= $dir/crl
# 签发证书索引数据库
database	= $dir/index.txt
# 证书的subject是否保证唯一性
unique_subject	= no

# 证书tmp目录,默认文件名为[serialnumber.pem]
new_certs_dir	= $dir/newcerts

# CA根证书文件
certificate	= $dir/root_ca.crt
# 当前可用的证书序列号
serial		= $dir/serial
# 当前可用的吊销证书列表序列号
crlnumber	= $dir/crlnumber
# 吊销证书列表文件
crl		= $dir/crl.pem
# CA根证书私钥
private_key	= $dir/private/root_ca.key
RANDFILE	= $dir/private/.rand

# 默认x509扩展的section配置
x509_extensions	= usr_cert

name_opt 	= ca_default
cert_opt 	= ca_default

# 吊销证书列表使用的扩展的section配置
# Netscape communicator旧版本不支持X.509标准新增的CR V2规范
# crlnumber和crl_extensions需要都注释才是V1 CRL
crl_extensions	= crl_ext

# 签发证书默认有效期天数
default_days	= 365
# 吊销证书列表默认有效期天数
default_crl_days= 30
# 默认加密算法
default_md	= sha256
# 是否对subject的各属性重新排序,建议配置
preserve	= no
# subject的各属性设置的策略
policy		= policy_anything

# optional 可选设置项
# supplied 必须设置项
[ policy_anything ]
countryName		= optional
stateOrProvinceName	= optional
localityName		= optional
organizationName	= optional
organizationalUnitName	= optional
commonName		= supplied
emailAddress		= optional

[ req ]
# 证书主体的各属性信息使用的section配置,如通用名(CN)、组织单位(OU)
distinguished_name = req_distinguished_name
# 创建自签名证书请求时,使用扩展section配置
x509_extensions	= v3_ca

[req_distinguished_name]

[v3_ca]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
# basicConstraints 指证书的基本约束(基本限制)扩展字段
# 该证书具备签发其他证书的能力,可以作为CA证书使用
basicConstraints = CA:true

# X509证书签发时使用的v3扩展section配置,For Server
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
# 证书主体CN别名使用的section配置
subjectAltName = @mysvn

#根据需求配置
[ mysvn ]
DNS.1 = ffu.com
IP.1 = 192.168.83.127

# X509证书签发时使用的扩展section配置,For Client
[ usr_cert ]
basicConstraints=CA:FALSE
#keyUsage = nonRepudiation, digitalSignature, keyEncipherment
#nsComme = "OpenSSL Generated Certificate"

# CRL扩展section配置
[ crl_ext ]
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always

签发证书

[root@test] cert$ cp -r /etc/pki/CA/* myCA/
[root@test] cert$ cp root_ca.crt myCA/
[root@test] cert$ cp root_ca.key myCA/private/
[root@test] cert$ cp server.key myCA/private/
# 生成证书索引数据库文件
[root@test] myCA$ touch index.txt
# 指定第一个签发证书的序列号,十六进制,签发后序列号自动增加
[root@test] myCA$ echo 01 > serial
[root@test] myCA$ openssl req -new -key private/server.key -out server.csr -config openssl.cnf -subj "/CN=*.ffu.com"
# -extensions 使用openssl.cnf中[ v3_req ]section配置
[root@test] myCA$ openssl ca -config openssl.cnf -in server.csr -out certs/server.crt -days 365 -extensions v3_req -batch
Using configuration from openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Feb  6 07:37:58 2020 GMT
            Not After : Feb  5 07:37:58 2021 GMT
        Subject:
            commonName                = *.ffu.com
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Key Usage:
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Subject Alternative Name:
                DNS:ffu.com, IP Address:192.168.83.127
Certificate is to be certified until Feb  5 07:37:58 2021 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

# 索引库文件已更新
[root@test] myCA$ cat index.txt
V	210205072251Z		01	unknown	/CN=*.ffu.com

# 目录结构
[root@test] myCA$ tree
.
├── certs
│   └── server.crt
├── crl
├── crlnumber
├── index.txt
├── index.txt.attr
├── index.txt.old
├── newcerts
│   └── 01.pem
├── openssl.cnf
├── private
│   ├── root_ca.key
│   └── server.key
├── root_ca.crt
├── serial
├── serial.old
└── server.csr

客户端证书生成
#

[root@test] myCA$ openssl genrsa -out private/client.key 2048
Generating RSA private key, 2048 bit long modulus
..................+++
.......................+++
e is 65537 (0x10001)

[root@test] myCA$ openssl req -new -key private/client.key  -out client.csr -config openssl.cnf  -subj "/CN=svn_client"
[root@test] myCA$ openssl ca -config openssl.cnf -in client.csr -out certs/client.crt -days 365 -batch
Using configuration from openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 2 (0x2)
        Validity
            Not Before: Feb  6 07:39:46 2020 GMT
            Not After : Feb  5 07:39:46 2021 GMT
        Subject:
            commonName                = svn_client
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
Certificate is to be certified until Feb  5 07:39:46 2021 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

[root@test] myCA$ cat index.txt
V	210205073758Z		01	unknown	/CN=*.ffu.com
V	210205073946Z		02	unknown	/CN=svn_client

# 创建PKCS12格式的证书文件,需要下发给客户端
[root@test] myCA$ openssl pkcs12 -export -clcerts -in certs/client.crt -inkey private/client.key -out certs/client.p12
Enter Export Password:
Verifying - Enter Export Password:

修改配置
#

配置文件/etc/httpd/conf/httpd.conf

# 注释http监听端口
# Listen 80
# 新增一个全局默认ServerName
ServerName 127.0.0.1
# 新增SSLRequireSSL
<Directory />
    AllowOverride none
    SSLRequireSSL
    Require all denied
</Directory>

# 新增
TraceEnable off
ServerSignature Off
ServerTokens Prod

ssl配置

[root@test] repos$ cd /etc/httpd/
[root@test] httpd$ mkdir -p cert/crl
[root@test] httpd$ cd cert/
[root@test] cert$ cp /data/cert/server.key .
[root@test] cert$ cp /data/cert/server.crt .
[root@test] cert$ cp /data/cert/root_ca.crt .

# 配置文件/etc/httpd/conf.d/ssl.conf
# 监听所有网卡
<VirtualHost *:443>
# 虚拟主机匹配的域名
ServerName mysvn.ffu.com
ServerAlias 192.168.83.127:443

# 服务端公私钥
SSLCertificateFile /etc/httpd/cert/server.crt
SSLCertificateKeyFile /etc/httpd/cert/server.key

# 开启客户端证书验证, 按需配置
SSLCACertificateFile /etc/httpd/cert/root_ca.crt
SSLVerifyClient require
SSLVerifyDepth  10
SSLCARevocationCheck chain
SSLCARevocationFile "/etc/httpd/cert/crl/crl.pem"

因为当前httpd版本不支持参数no_crl_for_cert_ok,可以生成一个不包含吊销证书列表的CRL文件,避免httpd报错

Optional flags available in httpd 2.4.21 or later

openssl.cnf中配置了CRL默认有效期default_crl_days= 30 ,需要及时更新crl.pem并reload httpd服务。如果crl.pem过期,请求httpd会报错

AH02276: Certificate Verification: Error (12): CRL has expired

也可以通过命令行参数-crldays 指定有效期

[root@test] myCA$ openssl ca -gencrl -out crl/crl.pem -config openssl.cnf -crldays 365
[root@test] myCA$ cp crl/crl.pem /etc/httpd/cert/crl/
[root@test] myCA$ openssl crl -in crl/crl.pem -noout -text
Certificate Revocation List (CRL):
        Version 2 (0x1)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: /CN=FFU ROOT CA
        Last Update: Feb  7 06:30:52 2020 GMT
        Next Update: Feb  6 06:30:52 2021 GMT
        CRL extensions:
            X509v3 CRL Number:
                1
 No Revoked Certificates.  

SVN配置文件

[root@test] conf.d$ cat /etc/httpd/conf.d/subversion.conf
<Location />
   DAV svn
   SVNListParentPath off
   SVNParentPath /data/repos/
   # Limit write permission to list of valid users.
   AuthType Basic
   AuthName "Authorization Realm"
   #用户认证密码库文件
   AuthUserFile /data/repos/myhub/conf/httpdPasswd
   AuthzSVNAccessFile /data/repos/myhub/conf/authz
   Satisfy all
   SVNAutoversioning on
   ModMimeUsePathInfo on
   Require valid-user

   Order Deny,Allow
   Allow from 192.168.83.0/24
   Deny from all
</Location>
<Location ~ "\.svn">
    Order Deny,Allow
    Deny from all
</Location>

[root@test] conf.d$ httpd -t
Syntax OK

[root@test] repos$ chown apache:apache /data/repos/myhub -R
[root@test] conf.d$ systemctl start httpd

svn客户端访问
#

以下配置适用linux或者macos客户端访问

修改svn客户端配置文件~/.subversion/server

[groups]
myhub = 192.168.83.127

[myhub]
store-ssl-client-cert-pp = yes
# 明文客户端秘钥包密码不保存本地
store-ssl-client-cert-pp-plaintext = no

store-passwords = yes
# 明文用户密码不保存本地
store-plaintext-passwords = no
# 服务器https双向认证时,客户端秘钥包文件
ssl-client-cert-file = /root/.subversion/myhub/client.p12
# 服务器证书的CA
ssl-authority-files = /root/.subversion/myhub/root_ca.crt

[root@node2] ~/.subversion/myhub$ ls
client.p12  root_ca.crt

拉取SVNmyhub库到本地,第一次登录需要输入密码,如果配置了保存密码,下次登录不需要再次输入

[root@node2] /data$ svn checkout https://192.168.83.127/myhub --username=lisa
“/root/.subversion/myhub/client.p12”的密码:
认证领域: <https://192.168.83.127:443> Authorization Realm
“lisa”的密码:
取出版本 0。

[root@node2] /data$ cd myhub/
[root@node2] /data$ touch test
[root@node2] /data/myhub$ svn status
?       test
[root@node2] /data/myhub$ svn add test
A         test
[root@node2] /data/myhub$ svn status
A       test
[root@node2] /data/myhub$ svn ci -m "add test file"
正在增加       test
传输文件数据.
提交后的版本为 1。
[root@node2] /data/myhub$ svn update
正在升级 '.':
版本 1。
[root@node2] /data/myhub$ svn log
------------------------------------------------------------------------
r1 | lisa | 2020-05-06 21:17:47 +0800 (二, 2020-05-06) | 1
add test file
------------------------------------------------------------------------

客户端证书的吊销
#

客户端pcks12证书可能会泄露,如果遇到这种情况,需要服务器拒绝其访问。可以通过openssl ca -revoke命令吊销客户端证书,并更新httpd配置的crl.pem文件

以上文lisa用户的客户端证书为例

吊销旧证书
#

[root@test] ~$ cd /data/cert/myCA
[root@test] myCA$ openssl ca -revoke certs/client.crt -config openssl.cnf
Using configuration from openssl.cnf
Revoking Certificate 02.
Data Base Updated
[root@test] myCA$ cat index.txt
V	210205073758Z		01	unknown	/CN=*.ffu.com
R	210205073946Z	200207065105Z	02	unknown	/CN=svn_client

[root@test] myCA$ openssl ca -gencrl -out crl/crl.pem -config openssl.cnf -crldays 365
Using configuration from openssl.cnf
[root@test] myCA$ openssl crl -in crl/crl.pem -noout -text
Certificate Revocation List (CRL):
        Version 2 (0x1)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: /CN=FFU ROOT CA
        Last Update: Feb  7 06:53:00 2020 GMT
        Next Update: Feb  6 06:53:00 2021 GMT
        CRL extensions:
            X509v3 CRL Number:
                2
Revoked Certificates:
    Serial Number: 02
        Revocation Date: Feb  7 06:51:05 2020 GMT
        
[root@test] myCA$ cp crl/crl.pem /etc/httpd/cert/crl/  
[root@test] myCA$ httpd -t
Syntax OK
[root@test] myCA$ httpd -k graceful

客户端使用旧证书client.p12访问失败

[root@node2] /data/myhub$ svn list
svn: E175002: Unable to connect to a repository at URL 'https://192.168.83.127/myhub'
svn: E175002: 方法 OPTIONS 失败于 “https://192.168.83.127/myhub”: SSL handshake failed: 收到 SSL 警报: 证书已吊销 (https://192.168.83.127)

签发新证书
#

[root@test] myCA$ openssl genrsa -out private/new_client.key 2048
Generating RSA private key, 2048 bit long modulus
............................................................................................................+++
...................................+++
e is 65537 (0x10001)
[root@test] myCA$ openssl req -new -key private/new_client.key  -out new_client.csr -config openssl.cnf  -subj "/CN=svn_client"
[root@test] myCA$ openssl ca -config openssl.cnf -in new_client.csr -out certs/new_client.crt -days 365 -batch
Using configuration from openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 3 (0x3)
        Validity
            Not Before: Feb  7 07:02:18 2020 GMT
            Not After : Feb  6 07:02:18 2021 GMT
        Subject:
            commonName                = svn_client
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
Certificate is to be certified until Feb  6 07:02:18 2021 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

[root@test] myCA$ openssl pkcs12 -export -clcerts -in certs/new_client.crt -inkey private/new_client.key -out certs/new_client.p12
Enter Export Password:
Verifying - Enter Export Password:

客户端拿到new_client.p12后访问

[root@node2] ~$ cd ~/.subversion/myhub
root@node2] ~/.subversion/myhub$ mv new_client.p12 client.p12

[root@node2] ~/.subversion/myhub$ cd /data/myhub/
[root@node2] /data/myhub$ svn list
test

Related

Docker配置TLS安全认证
·516 字·3 分钟
Docker CA Openssl
如何使用openssl工具创建私有CA
·970 字·5 分钟
Linux CA Openssl
kvm虚拟机磁盘扩容
·2036 字·10 分钟
Kvm Linux WindowsServer