nginx配置单向认证与双向认证
nginx配置单向认证与双向认证
1. 生成所需证书
将以下下代码保存为create_cert.sh并执行, 可以按需要修改 PROJECT_NAME 和 CN 等属性。
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the axTLS project nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# Generate the certificates and keys for testing.
#
PROJECT_NAME="TLS Nginx Test"
# Generate the openssl configuration files.
cat > ca_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME Dodgy Certificate Authority
EOF
cat > server_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME
CN = 10.42.166.214
EOF
cat > client_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME Device Certificate
CN = 10.42.166.214
EOF
mkdir ca
mkdir server
mkdir client
mkdir certDER
# private key generation
openssl genrsa -out ca.key 1024
openssl genrsa -out server.key 1024
openssl genrsa -out client.key 1024
# cert requests
openssl req -out ca.req -key ca.key -new \
-config ./ca_cert.conf
openssl req -out server.req -key server.key -new \
-config ./server_cert.conf
openssl req -out client.req -key client.key -new \
-config ./client_cert.conf
# generate the actual certs.
openssl x509 -req -in ca.req -out ca.crt \
-sha1 -days 5000 -signkey ca.key
openssl x509 -req -in server.req -out server.crt \
-sha1 -CAcreateserial -days 5000 \
-CA ca.crt -CAkey ca.key
openssl x509 -req -in client.req -out client.crt \
-sha1 -CAcreateserial -days 5000 \
-CA ca.crt -CAkey ca.key
openssl x509 -in ca.crt -outform DER -out ca.der
openssl x509 -in server.crt -outform DER -out server.der
openssl x509 -in client.crt -outform DER -out client.der
mv ca.crt ca.key ca/
mv server.crt server.key server/
mv client.crt client.key client/
mv ca.der server.der client.der certDER/
rm *.conf
rm *.req
rm *.srl
生成证书后的目录结构为:
create_cert.sh
ca/
ca.crt
ca.key
certDER/
ca.der
client.der
server.der
client/
client.crt
client.key
server/
server.crt
server.key
2. nginx单向认证配置
其中97端口是无认证,98端口是单向认证的配置
server {
listen 97;
location /hello {
default_type 'application/json';
return 200 '{"status":"success","text":"No authentication"}';
}
}
server {
listen 98;
ssl on;
ssl_certificate /opt/cert/server/server.crt;
ssl_certificate_key /opt/cert/server/server.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
location /hello {
default_type 'application/json';
return 200 '{"status":"success","text":"One-way authentication"}';
}
}
3. nginx双向认证配置
server {
listen 99;
ssl on;
ssl_certificate /opt/cert/server/server.crt;
ssl_certificate_key /opt/cert/server/server.key;
ssl_client_certificate /opt/cert/ca/ca.crt;
ssl_verify_client on;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
location /hello {
default_type 'application/json';
return 200 '{"status":"success","text":"Two-way authentication"}';
}
}
4. python client连接测试
import urllib.request
import ssl
import json
def no_authentication(url):
headers = {
'Content-Type': 'application/json',
}
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request)
print (json.loads(response.read().decode('utf8')))
def one_way_authentication(url, cafile):
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.load_verify_locations(cafile)
headers = {
'Content-Type': 'application/json',
}
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request, context=context)
print (json.loads(response.read().decode('utf8')))
def two_way_authentication(url, cafile, certfile, keyfile):
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.load_cert_chain(certfile, keyfile)
context.load_verify_locations(cafile)
headers = {
'Content-Type': 'application/json',
}
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request, context=context)
print (json.loads(response.read().decode('utf8')))
# 证书文件
cafile = 'ca.crt'
certfile = 'client.crt'
keyfile = 'client.key'
# 无认证
no_authentication("http://127.0.0.1:97/hello")
# 单向认证
one_way_authentication("https://127.0.0.1:98/hello", cafile)
# 双向认证
two_way_authentication("https://127.0.0.1:99/hello", cafile, certfile, keyfile)
执行后输入结果为:
{'status': 'success', 'text': 'No authentication'}
{'status': 'success', 'text': 'One-way authentication'}
{'status': 'success', 'text': 'Two-way authentication'}
参考资料
- python关于SSL/TLS认证的实现, https://blog.csdn.net/vip97yigang/article/details/84721027
- Nginx单向认证和双向认证安装配置, https://blog.csdn.net/liucy007/article/details/86719902