114

Ceph Civetweb HTTPS的实现方案

 4 years ago
source link: http://mp.weixin.qq.com/s/g-romQHneaJGTzM98ZS2fw
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Ceph Civetweb HTTPS的实现方案

董林鹏 荆文军 苏研存储小黑板 2017-07-03 01:09 Posted on

从Jewel 10.2.6 版本开始, Civetweb可以使用OpenSSL库同时支持HTTP和HTTPS,并且不再需要使用软连接方式创建openSSL的动态链接库,极大的方便了Rados Gateway(以下简称RGW)的配置和运维。

Why HTTPS

HTTP协议传输的数据都是未加密的,比如访问搜索网站输入的搜索关键字等都是透明可见的,对于传输用户敏感数据和隐私信息是不安全的。

HTTPS是以安全为目标的HTTP通道,简单的可以认为 HTTPS=HTTP+加密+认证+完整性保护。即HTTP下加入SSL(TLS)层,HTTPS的安全基础是SSL。

SSL及其继任者TLS是为网络通信提供安全及数据完整性的一种安全协议。SSL与TLS在传输层对网络连接进行加密。SSL协议提供的安全通道有以下三个特性:

  • 机密性:SSL协议使用密钥加密通信数据。

  • 可靠性:服务器和客户都会被认证,客户的认证是可选的。

  • 完整性:SSL协议会对传送的数据进行完整性检查。

Civetweb配置HTTPS

  • 创建自签名证书

生成根证书的私钥,参数des3是加密算法,用其签发服务器端证书或者客户端证书

openSSL genrsa -des3 -out server.key 1024

生成服务器端签名请求证书(csr证书)

openSSL req -new -key server.key -out server.csr    
cp server.key server.key.orig

去除密钥文件的保护密码,每次读取key文件时可以不需要口令

openSSL rsa -in server.key.orig -out server.key

生成自签名证书,有效期设置为10年

openSSL x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
cp server.crt /etc/ceph/private/server.pem
cat server.key >> /etc/ceph/private/server.pem

注:在生成服务器端签名请求证书时,为了与AWS S3的桶域名访问规则一致,需要设置common name(CN)选项为`*.yourdomain.com`,其他的选项可根据实际情况来定。

  • 配置/etc/ceph/ceph.conf

在[client.rgw.INSTANCE] section添加rgw_dns_name和rgw_frontends两个参数。

[client.rgw.instance01]
host = hostname
rgw_dns_name = yourdomain.com
rgw_frontends = "civetweb port=8088+443s ssl_certificate=/etc/ceph/private/server.pem"

注:在`rgw_frontends`参数中配置3.1小节中生成的SSL自签名证书server.pem的路径。

Nginx反向代理支持HTTPS

如果使用Nginx提供RGW负载均衡服务,可以在Nginx层实现SSL支持,RGW则可以保持原有配置不变,其配置过程如下:

  • 创建自签名证书

创建私钥证书目录

mkdir /etc/SSL/private && chmod 700 /etc/SSL/private

生成私钥和自签名证书到指定目录

openSSL req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/SSL/private/nginx-selfsigned.key -out /etc/SSL/certs/nginx-selfsigned.crt

注:在生成服务器端签名请求证书时,为了与AWS S3的桶域名访问规则一致,需要设置common name(CN)选项为`*.yourdomain.com`,其他的选项可根据实际情况来定。

生成Strong Diffie-Hellman Group

openSSL dhparam -out /etc/SSL/certs/dhparam.pem 2048
  • 配置/etc/nginx/nginx.conf

