【5.0】认证客户端的链接合法性
【一】如何实现验证
【1】思路
- 在TCP协议中,客户端和服务端之间的连接是通过三次握手过程建立起来的。
- 在这个过程中,会进行一些简单的验证来确保连接的安全性和合法性。
【2】具体的过程
-
客户端向服务器发送一个SYN(同步)包,其中包含一个随机生成的序列号seq=x和一个标志位SYN=1。
-
服务器收到这个SYN包后,返回一个SYN/ACK(同步/确认)包,其中包含自己的序列号seq=y和确认序号ack=x+1,并且标志位SYN和ACK都设置为1。
-
客户端再次发送一个ACK(确认)包,其中包含确认序号ack=y+1和标志位ACK设置为1。
【3】总结
- 通过上述的三次握手过程,客户端和服务端之间建立了可靠的连接。
- 在这个过程中,没有对客户端的身份进行验证,这是因为在TCP/IP模型中,面向连接的服务通常不会对客户端的身份进行验证。
- 如果需要更高级别的安全性,可以在应用程序层实现身份验证,例如使用SSL/TLS协议。在SSL/TLS协议中,客户端和服务端之间会进行握手协商,以确定使用的加密算法、版本等信息,并在连接建立之后进行数据加密和身份验证。
【二】加密思路
- 如果你想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂
- 那么利用hmac+加盐的方式来实现
【1】服务端
from socket import *
import hmac, os
secret_key = b'this is a secret key'
def conn_auth(conn):
'''
认证客户端链接
:param conn:
:return:
'''
print('开始验证新链接的合法性')
msg = os.urandom(32)
conn.sendall(msg)
h = hmac.new(secret_key, msg)
digest = h.digest()
respone = conn.recv(len(digest))
return hmac.compare_digest(respone, digest)
def data_handler(conn, bufsize=1024):
if not conn_auth(conn):
print('该链接不合法,关闭')
conn.close()
return
print('链接合法,开始通信')
while True:
data = conn.recv(bufsize)
if not data: break
conn.sendall(data.upper())
def server_handler(ip_port, bufsize, backlog=5):
'''
只处理链接
:param ip_port:
:return:
'''
tcp_socket_server = socket(AF_INET, SOCK_STREAM)
tcp_socket_server.bind(ip_port)
tcp_socket_server.listen(backlog)
while True:
conn, addr = tcp_socket_server.accept()
print('新连接[%s:%s]' % (addr[0], addr[1]))
data_handler(conn, bufsize)
if __name__ == '__main__':
ip_port = ('127.0.0.1', 9999)
bufsize = 1024
server_handler(ip_port, bufsize)
【2】合法客户端
from socket import *
import hmac, os
# 定义秘钥串
secret_key = b'this is a secret key'
# 对秘钥串进行hash加密
def conn_auth(conn):
'''
验证客户端到服务器的链接
:param conn:
:return:
'''
# 接收 32 长度的字符串
msg = conn.recv(32)
# 将接收到的数据和秘钥串进行加密校对
h = hmac.new(secret_key, msg)
digest = h.digest()
conn.sendall(digest)
def client_handler(ip_port, bufsize=1024):
# 创建tcp链接对象
tcp_socket_client = socket(AF_INET, SOCK_STREAM)
tcp_socket_client.connect(ip_port)
# 先将秒传接收到
conn_auth(tcp_socket_client)
while True:
data = input('>>: ').strip()
if not data: continue
if data == 'quit': break
tcp_socket_client.sendall(data.encode('utf-8'))
respone = tcp_socket_client.recv(bufsize)
print(respone.decode('utf-8'))
tcp_socket_client.close()
if __name__ == '__main__':
ip_port = ('127.0.0.1', 9999)
bufsize = 1024
client_handler(ip_port, bufsize)
【3】非法客户端(无加密方式)
from socket import *
def client_handler(ip_port, bufsize=1024):
tcp_socket_client = socket(AF_INET, SOCK_STREAM)
tcp_socket_client.connect(ip_port)
while True:
data = input('>>: ').strip()
if not data: continue
if data == 'quit': break
tcp_socket_client.sendall(data.encode('utf-8'))
respone = tcp_socket_client.recv(bufsize)
print(respone.decode('utf-8'))
tcp_socket_client.close()
if __name__ == '__main__':
ip_port = ('127.0.0.1', 9999)
bufsize = 1024
client_handler(ip_port, bufsize)
【4】非法客户端(无秘钥)
from socket import *
import hmac, os
secret_key = b'this is a secret key'
def conn_auth(conn):
'''
验证客户端到服务器的链接
:param conn:
:return:
'''
msg = conn.recv(32)
h = hmac.new(secret_key, msg)
digest = h.digest()
conn.sendall(digest)
def client_handler(ip_port, bufsize=1024):
tcp_socket_client = socket(AF_INET, SOCK_STREAM)
tcp_socket_client.connect(ip_port)
conn_auth(tcp_socket_client)
while True:
data = input('>>: ').strip()
if not data: continue
if data == 'quit': break
tcp_socket_client.sendall(data.encode('utf-8'))
respone = tcp_socket_client.recv(bufsize)
print(respone.decode('utf-8'))
tcp_socket_client.close()
if __name__ == '__main__':
ip_port = ('127.0.0.1', 9999)
bufsize = 1024
client_handler(ip_port, bufsize)
本文来自博客园,作者:Chimengmeng,转载请注明原文链接:https://www.cnblogs.com/dream-ze/p/17968022