You are on page 1of 52

LỜI CẢM ƠN

Lời đầu tiên, nhóm chúng em xin chân thành gửi lời cảm ơn đến thầy Nguyễn
Mạnh Thắng – giảng viên khoa An toàn thông tin trường Học viện Kỹ thuật Mật

đã tạo điều kiện cũng như cung cấp kiến thức, đồng thời đưa ra những lời khuyên
cần thiết để chúng em có thể hoàn thành đề tài này.

Hà Nội, ngày 1 tháng 4 năm 2024


MỤC LỤC
MỤC LỤC ....................................................................................................................3
DANH MỤC CHỮ VIẾT TẮT....................................................................................5
DANH MỤC BẢNG:
Bảng 1.4. Chi tiết tham số của hàm socket()........................................................18
Bảng 1.5: Phương thức dùng trong giao tiếp Client/Server.................................18
Bảng 1.6: Một số phương thức hỗ trợ thu thập thông tin.....................................19
DANH MỤC HÌNH VẼ :
Hình 1.1: Cấu trúc socket.....................................................................................7
Hình 1.2. Quá trình bắt tay 3 bước......................................................................12
Hình 1.3. Cơ chế hoạt động của stream socket...................................................13
Hình 2.1. SSL Handshake...................................................................................24
LỜI NÓI ĐẦU...............................................................................................................6
Chương I: GIỚI THIỆU VỀ SOCKET PROGRAMING
1.1. Tổng quan về Socket và mục đích của Socket Programing...................................7
1.1.1. Tổng quan ........................................................................................................7
1.1.2. Mục đích của lập trình Socket .........................................................................9
1.2. Cơ chế hoạt động của Socket trong trao đổi dữ liệu qua Internet.........................10
1.3. Các ứng dụng của lập trình Socket........................................................................14
1.4. Các thư viện và ngôn ngữ hỗ trợ lập trình Socket.................................................16
1.4.1. Các ngôn ngữ hỗ trợ lập trình Socket .............................................................16
1.4.2. Giới thiệu module socket trong Python...........................................................17
CHƯƠNG II - ỨNG DỤNG AN TOÀN SOCKET PROGRAMING...................20
2.1. Các nguy cơ bảo mật trong Socket Programing...................................................20
2.1.1. Thiếu xác thực trong quá trình bắt tay ..........................................................20
2.1.2. Kênh TCP không được mã hóa......................................................................20
2.2. Các phương pháp bảo mật................................................................................21
2.2.1. Xác thực người dùng .................................................................................21
2.2.2. Giao thức SSL/TLS....................................................................................22
CHƯƠNG III – THỰC NGHIỆM......................................................................27
3.1. Tổng quan mô hình xây dựng bài toán............................................................27
3.2. Tiến hành.........................................................................................................27
3.2.1. Xác thực người dùng trong giao tiếp Client – Server................................27
3.2.2. Triển khai giao thức SSL/TLS trong giao tiếp Client – Server.................33

TÀI LIỆU THAM KHẢO........................................................................................50


DANH MỤC CHỮ VIẾT TẮT
AES Advanced Encryption Standard
CA Certificate Authority
DLP Data Loss Prevention
DoS Denial of Service
FTP File Transfer Protocol
HMAC Hash-based Message Authentication Code
HTTP Hypertext Transfer Protocol
IETF Internet Engineering Task Force
IoT Internet of Things
IP Internet Protocol
NIST National Institute of Standards and Technology
OWASP Open Worldwide Application Security Project
SCP Secure Copy Protocol
SQL Structured Query Language
SSL Secure Sockets Layer
TLS Transport Layer Security
TCP Transmission Control Protocol
UDP User Datagram Protocol
XSS Cross-site Scripting
LỜI NÓI ĐẦU

Trong thế giới kết nối mạng ngày nay, việc truyền dữ liệu qua mạng internet
thông qua socket programming đã trở thành một phần không thể thiếu của
cuộc sống hàng ngày và hoạt động kinh doanh. Socket programming cung cấp
khả năng thiết lập kết nối giữa các thiết bị mạng từ xa, cho phép truyền dữ
liệu một cách linh hoạt và hiệu quả. Tuy nhiên, điều quan trọng cần nhớ là
việc truyền dữ liệu qua mạng internet không chỉ đem lại lợi ích mà còn mở ra
nhiều rủi ro về an ninh thông tin.

Trong một thế giới mà tin tặc luôn tìm cách tìm kiếm lỗ hổng để tấn công hệ
thống, việc bảo vệ dữ liệu trở nên cực kỳ quan trọng. Socket programming,
với tính linh hoạt và mạnh mẽ của nó, không nằm ngoài tầm ngắm của những
kẻ tấn công này. Bất kỳ lỗ hổng nào trong ứng dụng có thể được lợi dụng để
xâm nhập vào hệ thống, đánh cắp dữ liệu quan trọng hoặc thậm chí là gây hại
cho hệ thống.

Bài báo cáo này sẽ đề cập đến những thách thức và giải pháp trong việc đảm
bảo an toàn trong socket programming. Bài này sẽ nói về các biện pháp bảo
mật cơ bản và nâng cao, từ việc sử dụng mã hóa dữ liệu đến cơ chế xác thực
và kiểm soát truy cập. Bằng cách hiểu rõ về những nguy cơ tiềm ẩn và áp
dụng các kỹ thuật bảo mật phù hợp, người dùng có thể xây dựng những ứng
dụng mạng an toàn và tin cậy, đóng góp vào sự phát triển bền vững của
internet và nền kinh tế số.

Hy vọng rằng bài báo cáo này sẽ giúp độc giả có cái nhìn sâu sắc hơn về vấn
đề an ninh mạng và truyền dữ liệu qua socket, đồng thời cung cấp cái nhìn về
các biện pháp bảo mật hiện đại và tiên tiến nhất để đối phó với những thách
thức đó.
CHƯƠNG I – GIỚI THIỆU VỀ SOCKET PROGRAMING
1.1. Tổng quan về Socket và mục đích của Socket Programing
1.1.1. Tổng quan
a. Socket và lập trình Socket
Socket là một điểm cuối của liên kết giao tiếp hai chiều (two-way
communication) giữa hai chương trình đang chạy trên mạng. Nó hoạt động như
một cánh cửa kết nối, cung cấp khả năng truyền dữ liệu giữa các chương trình
với nhau.
Lập trình Socket là một mô hình lập trình cho phép giao tiếp giữa các tiến trình
(ứng dụng/chương trình) qua mạng. Nó cho phép các tiến trình chạy trên các
máy
tính khác nhau trao đổi dữ liệu.
b. Cấu trúc
Socket được định nghĩa trong hệ điều hành bằng một cấu trúc, được xem như
điểm nối để hai chương trình giao tiếp với nhau. Cấu trúc của socket có 5
trường,
gồm:
− Family: xác định họ địa chỉ socket sử dụng (IPv4, IPv6,...).

− Type: xác định loại socket.

− Protocol: chỉ định giao thức cụ thể được sử dụng (thường được gán = 0).

− Local Socket Address và Remote Socket Address: là địa chỉ socket của

máy cục bộ và máy từ xa.


Hình 1.1: Cấu trúc Socket
c. Phân loại
Có 4 loại Socket phổ biến:
− Stream Socket: Tên gọi khác của loại này là Socket hướng kết nối, hoạt
động thông qua giao thức TCP (Transmission Control Protocol). Quá trình vận
hành diễn ra khi Server và Client đã kết nối với nhau. Hình thức này có ưu điểm
là dữ liệu đảm bảo truyền đúng đến nơi nhận, thứ tự và thời gian nhanh chóng,
chuẩn xác. Mỗi thông điệp gửi đi đều có xác nhận trả về cho đối tượng thực
hiện. Qua đó, người dùng được thông báo thông tin đầy đủ. Mặt khác, nhược
điểm là giữa máy chủ và máy nhận chỉ có một IP. Vì thế khi kết nối, một máy
phải chờ đến khi đối tượng kia chấp nhận kết nối.
− Datagram Socket: còn được gọi là Socket không hướng kết nối. Hình
thức hoạt động với sự hỗ trợ của giao thức UDP (User Datagram Protocol).
Datagram Socket hoạt động tốt ngay cả khi không thiết lập kết nối giữa hai máy
với nhau. Các ưu điểm có thể kể đến của Datagram Socket là quá trình kết nối,
truyền tải thông tin đơn giản, không yêu cầu quá nhiều thao tác. Thời gian
truyền
tải dữ liệu được đánh giá là cực nhanh chóng. Thế nhưng, nó có một nhược
điểm lớn là quá trình truyền thông tin chưa đảm bảo độ tin cậy, dữ liệu bên nhận
có thể không đúng với thứ tự bên truyền hoặc bị lặp.
− WebSocket: Là công cụ hỗ trợ kết nối qua lại giữa Client và Server trên
Internet. Quy trình diễn ra nhanh chóng, hiệu quả nhờ việc sử dụng TCP Socket.
Không chỉ dùng riêng cho ứng dụng web, loại này có thể áp dụng với bất kỳ
mục đích trao đổi thông tin khác. Điều cần đảm bảo là hoạt động diễn ra trên
không gian mạng. Loại này có ưu điểm như sau: Tăng cường tốc độ truyền tải
thông tin giữa hai chiều. Khi phát hiện lỗi rất dễ phát hiện và xử lý. Cách sử
dụng đơn giản, không cần cài đặt thêm các phần mềm bổ sung khác. Không cần
dùng nhiều phương pháp hỗ trợ kết nối khác nhau. Trong khi đó, nhược điểm
là nó chưa thể chạy trên tất cả trình duyệt. Điều tương tự xảy ra đối với dịch vụ
có phạm vi yêu cầu, khó hỗ trợ hoàn toàn.
− Unix Socket: Đây là điểm giao tiếp, hỗ trợ trao đổi giữa các ứng dụng
khác nhau ngay trên cùng máy tính. Mọi hoạt động được ghi nhận diễn ra ở
nhân của hệ điều hành. Nhờ vậy, tốc độ kết nối, truyền tải nhanh, nhẹ, đảm bảo
hiệu quả. Đặc điểm của Unix Socket là tránh được các bước kiểm tra hoặc
Routing. Vì thế, quá trình truyền tin dễ dàng hơn nhiều. Ngoài ra, một số ưu
điểm khác với dạng Endpoint này là: Có thể tăng cường tốc độ truy cập MySQL
lên đến 30 – 50%, giảm độ trễ, từ 60ms chỉ còn 5ms. Tăng cường PostgreSQL
lên hơn 30%. Tăng Redis lên 50%... Nhược điểm tồn tại trong trường hợp ứng
dụng nằm trên những máy chủ khác nhau. Hệ thống sẽ không thể kết nối bằng
Unix Socket. Ngoài ra, vấn đề phân quyền giữa các tập tin đôi khi vẫn xảy ra.
Ngoài ra, còn có một số loại Socket khác như Raw Socket, Sequenced Packet
Socket, …
1.1.2. Mục đích của lập trình Socket
Nhiều socket được sử dụng liên tục để tiết kiệm thời gian và nâng cao hiệu suất
làm việc.
Ưu điểm lớn nhất của socket là hỗ trợ hầu hết các hệ điều hành bao gồm MS
Windows, Linux,… Ngoài ra, nó cũng được sử dụng với nhiều ngôn ngữ lập
trình,
gồm C, C++, Java, Python, v.v… Vì thế nó tương thích với hầu hết mọi đối
tượng
người dùng với những cấu hình máy khác nhau.
Mục đích của lập trình Socket là tạo ra một cơ chế để ứng dụng có thể giao tiếp
với nhau qua mạng. Điều này có vai trò quan trọng trong việc phát triển ứng
dụng
mạng và giao tiếp giữa các thiết bị trên cùng một mạng. Dưới đây là một số mục
đích cụ thể của việc sử dụng lập trình Socket.
Giao tiếp giữa các quy trình (process): Socket cho phép các quy trình trên các
máy tính khác nhau giao tiếp với nhau. Điều này rất hữu ích trong việc xây dựng
ứng dụng phân tán, nơi các phần của ứng dụng chạy trên các máy tính riêng biệt
và cần trao đổi dữ liệu.
Truyền dữ liệu: Socket cho phép các ứng dụng gửi và nhận dữ liệu qua mạng.
Điều này cho phép truyền dữ liệu từ một máy tính đến một máy tính khác, hoặc
giữa các tiến trình trên cùng một máy tính. Các gói tin này có thể chứa thông tin
về tin nhắn, tệp tin, hoặc bất kỳ dữ liệu nào khác.
Tạo liên kết giữa client và server: Khi một ứng dụng client muốn gửi dữ liệu
đến
server, nó sẽ tạo một socket và kết nối đến socket trên server thông qua một
cổng.
Cổng là một số nguyên dương được sử dụng để xác định dịch vụ hoặc ứng dụng
cụ thể trên server.
Hỗ trợ nhiều ngôn ngữ và hệ điều hành: Socket programming không chỉ hỗ trợ
các ứng dụng viết bằng ngôn ngữ lập trình khác nhau (như Python, Java, C++,
v.v.) giúp tận dụng sức mạnh của mỗi ngôn ngữ và tối ưu hóa hiệu suất mà còn
hoạt động trên nhiều hệ điều hành khác nhau (như Windows, Linux, macOS,
v.v.)
giúp việc lập trình tích hợp dễ dàng và tăng tính linh hoạt và tương thích với
nhiều
môi trường khác nhau.
1.2. Cơ chế hoạt động của Socket trong trao đổi dữ liệu qua Internet
Hiện nay, dữ liệu được truyền qua Internet thông qua hai giao thức chủ yếu là
TCP và UDP. Đối với giao thức TCP sử dụng Stream Socket, dữ liệu được
truyền
bảo đảm tính toàn vẹn, độ tin cậy và thứ tự các gói tin. Điều đó giúp giao thức
TCP được ứng dụng chủ yếu trong những hoạt động cần độ chính xác cao như
truyền tải trang web, truyền tải email, hay kho lưu trữ điện toán đám mây,…
Ngược lại, giao thức UDP sử dụng Datagram Socket cung cấp một đường truyền
nhanh chóng, nhưng dữ liệu không thể đáng tin cậy và khó đảm bảo tính toàn
vẹn
như TCP. Dễ thấy rằng, với những đặc tính như vậy, giao thức UDP được dùng
trong những hoạt động mạng yêu cầu tính thời gian thực, hoặc không yêu cầu độ
chính xác của dữ liệu quá cao. Một số ứng dụng của giao thức UDP có thể kể
đến
là truyền phát trực tiếp, trò chơi trực tuyến, hay các ứng dụng liên lạc thời gian
thực như Zoom, Skype có thể chấp nhận một số mất mát dữ liệu mà không ảnh
hưởng đến chất lượng cuộc gọi.
*Datagram Socket
Datagram Socket là một loại socket trong lập trình mạng được sử dụng để giao
tiếp qua giao thức UDP. Datagram Socket cho phép truyền dữ liệu dưới dạng
các
gói tin độc lập, không yêu cầu việc thiết lập kết nối trước. Dưới đây là cơ chế
hoạt động của Datagram Socket:
− Tạo và gán địa chỉ cho socket: Đầu tiên, ứng dụng muốn truyền dữ liệu
cần phải tạo một Datagram Socket để thiết lập điểm kết nối trên máy tính. Sau
đó cần gán một địa chỉ IP và một số cổng cho socket, để socket có thể xác định
được nơi nó sẽ lắng nghe hoặc gửi dữ liệu.
− Gửi dữ liệu: Khi cần gửi dữ liệu, ứng dụng sử dụng hàm gửi (sendto) để
gửi
dữ liệu qua socket. Dữ liệu được gói vào các gói tin và gửi đi mà không cần
thiết lập kết nối trước.
− Nhận dữ liệu: Để nhận dữ liệu, ứng dụng sử dụng hàm nhận (recvfrom) để
lắng nghe các gói tin đến qua socket. Khi một gói tin đến, ứng dụng nhận
được dữ liệu cùng với địa chỉ và cổng của nguồn gửi.
− Xử lý dữ liệu: Sau khi nhận dữ liệu, ứng dụng có thể xử lý nó theo yêu cầu
của mình, ví dụ: hiển thị dữ liệu lên giao diện người dùng, lưu trữ vào cơ sở
dữ liệu, hoặc truyền tiếp cho các phần khác của ứng dụng.
*Stream Socket
Stream Socket được sử dụng trong giao thức TCP, cụ thể là trong quá trình bắt
tay ba bước. Quá trình này giúp thiết lập một kênh truyền an toàn giữa hai thực
thể trong mạng Internet. Đúng như tên gọi của nó, quy trình này có 3 bước cơ
bản
như sau:

Hình 1.2: Quá trình bắt tay 3 bước

− Đầu tiên, máy chủ A sẽ khởi tạo kết nối bằng cách gửi gói tin SYN đến máy
chủ đích. Gói tin này chứa một số ngẫu nhiên(ví dụ:100) đánh dấu sự bắt đầu
của số thứ tự
cho dữ liệu mà máy chủ A sẽ truyền.
− Máy chủ đích nhận gói SYN của A, sau đó nó sẽ phản hồi lại bằng gói SYN
là số thứ tự của của máy A tăng thêm 1 (VD: 101), và gói ACK là số của máy
server (VD: 200). (số xác nhận)
− Máy chủ A sau khi nhận được 2 gói ACK và SYN từ máy chủ đích, cũng sẽ
gửi lại một gói ACK xác nhận là số thứ tự của máy đích tăng thêm 1 (VD:
102).
Sau khi 3 bước được thực hiện, kênh truyền giữa 2 máy đã được tạo và nó sẽ
duy
trì liên tục cho đến khi kết thúc quá trình truyền tin. Để đi vào chi tiết hơn, hình
sau sẽ nói về cơ chế hoạt động của Stream Socket:

Hình 1.3: Cơ chế hoạt động của Stream Socket

− Bước 1: Client sẽ tạo ra 1 socket có chức năng gửi yêu cầu kết nối với Server.
Còn Server sẽ tạo 1 socket có chức năng lắng nghe và chấp nhận các yêu cầu
kết nối từ phía Client. Quá trình tạo sẽ sử dụng hàm socket(). Sau đó, hai bên
sẽ gán địa chỉ đích và Port cho socket của mình.
− Bước 2: Socket ở phía Client sẽ gửi đi gói tin SYN như một yêu cầu kết nối
bằng hàm connect(), trong khi socket ở Server sẽ lắng nghe yêu cầu bằng
hàm listen(). Khi “bắt” được yêu cầu từ phía Client, nó sẽ chấp nhận kết nối
bằng hàm accept().
− Bước 3: Server sẽ tạo một socket mới có chức năng truyền và nhận dữ liệu.
Sau đó, Client và Server sẽ trao đổi các gói tin ACK và SYN như đã trình
bày ở trên qua socket này, tiếp theo chúng mới truyền và nhận dữ liệu của
nhau qua hàm send() và recv().
− Bước 4: Sau khi quá trình trao đổi dữ liệu hoàn tất, tài nguyên trên socket sẽ
được giải phóng bằng hàm close(). Tuy nhiên socket không bị xóa hoàn toàn,
mà sẽ có thể tái sử dụng nhằm tối ưu hiệu suất và tài nguyên của Server.
Có thể thấy được, mỗi loại socket đều có ưu điểm, hạn chế, cũng như các ứng
dụng đặc thù của riêng mình. Nhưng chung quy lại, chúng đều phục vụ một mục
đích chung là trao đổi dữ liệu qua Internet.
1.3. Các ứng dụng của lập trình Socket
Lập trình Socket được sử dụng rộng rãi và có nhiều ứng dụng trong các lĩnh vực
khác nhau, bao gồm:
Giao tiếp Client-Server: Lập trình socket được sử dụng rộng rãi để cho phép
giao tiếp giữa máy khách và máy chủ trong môi trường mạng. Máy chủ lắng
nghe
các kết nối đến ở các port cụ thể, trong khi máy khách kết nối với máy chủ, cho
phép chúng trao đổi dữ liệu và thực hiện nhiều tác vụ khác nhau như truyền tệp,
truy cập từ xa và nhắn tin.
Web Server và Client: Máy chủ web, chứa các trang web và phục vụ trang
web
cho các máy khách (trình duyệt web), sử dụng lập trình socket để xử lý yêu cầu
và phản hồi HTTP. Tương tự, các máy khách (trình duyệt) sử dụng socket để
giao
tiếp với các máy chủ khi truy xuất trang web, gửi yêu cầu HTTP và nhận phản
hồi.
Ứng dụng chat: Lập trình socket cho phép giao tiếp thời gian thực trong các
ứng dụng trò chuyện, cho phép người dùng gửi và nhận tin nhắn ngay lập tức.
Các máy chủ quản lý kết nối từ nhiều client và phân phối tin nhắn giữa chúng,
tạo
điều kiện cho trò chuyện một-một hoặc trò chuyện nhóm.
Trò chơi trực tuyến đa người chơi: Lập trình socket rất quan trọng cho việc
phát
triển các trò chơi trực tuyến đa người chơi, nơi người chơi tương tác thời gian
thực với nhau. Các máy chủ sử dụng socket để quản lý kết nối của người chơi,
xử
lý logic trò chơi và đồng bộ hóa trạng thái trò chơi trên nhiều client, cho phép
trải
nghiệm chơi game có tính cộng tác và cạnh tranh.
Truy cập và điều khiển từ xa: Lập trình socket tạo điều kiện cho việc truy
nhập
và kiểm soát máy tính và các thiết bị từ xa qua mạng. Các ứng dụng desktop từ
xa và bộ giả lập terminal sử dụng socket để thiết lập kết nối giữa một thiết bị
client và một hệ thống từ xa, cho phép người dùng truy cập và quản lý tài
nguyên
từ xa. Các hệ thống phân tán: Lập trình socket đóng một vai trò quan trọng trong
việc xây dựng các hệ thống phân tán, nơi nhiều thành phần độc lập giao tiếp với
nhau qua mạng. Các ứng dụng phân tán như cơ sở dữ liệu phân tán, hệ thống tệp
phân tán và các trang tính phân tán phụ thuộc vào socket để giao tiếp giữa các
tiến trình và trao đổi dữ liệu.
IoT: Trong các hệ thống IoT, các thiết bị tương tác với nhau và với các máy
chủ tập trung để thu thập dữ liệu, giám sát môi trường và điều khiển các đối
tượng
vật lý. Lập trình socket tạo điều kiện cho việc giao tiếp giữa các thiết bị IoT,
cổng
thông tin và máy chủ đám mây, cho phép truyền dữ liệu thời gian thực, thu thập
dữ liệu cảm biến và quản lý thiết bị.
Giám sát và quản lý mạng: Lập trình socket được sử dụng trong các công cụ
giám sát và quản lý mạng để thu thập thống kê, giám sát lưu lượng và quản lý
các
thiết bị mạng. Các công cụ này sử dụng socket để giao tiếp với các thiết bị
mạng,
thu thập thông tin và thực hiện các nhiệm vụ cấu hình.
Truyền dữ liệu: Các ứng dụng truyền tập tin như FTP và SCP sử dụng lập
trình
socket để truyền tập tin giữa các client và máy chủ một cách an toàn. Socket cho
phép truyền dữ liệu đáng tin cậy và hỗ trợ các tính năng như xác minh tính toàn
vẹn của tập tin và tiếp tục truyền tập tin bị gián đoạn.
Thu thập dữ liệu: Có thể sử dụng lập trình socket để tạo các kết nối mạng tới
các cổng TCP hoặc UDP trên server mục tiêu và xác định trạng thái của các
cổng
đó (mở, đóng hoặc được lọc). Bằng cách sử dụng socket, người dùng có thể thiết
lập các kết nối mạng và gửi các gói tin đến máy chủ để kiểm tra xem cổng có
sẵn
hay không. Điều này cho phép hacker xác định được thông tin ban đầu của mục
tiêu để khai thác các lỗ hổng và thực hiện tấn công. Bên cạnh đó, lập trình
socket
cũng giúp người quản trị mạng đánh giá được độ an toàn của hệ thống để đưa ra
những giải pháp khắc phục, phòng chống xâm nhập.
1.4. Các thư viện và ngôn ngữ hỗ trợ lập trình Socket
1.4.1. Các ngôn ngữ hỗ trợ lập trình Socket
Lập trình Socket chính là cốt lõi của lập trình mạng, do đó hiện nay có rất nhiều
các ngôn ngữ lập trình phổ biến hỗ trợ lập trình socket, dưới đây là một số ví
dụ:

-C/C++: là ngôn ngữ phổ biến nhất cho lập trình socket. Nó cung cấp hiệu suất
cao và khả năng kiểm soát chi tiết cho các lập trình viên. Các thư viện hỗ trợ lập
trình socket gồm: Thư viện Winsock dành cho hệ điều hành Windows; Thư viện
Berkeley sockets dành cho hệ điều hành Unix/Linux và thư viện Libevent – thư
viện đa nền tảng hỗ trợ nhiều giao thức mạng và các tính năng nâng cao.
-Java: Java là ngôn ngữ lập trình hướng đối tượng phổ biến khác hỗ trợ lập
trình
socket. Java cung cấp khả năng di động cao và dễ sử dụng. Các thư viện hỗ trợ
lập trình socket gồm: java.net.Socket: Cung cấp các lớp cơ bản để tạo kết nối
socket và gửi/nhận dữ liệu; java.nio.channels.SocketChannel: Cung cấp các lớp
hiệu suất cao hơn cho lập trình socket không đồng bộ.
-Go: Go là ngôn ngữ lập trình mới nổi được thiết kế cho hiệu suất cao và khả
năng đồng bộ. Go là lựa chọn tốt cho việc phát triển các ứng dụng socket có yêu
cầu cao.
Thư viện hỗ trợ lập trình socket là net, có chức năng cung cấp các lớp cơ bản để
tạo kết nối socket và gửi/nhận dữ liệu.
-JavaScript: JavaScript được sử dụng chủ yếu cho phát triển web, nhưng nó
cũng
có thể được sử dụng để lập trình socket. Các thư viện hỗ trợ lập trình socket
gồm
WebSocket – cung cấp giao thức cho phép truyền dữ liệu hai chiều giữa máy
chủ
và trình duyệt web và thư viện Socket.IO – thư viện hỗ trợ lập trình socket thời
gian thực cho các ứng dụng web.
-Python: Python là ngôn ngữ lập trình đơn giản và dễ học, phù hợp cho việc
phát
triển các ứng dụng socket đơn giản. Python sử dụng một số thư viện để lập trình
socket như: Thư viện socket – cung cấp các lớp cơ bản để tạo kết nối socket và
gửi/nhận dữ liệu; Asyncore – thư viện hỗ trợ lập trình socket không đồng bộ;
Twisted – Thư viện mạng mạnh mẽ hỗ trợ nhiều giao thức mạng và các tính
năng
nâng cao.
1.4.2. Giới thiệu module socket trong Python
Python cung cấp Module Socket giúp chúng ta dễ dàng thực hiện kết nối
Client/Server để giao tiếp với nhau. Để có thể sử dụng được, trước tiên ta phải
import module Socket vào chương trình:
Tạo một Socket:

Chi tiết tham số:


AF_INET: IPV4
Socket_family:họ địa chỉ AF_INET6: IPV6
AF_UNIX
+ SOCK_STREAM: Dựa trên giao thức TCP, chỉ thực hiện trên 2
tiến trình đã thiết lập kết nối. Giao thức này đảm bảo dữ liệu truyền
đến nơi nhận 1 cách tin cậy và đúng tuần tự. Còn được gọi là socket
Socket Type: cách thiết hướng kết nối.
lập giao thức + SOCK_DGRAM: Dựa trên giao thức UDP, không yêu cầu thiết
lập kết nối. Giao thức này không đảm bảo dữ liệu truyền đến nơi
nhận 1 cách tin cậy và toàn vẹn. Còn được gọi là socket hướng
không kết nối.
Bảng 1.4: Chi tiết tham số của hàm socket()
Một số phương thức được sử dụng trong lập trình Socket với ngôn ngữ Python:

self.node.bind(port_and_ip) Phương thức này nhằm gán địa chỉ IP và Port

Phương thức này node server sẽ lắng nghe kết nối


self.node.listen(5)
đến

self.connection, addr = self.node.accept() Phương thức này thiết lập chấp nhận kết nối

self.connection.send(SMS.encode()) Phương thức này dùng để gửi tin nhắn khi được kết
nối

self.connection.recv(1024).decode() Phương thức này sử dụng để nhận thông báo từ


client trong suốt lúc chương trình hoạt động

Bảng 1.5: Một số phương thức dùng để kết nối và trao đổi thông tin.
Python hỗ trợ thu thập thông tin Server, bao gồm: tên miền, host, địa chỉ IP, …
với một số Module sau đây:

Trả về một chuỗi chứa tên máy chủ của máy mà


gethostname()
trình thông dịch Python hiện đang thực thi.

Dùng để dịch tên máy chủ thành địa chỉ IPv4. Địa chỉ
IPv4 được trả về dưới dạng chuỗi và được lưu vào biến
gethostbyname(hostname)
addr. gethostbyname() không hỗ trợ
IPv6.

Tương tự gethostbyname() nhưng được mở rộng thêm.


Trả về bộ ba: hostname, aliaslist, ipaddrlist, trong đó
hostname là tên máy chủ lưu trữ chính của hostname,
gethostbyname_ex(hostname) aliaslist là danh sách (có thể trống) tên các máy chủ lưu
trữ thay thế cho cùng một địa chỉ và ipaddrlist là danh
sách địa chỉ IPv4.
gethostbyname_ex() không hỗ trợ IPv6.

Tương tự gethostbyname_ex(), tuy nhiên tham số


gethostbyaddr(ip_address)
truyền vào là địa chỉ IPv4.
getfqdn(name) Trả về đầy đủ tên miền nếu nó có sẵn.
Dịch đối số của host/port thành một chuỗi 5 bộ chứa tất
cả các đối số cần thiết để tạo thành một Socket được kết
getaddrinfo(host, port, family=0, nối với dịch vụ đó. Host là tên miền, port là tên chuỗi
type=0, proto=0, flags=0) dịch vụ.
Hàm này sẽ trả về 5 bộ với cấu trúc như sau:
(family, type, proto, canonname, sockaddr).

connect_ex(IP address, port) Trả về giá trị 0 nếu thao tác thành công, ngược lại
sẽ trả về giá trị cho biến errno.

Bảng 1.6: Một số phương thức dùng để thu thập thông tin Server.
CHƯƠNG II – ỨNG DỤNG AN TOÀN SOCKET-PROGRAMING
2.1. Một số nguy cơ bảo mật trong Socket Programing
2.1.1. Thiếu xác thực trong quá trình bắt tay
WebSocket, một giao thức socket phổ biến cho giao tiếp thời gian thực, có một
quá trình bắt tay để thiết lập kết nối. Khác với các yêu cầu HTTP thông thường,
quá trình bắt tay này không bao gồm chức năng xác thực khách hàng. Điều này
có nghĩa là máy chủ không thể xác minh danh tính của khách hàng trong quá
trình kết nối ban đầu. Một số rủi ro tiềm ẩn như:
+ Mạo danh: Người dùng trái phép có thể mạo danh người dùng hợp pháp bằng
cách bắt chước các gói dữ liệu. Điều này có thể dẫn đến truy cập trái phép
hoặc các hành động trái phép.
+ Gian lận dữ liệu: Kẻ tấn công có thể chặn và sửa đổi dữ liệu chảy qua kết nối
socket.
2.1.2. Kênh TCP không được mã hóa
Một vấn đề khác với WebSockets là chúng có thể được sử dụng trên kênh TCP
không được mã hóa. Điều này dẫn đến tất cả các loại vấn đề được liệt kê trong
Top 10 phơi nhiễm dữ liệu nhạy cảm A6 của OWASP. Kênh TCP truyền dữ liệu
dưới dạng văn bản thuần túy, không được mã hóa. Điều này khiến nó dễ bị tấn
công bởi những kẻ nghe lén. Một số tác động mà chúng có thể làm:
+ Đánh cắp dữ liệu nhạy cảm: Thông tin đăng nhập, mật khẩu, dữ liệu tài chính
và các thông tin nhạy cảm khác có thể bị đánh cắp nếu kẻ tấn công có quyền
truy cập vào mạng.
+ Sửa đổi dữ liệu: Kẻ tấn công có thể thay đổi dữ liệu được truyền đi, dẫn đến
các hành động không mong muốn hoặc sai lệch thông tin.
+ Nghe lén giao tiếp: Kẻ tấn công có thể theo dõi toàn bộ nội dung giao tiếp
giữa các ứng dụng sử dụng kênh TCP.
2.2. Các phương pháp bảo mật
2.2.1. Xác thực người dùng
Trong lập trình Socket, việc xác thực người dùng là vô cùng quan trọng, nó
giúp đảm bảo chỉ những người dùng được ủy quyền mới có quyền truy cập tài
nguyên mạng. Qua đó, xác thực người dùng giúp đảm bảo tính toàn vẹn, tính
bảo mật và độ tin cậy của hệ thống.
Quá trình xác thực thường diễn ra như sau:
+ Người dùng kết nối đến máy chủ thông qua socket.
+ Máy chủ yêu cầu người dùng cung cấp thông tin xác thực. (VD: user và
password)
+ Người dùng gửi thông tin xác thực đến máy chủ.
+ Máy chủ kiểm tra thông tin xác thực và quyết định liệu người dùng có được
phép truy cập hay không.
+ Nếu thông tin xác thực là hợp lệ, máy chủ sẽ cho phép kết nối tiếp tục và
cung cấp các dịch vụ được yêu cầu.
Sau đây là một số phương thức xác thực người dùng trong lập trình Socket:
+ Xác thực mật khẩu (Password Authentication): Trong phương pháp này,
người dùng cần cung cấp một cặp tên đăng nhập và mật khẩu để đăng nhập
vào hệ thống. Mật khẩu thường được bảo mật bằng cách sử dụng hàm băm.
Sau đó, máy chủ sẽ kiểm tra xem cặp username và password này có hợp lệ
hay không.
+ Xác thực mã thông báo (Token-based Authentication): Người dùng đăng
nhập bằng cách cung cấp một mã thông báo (token) duy nhất. Mã thông báo
này có thể được tạo ra bằng nhiều cách khác nhau và thường có thời hạn.
(VD: JWT)
+ Xác thực chứng chỉ (Certificate Authentication): Sử dụng chứng chỉ
SSL/TLS để xác thực. Mỗi bên đều có một bộ chứng chỉ, máy chủ sẽ xác
minh xem chứng chỉ của người dùng có được ký bởi một tổ chức uy tín hay
không. Trong python, có thể sử dụng module ssl để thực hiện xác thực theo
cách này.
2.2.2. Giao thức SSL/TLS
Giao thức SSL/TLS là giao thức ở lớp Transport có tầm quan trọng cao nhất
đối với sự bảo mật của các trình ứng dụng trên Web.
SSL: Viết tắt của Security Sockets Layer, SSL là một giao thức mật mã giúp
truyền thông an toàn qua mạng máy tính. SSL được phát triển bởi Netscape,
phiên bản đầu tiên được công bố là SSL 2.0 (năm 1995), sau đó là phiên bản 3.0
(năm 1996). Tuy nhiên do có nhiều lỗ hổng nên không được phát triển nữa và
ngày nay SSL cũng ít được sử dụng hơn TLS.
TLS: Viết tắt của Transport Layer Security, TLS cũng giống như SSL là một
giao thức mật mã giúp truyền thông an toàn. TLS 1.0 được IETF phát triển năm
1999, các phiên bản tiếp theo là TLS 1.1, 1.2, 1.3.

Tóm lại, TLS là phiên bản tiếp theo và cải tiến của SSL, được phát triển để
cung cấp một môi trường bảo mật mạnh mẽ hơn cho việc truyền dữ liệu qua
mạng. Trong khi SSL vẫn tồn tại và được sử dụng trong một số trường hợp, TLS
là lựa chọn ưu tiên cho các ứng dụng và dịch vụ mới.

Trong giao thức SSL/TLS có 4 giao thức con với những chức năng cụ thể:
+ SSL Record: Giao thức này được sử dụng để chia nhỏ dữ liệu thành các
gói tin nhỏ hơn, mã hóa dữ liệu và thêm các thông tin bảo mật như mã băm, chữ
ký số, và khóa phiên trước khi gửi đi.
+ SSL Handshake: Giao thức Handshake được sử dụng để thiết lập kết nối an
toàn giữa máy khách và máy chủ, xác thực các bên và thỏa thuận các thông
tin cần thiết cho việc thiết lập kết nối bảo mật.
+ SSL Change Cipher Spec: Giao thức này được sử dụng để thông báo cho đối
phương biết rằng các thông tin được trao đổi từ bây giờ sẽ được mã hóa bằng
các thuật toán đã thỏa thuận trong giao thức Handshake.
+ SSL Alert: Giao thức này được sử dụng để thông báo về các sự kiện quan
trọng và cảnh báo liên quan đến quá trình trao đổi dữ liệu bảo mật như như
lỗi xác thực, lỗi băm, hoặc lỗi mã hóa,…

Trong 4 giao thức trên, mỗi giao thức đều có tầm quan trọng riêng, nhưng đặc
biệt phải kể đến giao thức SSL Handshake, đây được coi như là cốt lõi của giao
thức SSL.
*Giao thức SSL Handshake
Giao tiếp qua SSL luôn bắt đầu bằng SSL Handshake. Handshake SSL là một
mật mã bất đối xứng cho phép trình duyệt xác minh máy chủ web, lấy khóa
công khai và thiết lập kết nối an toàn trước khi bắt đầu truyền dữ liệu thực tế.
Hình sau minh họa các bước liên quan đến quá trình SSL Handshake:

Hình 2.1: SSL Handshake


*)Phân Tích Quá Trình
− Đầu tiên, máy khách gửi thông báo "client hello". Điều này bao gồm số
phiên bản SSL của máy khách, cài đặt mật mã, dữ liệu theo phiên cụ thể và
thông tin khác mà máy chủ cần giao tiếp với máy khách bằng SSL.
− Máy chủ phản hồi bằng một thông báo "server hello". Bao gồm số
phiên bản SSL của máy chủ, cài đặt mật mã, dữ liệu theo phiên cụ thể, chứng
chỉ SSL có khóa công khai và thông tin khác mà máy khách cần để giao tiếp
với máy chủ qua SSL.
-Máy khách xác minh chứng chỉ SSL của máy chủ từ CA (Certificate
Authority) và xác thực máy chủ. Nếu xác thực không thành công, thì máy
khách từ chối kết nối SSL.)
− Nếu xác thực thành công, Máy khách tạo một session key, mã hóa nó bằng
khóa công khai của máy khác và gửi đến máy chủ. Nếu máy chủ đã yêu cầu
xác thực máy khách (chủ yếu là trong giao tiếp máy chủ với máy chủ), thì
máy khách sẽ gửi chứng chỉ của chính mình đến máy chủ.
− Máy chủ giải mã khóa phiên bằng khóa riêng của nó và gửi xác nhận đến
máy khách được mã hóa bằng khóa phiên.
Do đó, khi kết thúc quá trình bắt tay SSL, cả máy khách và máy chủ đều có
khóa phiên hợp lệ mà họ sẽ sử dụng để mã hóa hoặc giải mã dữ liệu thực tế.
khóa công khai và khóa cá nhân sẽ không được sử dụng nữa sau đó.
*Chứng chỉ SSL/TLS
Chứng chỉ SSL/TLS là là một loại tài liệu số được sử dụng để xác thực
danh tính của một máy chủ hoặc một khóa công khai trong quá trình thiết lập
kết nối an toàn qua mạng Internet sử dụng giao thức SSL/TLS. Chứng chỉ này
chứa các thông tin liên quan đến máy chủ hoặc khóa công khai, bao gồm thông
tin về chủ sở hữu, thông tin về tên miền, khóa công khai, thông tin về cơ quan
chứng thực (CA) và dấu chứng thực.
Khi người dùng truy cập một trang web không có chứng chỉ SSL/TLS, sẽ xuất
hiện thông báo kết nối không an toàn, một số trang sẽ không hiện thông báo,
thay vào đó người dùng có thể nhận biết bằng biểu tượng khóa bên cạnh đường
dẫn của trang web đó.

Đã có chứng chỉ SSL/TLS Chưa có chứng chỉ SSL/TLS

Dĩ nhiên, khi truy cập trang web không có chứng chỉ SSL/TLS, việc cung
cấp thông tin cá nhân username và password trên trang này có nguy cơ bị người
khác bắt gói tin và đọc được nội dung bên trong, từ đó dẫn đến việc lộ các thông
tin nhạy cảm. Nhưng khi truy cập vào https://actvn.edu.vn/ thì người dùng có
thể yên tâm hơn do https là sự kết hợp của giao thức HTTP và giao thức
SSL/TLS, tức là trang web này đã có chứng chỉ SSL/TLS.
Từ những điều trên có thể thấy rằng chứng chỉ SSL/TLS có nhiều tác dụng
quan trọng. Đầu tiên, nó giúp xác thực giữa Client và Server. Ngoài ra nó còn
giúp đảm bảo tính toàn vẹn của dữ liệu bằng cách mã hóa dữ liệu nhằm đảm bảo
tính bí mật, cũng như nén dữ liệu.

.
CHƯƠNG III – THỰC NGHIỆM
3.1. Tổng Quan Mô Hình Xây Dựng Bài Toán
a) Bài toán xác thực người dùng:
Sử dụng ngôn ngữ Python để xây dựng một ứng dụng giao tiếp đơn giản
giữa thực thể là Client và Server. Trước khi muốn giao tiếp, Client phải đăng
nhập thành công bằng tên tài khoản và mật khẩu được lưu trữ ở dạng băm trong
cơ sở dữ liệu. Nếu chưa có tài khoản, Client có thể lựa chọn “Đăng ký” để tạo
tài khoản mới. Tài khoản đó bao gồm tên tài khoản và mật khẩu ở dạng băm,
nhằm tăng tính an toàn đối với các cuộc tấn công vào cơ sở dữ liệu.
b) Bài toán tăng cường tính bảo mật trong quá trình giao tiếp Client – Server :
Sử dụng module socket và ssl để xây dựng giao thức SSL/TLS trong giao
tiếp Client – Server. Client trước khi kết nối sẽ thực hiện xác thực Server qua
chứng chỉ SSL được gửi từ Server. Nếu xác thực thành công, Client sẽ thực hiện
kết nối và bắt đầu quá trình truyền/nhận thông điệp với Server.
3.2. Tiến Hành
3.2.1. Xác thực người dùng trong giao tiếp Client-Server:
*)Server:
Đầu tiên ta cần import vào các module cần thiết:

-Trong đó module sqlite3 là một thư viện cung cấp chức năng truy cập và
thao tác với cơ sở dữ liệu Sqlite
-Module hashlib là một thư viện cung cấp các hàm băm mật mã cho dữ liệu
-Module socket đã được giải thích.

Sau đó, tạo ra một socket, gán địa chỉ và port cho socket đó, rồi chuyển sang
chế độ lắng nghe bằng hàm listen(). Chấp nhận kết nối đến:

Xây dựng hàm có chức năng “Đăng ký”. Khi hàm này được gọi, Client có thể
đăng ký tài khoản mới với username và mật khẩu:

Từ dòng 18 đến 24, sau khi nhập mật khẩu, Client sẽ phải xác nhận lại mật
khẩu, nếu mật khẩu xác nhận không trùng khớp với mật khẩu đặt ban đầu, người
dùng phải nhập lại.
Từ dòng 25 đến 30, khi mật khẩu đã được xác nhận, nó sẽ được băm và thêm
vào cơ sở dữ liệu. Khi quá trình hoàn tất, một thông điệp báo thành công sẽ
được gửi tới Client.
Xây dựng hàm có chức năng “Đăng nhập”. Thông tin username và mật khẩu
được nhận từ Client:

Từ dòng 40 đến 42, mật khẩu sau khi nhận sẽ được băm, sau đó truy vấn trong
cơ sở dữ liệu.
Từ dòng 44 đến 48, kết quả phép truy vấn sẽ được gửi bằng một thông điệp tới
Client.
Cuối cùng, gửi thông điệp gồm 2 lựa chọn đến Client:
Nếu phản hồi của Client là ‘1’ (Log in), kênh chat được tạo ra để Client và
Server giao tiếp tới khi thông điệp Server nhận được là ‘exit’, kênh chat sẽ kết
thúc:

Nếu phản hồi là ‘2’ (Sign up), hàm có chức năng “Đăng ký” được gọi:

*)Client:
Import module socket, sau đó tạo socket và kết nối đến địa chỉ của Server:
Bắt đầu nhận thông điệp từ Server và gửi phản hồi, nếu lựa chọn là ‘1’ (Log
in),người dùng có thể nhập username và mật khẩu, nếu đăng nhập thành công,
kênh chat sẽ được tạo ra

Nếu lựa chọn là ‘2’ (Sign up), người dùng sẽ nhập username mật khẩu mới cho
đến khi hợp lệ và nhận được thông báo ‘Create account successful’
*)Kết Quả:

Client Server

Lúc này, thông tin tài khoản của Client đã được lưu trên cơ sở dữ liệu với mật
khẩu đã được mã hóa theo hàm băm:

Khi người dùng chọn ‘1’ (Log in):


Client Server
3.2.2. Triển khai giao thức SSL/TLS trong giao tiếp Client – Server
a) Các hàm, chức năng chính
* Set Username

- Lưu lại username cũ nếu có trước khi thực hiện set username
- Hiện ra form yêu cầu nhập username:
+/ Lưu username vào file config
+/ Nếu đối tượng là client và đã kết nối thì gửi đi username cũ của user đó
* Set Server IP/Port

- Mở một form để điền thông tin về server, mục đích tuỳ thuộc vào việc đối
tượng là server hay client
+/ Đối với server việc set ip và port để mở kết nối
+/ Đối với client thì đây là bước thiết lập thông tin về server muốn kết nối
- Thông tin về ip và port cũng sẽ được lưu lại để thuận tiện cho những lần kết
nối sau
* Set Password

- Vẫn sẽ tương tự với các thiết lập trên, điểm khác biệt là khi nhập sẽ ẩn các
kí tự nhập vào bằng các dấu *, cũng như không lưu mật khẩu vào file config
để đảm bảo không bị lộ mật khẩu khi bị tấn công
* Start server

- Tạo socket sử dụng giao thức TCP và Ipv4


- Cho phép address có thể được sử dụng ngay lập tức sau khi đóng server
(tránh việc gặp lỗi khi dùng lại address đó)
- Truy vấn DNS tới IP để lấy địa chỉ, gán vào add_info
- Trích xuất IP và Port
- Thực hiên lắng nghe kết nối đến địa chỉ được chỉ định (đoạn trong byte có
thể sẽ sửa thành addr)

- Tạo một context SSL/TLS mới dùng để yêu cầu xác thực từ client
- Load file cert và key được chỉ định
- Chuyển socket thành SSL/TLS ở chế độ server side

- Khởi chạy một luồng (thread) mới để chạy hàm accept_clients:

+/ Tạo một vòng lặp chỉ kết thúc khi đóng kết nối qua biến is_connected
+/ Chờ và chấp nhận một kết nối từ client. Nó trả về một list/tuple chứa 2
giá trị, gán chúng vào conn, addr (conn là socket đại diện cho kết nối thiết
lập với server, addr chứa địa chỉ IP và port của client đã kết nối
+/ Gửi thông báo lên bảng chat là có một client đã kết nối tới server
+/ Tạo một luồng mới để chạy hàm nhận tin nhắn (sẽ được đề cập sau) với
2 tham số là conn và addr
+/ Thiết lập daemon thành True, để khi server đóng thì các luồng con đang
chạy cũng sẽ dừng lại
+/ Bắt đầu chạy luồng
+/ Nếu gặp lỗi sẽ trả về thông báo lỗi và dừng việc chấp nhận kết nối
- Bắt đầu chạy luồng chấp nhận kết nối
- Thông báo rằng Server đã chạy
- Cập nhật tên server vào danh sách người dùng
- Nếu gặp lỗi sẽ trả về thông báo lỗi không thể khởi chạy server
* Stop server

- Nếu đối tượng là server và đang chạy


+/ Duyệt các socket trên list lưu các socket client và thực hiện đóng các
socket đó
- Đóng kết nối của bản thân
- Set các trạng thái về False và xoá dữ liệu trong list clients
- Cập nhật user list về trống
- Gửi lên bảng chat thông báo răng server đã đóng
- Nếu đối tượng không phải server hay không chạy thì sẽ báo lỗi
* Tạo cert (tự động tạo khi start server)

- Khởi tạo biến đại diện cho đường dẫn tới cert và key
- Lấy thông tin về thư mục hiện tại (là thư mục chứa script
- Tạo đường dẫn tới 2 file cert và key, gán cho 2 biến đường dẫn khởi tạo ban
đầu

- Tạo một khoá bí mật với các tham số được chỉ định
+/ Số mũ public (mã hoá công khai)
+/ Kích thước khoá
+/ Sử dụng backend mặc định để tạo key
- Tạo thông tin chủ thể (subject) và đơn vị cấp phát (issuer) cho chứng chỉ
như quốc gia, tình thành, tổ chức,…
- Thiết lập một đối tượng cert (chứng chỉ)
+/ subject_name: Thiết lập thông tin chủ thể của cert
+/ issuer_name: Thiết lập đơn vị cấp phát cert
+/ public_key: Thiết lập public key cho cert
+/ serial_number: Thiết lập số serial (ngẫu nhiên)

+/ not_valid_before: Thiết lập thời gian hiệu lực


+/ not_valid_after: Thiết lập thời gian hết hạn cert
+/ add_extension: Thêm extension cho phép truy cập chứng chỉ qua
localhost
+/ sign: Ký cert bằng khoá bí mật, sử dụng SHA256 và back_end mặc định
- Mở file key ở chế độ ghi nhị phân:
+/ Ghi private key vào file theo định dạng PEM và mã hoá PKCS8
+/ Không sử dụng thuật toán mã hoá để lưu khoá bí mật

- Mở file và ghi nội dung cho file cert bằng định dạng PEM

- Trả về thông báo lỗi tạo khoá thất bại khi gặp lỗi
* Connect Client

- Nếu chưa kết nối:


+/ Thay đổi trạng thái thành đã kết nối
+/ Tạo socket sử đụng giao thức TCP và Ipv4
+/ Kết nối tới server được chỉ định

- Tạo một context SSL/TLS mới, sử dụng các thiết lập mặc định
- check_hostname = FALSE: Bỏ qua kiểm tra tên miền server (chỉ dùng trong
thử nghiệm)
- verify_mode = ssl.CERT_NONE: Bỏ qua việc xác thực chứng chỉ SSL của
server (cũng chỉ dùng trong thử nghiệm)

- Tạo luồng nhận tin nhắn sử


- Gửi username tới server và thực hiện cập nhật lại danh sách user
- Gửi tin nhắn lên khung chat là đã kết nối tới server
* Disconnect Client

- Nếu đối tượng là client và đang kết nối:


+/ Gửi trạng thái disconnect tới server
+/ Đóng socket và đổi trạng thái đã kết nối thành FALSE
+/ Thông báo lên khung chat là đã ngắt kết nối
* Update User List
- Là một chức năng cập nhật danh sách các user đang kết nối tới server
- Trước mắt hàm này sẽ toàn bộ dữ liệu của user list cũ trên giao diện
- Nếu đối tượng là server thì sẽ thêm username của bản thên vào user list, nếu
không thì tiếp tục
- Lần lượt thêm tất cả user lại vào danh sách được cung cấp bởi tham số
user_list
* Broadcast User List

- Đây là một hàm để gửi các cập nhật và danh sách user cho các client đang
kết nối
- Hàm này tạo một biến lưu user list và một đoạn tin nhắn cụ thể, những từ
khoá trong đoạn tin nhắn sẽ dùng để xác định đây là một tin nhắn cập nhật
- Mã hoá tin nhắn này và gửi đi
* Gửi tin nhắn
- Tuỳ vào các hành động cụ thể thì server sẽ gửi đi các tin nhắn định dạng
khác nhau (các thông báo về username mới, một client đã disconnect hay là
một user đổi tên), nếu chỉ là đoạn chat thông thường thì sẽ gửi bằng cách
thông thường
- Nếu là client thì sẽ gửi tin nhắn được mã hoá tới server, còn ngược lại thì
server sẽ gửi tin nhắn tới toàn bộ client
- Trường hợp tin nhắn không thuộc 3 tin nhắn có định dạng để thực hiện các
chức năng thì ra in lên bảng chat, còn không thì sẽ chỉ gửi chứ không in ra
* Nhận tin nhắn

- Trước khi nhận tin, chương trình sẽ kiểm tra xem Client có đang kết nối hay
không bằng hàm kiểm tra socket và kiểm tra data nhận được
- Về hàm kiểm tra socket thì chương trình sẽ gửi đi một đoạn byte rỗng tới kết
nối được chỉ định, nếu gặp lỗi sẽ trả về False và ngược lại
- Sau khi kiểm tra kết nối (giải mã và mã hoá sẽ đề cập sau) thì sẽ đến công
đoạn kiểm tra các từ khoá trong tin nhắn để xác định tin nhắn này thuộc dạng
nào. Nếu chứa “ENCRYPTEDUSERLIST:” thì chương trình sẽ tạo user list
dựa trên tin nhắn gửi tới và cập nhật lại user list hiện tại

- Nếu bắt đầu bằng USERNAME:


+/ Lấy thông tin của username đó
+/ Nếu là server thì update và broadcast userlist. Ngoài ra còn gửi thêm
một tin nhắn bắt đầu bằng SERVERUSERNAME:
+/ Nếu là client thì chỉ đơn giản là update user list thôi

- Nếu bắt đầu bằng SERVERUSERNAME:


+/ Lấy tên server
+/ Lấy danh sách user
+/ Nếu tên server không có trong danh sách user thì thêm vào

- Nếu bắt đầu bằng USERNAMECHANGE:


+/ Lấy ra username cũ và mới
+/ Nếu là server thì sẽ thay thế vị username mới dánh list clients thay
username cũ, đồng thời update và broadcast danh sách user mới đi

- Bắt đầu bằng DISCONNECT:


+/ Lấy tên username đã ngắt kết nối
+/ Nếu là server thì sẽ xoá username đó khỏi list clients, đồng thời đóng kết
nối và cập nhật lại user list
- Còn lại nếu không có bất kì từ khoá nào thì sẽ chỉ đơn giản là gửi tin nhắn đi
và hiện trên khung chat
- Kiểm tra cái lỗi trả về khi gửi đi mật khẩu để xác thực, client chỉ được phép
nhập sai 3 lần. Sau 3 lần nhập sai, kết nối sẽ đóng lại
* Mã hoá tin nhắn
Ngoài việc mã hoá tin nhắn gửi đi qua SSL/TLS, chương trình này còn kết hợp
thêm thuật toán mã hoá khác để tăng cường bảo mật

- Tạo khoá dẫn xuất sử dụng hàm tạo khoá dựa trên mật khẩu (PBKDF2), kết
hợp hàm băm sha256 (trước đó password được encode sang dạng byte) với
100000 lần lặp
- Salt được dùng để nối vào mật khẩu nhằm chống các cuộc tấn công
Dictionary hay Rainbow Attack
- Hàm trả về một khoá có độ dài được chỉ định bởi KEY_SIZE
- Trước hết hàm mã hoá này sẽ kiểm tra tin nhắn có ở dạng byte không, nếu
không thì sẽ chuyển nó về dạng byte
- Thiết lập mã hoá: Khởi tạo đối tượng AES sử sụng key và chế độ EAX
- Mã hoá tin nhắn thành bản mã cũng như tạo một tag (mã xác thực)
- Trả về 3 giá trị là nonce (một số ngẫu nhiên sử dụng một lần cho mã hoá
nhằm ngăn chặn Replay Attack, bản mã và tag. Dưới đây sẽ nói chi tiết về mã
hoá tin nhắn sử dụng 3 thành phần này

- salt sẽ được tạo ngẫu nhiên và có kích thước được chỉ định
- key được tạo bằng hàm dẫn xuất khoá đã đề cập trước đó
- Mã hoá tin nhắn sử dụng key -> gấn cho encrypted_data
- encrypted_data khi đó là một mảng chứa 3 giá trị nonce, ciphertext, tag, tách
chúng thành các xâu để nối với nhau cũng nhau nối với salt -> gán vào
encrypted_message
- Cuối cùng thì dùng base64 để mã hoá encrypted message -> gán vào
encrypted_messagem, đây sẽ là bản mã cuối cùng để truyền đi
* Giải mã tin nhắn

- Tham số đầu vào của hàm giải mã có encrypted_data – là mảng gòm 3 giá
trị nonce, ciphertext, tag
- Khởi tạo đối tượng AES sử dụng key, nonce lấy từ encrypted_data, chế độ
EAX
- Bản rõ sẽ được lấy từ hàm decrypt_and_verify bằng cách cung cấp bản mã
và tag, cuối cùng decode để chuyển từ dạng byte sang dạng thường
b) Thực nghiệm trên giao diện UI
* Phía server
- Chương trình sẽ không chia thành 2 file để phân biệt client và server như thông
thường mà kết hợp thành một ứng dụng duy nhất
- Giao diện chỉnh (gồm thanh menu, khung hiển thị chat, khung nhập tin nhắn,
khung hiển thị danh sách user, nút gửi tin nhắn)

- Phía server: sử dụng menu Settings để thiết lập Server name, Server IP/Port,
Password chung để kết nối
- Start Server: Khởi chạy server đồng thời tạo cert/key tại chính thư mục cuẩ
chương trình, server sẽ tự động lấy file cert và key ở thư mục ứng dụng để bọc
socket bằng một lớp bảo mật SSL/TLS. Nếu khởi chạy thành động. Lưu ý: Nếu
chưa có cert thì khi khởi chạy sẽ có thông báo lỗi không tìm được file cert/key

* Phía client
- Thực hiện các bước thiết lập thông tin tương tự phía client, đảm bảo các thông
tin quan trọng như IP/Port và Password được thiết lập tương ứng với server để
kết nối được triển khai
- Client – Connect: Thực hiện gửi yêu cầu kết nối tới server, server sẽ gửi cert
cho client. Thiết lập của client là không xác minh tính hợp lệ của chứng chỉ hay
kiểm tra tên miền nhưng trên thực tế thì việc thiết lập như vậy có thể dẫn tới
những rủi ro bảo mật (như Man-in-the-middle Attack). Ngoài lớp mã hoá được
tạo bởi giao thức SSL/TLS ra ứng dụng còn bổ sung thêm thuật toán mã hoá đã
được đề cập ở phần trước để tăng tính bảo mật cho tin nhắn

- Đây là gói tin biểu thi tương tác giữa client và server khi Client yêu cầu kết
nối:
+/ Client Hello: Client gửi lời chào tới server, gói tin này chứa các thông tin
như phiên bản TLS và bộ mã hoá mà client hỗ trợ, một số ngẫu nhiên và
extension (phần mở rộng
+/ Server Hello: Server chào lại Client. Gói tin chứa phiên bản TLS và bộ mã
hoá mà server sẽ chọn, số ngâu nhiên, extension và chứng chỉ (cert) của
server
+/ Change Cipher Spec: Thông báo cho server/client sắp sử dụng bộ mã hoá
cipher suite đã thoả thuận để mã hoá và giải mã tin nhắn
+/ Application Data: Client/Server gửi tin nhắn Application Data tới đối
phương, chứa tin nhắn/dữ liệu được mã hoá cần gửi đi
- Có thể ngắt kết nối tới server hay thậm chí dừng server bằng các tuỳ chọn
trong menu, tránh việc chỉ tắt bằng nút close của cửa sổ bởi đôi khi sẽ gặp lỗi
TÀI LIỆU THAM KHẢO
[1] https://vnpro.vn/thu-vien/tong-quan-ve-giao-thuc-ssl-tls-4024.html
[2] https://realpython.com/python-sockets/
[3] https://www.freecodecamp.org/news/socket-programming-in-python/
[4] https://www.ibm.com/docs/en/i/7.4?topic=network-client-security-in-tcpip
[5] https://snyk.io/blog/implementing-tls-ssl-python/
[6] https://github.com/vuongwyen/chat-app-using-SSL-TLS

You might also like