cat /etc/nginx/nginx.conf
HTTP {

    ...
    ...
    ...
    upstream  rgw  {
        server   10.142.*.*:8088;
        ...
        ...
        server   10.142.*.*:8088;
    }
    server {
        listen       18080 default;
        listen       [::]:18080 default;
        server_name  yourdomain.com;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            proxy_pass        http://rgw;
            proxy_set_header   Host             $host:$server_port;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
        error_page 404 /404.html;
            location = /40x.html {
        }
        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
    server {
        listen       18080;
        listen       [::]:18080;
        server_name  *.yourdomain.com;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            if ( $host ~* (.*)\.yourdomain.com$) {
                        proxy_pass      http://rgw$request_uri;
            }
            proxy_set_header   Host             $host:$server_port;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
        error_page 404 /404.html;
            location = /40x.html {
        }
        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}
  • 配置/etc/nginx/conf.d/SSL.conf 

cat /etc/nginx/conf.d/SSL.conf
server {
    listen 18443 HTTP2 SSL;
    listen [::]:18443 HTTP2 SSL;

    server_name yourdomain.com;

    SSL_certificate /etc/SSL/certs/nginx-selfsigned.crt;
    SSL_certificate_key /etc/SSL/private/nginx-selfsigned.key;
    SSL_dhparam /etc/SSL/certs/dhparam.pem;
    root         /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;


    location / {
            proxy_pass        http://rgw;
            proxy_set_header   Host             $host:$server_port;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}
server {
    listen 18443;
    listen [::]:18443;
    server_name *.yourdomain.com;
    SSL_certificate /etc/SSL/certs/nginx-selfsigned.crt;
    SSL_certificate_key /etc/SSL/private/nginx-selfsigned.key;
    SSL_dhparam /etc/SSL/certs/dhparam.pem;
    root         /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
            if ( $host ~* (.*)\.yourdomain.com$) {
                        proxy_pass      http://rgw$request_uri;
            }
            proxy_set_header   Host             $host:$server_port;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

注:示例配置文件中HTTPS后端的RGW和HTTP的后端RGW相同,如果将HTTPS和HTTP的RGW分开,则在/etc/nginx/conf.d/SSL.conf 文件前添加upstream块。

测试验证HTTPS数据加密

测试以Civetweb配置HTTPS为例。

  • RGW主机和测试主机配置/etc/hosts

在RGW主机和测试主机/etc/hosts添加:

10.139.*.* yourdomain.com
  • 通过python sdk分别使用HTTP和HTTPS list bucket

使用HTTP list bucket

cat http_test.py
from boto3.session import Session
    import boto3
    import botocore
    import warnings
    warnings.filterwarnings("ignore", category=UnicodeWarning)

    access_key = "your access key"
    secret_key = "your secret key"
    url = "http://yourdomain.com:8088" 
    s3 = boto3.client('s3',
                      use_SSL=False,
                      verify=False,
                      endpoint_url=url,
                      aws_access_key_id=access_key,
                      aws_secret_access_key=secret_key
                      )

    def list_buckets_of_user():
        resp = s3.list_buckets()['Buckets']
        for bucket in resp:
            print bucket['Name']

    list_buckets_of_user()

使用HTTPS list bucket:这里的证书是自签名而不是机构颁发,所以为测试方便,在脚本中需要设置不检查证书。

cat https_test.py
    from boto3.session import Session    import boto3    import botocore    import warnings
    warnings.filterwarnings("ignore", category=UnicodeWarning)

        access_key = "your access key"
        secret_key = "your secret key"
        url = "HTTPS://yourdomain.com" #HTTPS使用443端口,此处不显示配置
    s3 = boto3.client('s3',
                      use_SSL=True,
                      verify=False,
                      endpoint_url=url,
                      aws_access_key_id=access_key,
                      aws_secret_access_key=secret_key
                      )    def list_buckets_of_user():
        resp = s3.list_buckets()['Buckets']        for bucket in resp:            print bucket['Name']

    list_buckets_of_user()



  • 执行测试脚本并网络抓包

tcpdump tcp -i eth0 -s 0 -c 1000 and  host yourdomain.com -w ./http_rgw.cap
tcpdump tcp -i eth0 -s 0 -c 1000 and  host yourdomain.com -w ./https_rgw.cap

使用wireshark进行抓包解析,分别如下图所示:

a) http_rgw.cap解析

Image

b) https_rgw.cap解析

Image

从上图可以看出,通过HTTPS访问RGW,请求数据被加密了,用户的敏感数据和隐私得到了有效的保护。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK