Exploring Cybersecurity: Building a Secure TCP Chat Server in Python
Introduction:
In my ongoing cybersecurity discovery through hands-on projects, I've been delving into fundamental concepts of security to deepen my understanding and enhance my skills. So far, I have created a basic TCP and UPD server. Let's now dive further into the world of network security by building a TCP chat server in Python. My goal is to not only create a functional chat server but also to gradually fortify it with advanced security measures, transforming it into a secure communication platform.
Conception:
This project began with laying the groundwork for our chat server. I started by implementing a basic server-client architecture where multiple clients could connect to the server and exchange messages.
The Code:
Let's take a closer look at the code for our TCP chat server:
server.py
#!/usr/bin/python3
import socket
import threading
clients = []
addresses = {}
# Handle client connections
def handle_client(client_socket, client_address):
# Add client to list
clients.append(client_socket)
# Receive and broadcast msgs
while True:
try:
message = client_socket.recv(1024).decode('utf-8')
if message:
broadcast(message, client_socket)
else:
print(f"Client {client_address} disconnected.")
break
except Exception as e:
print(f"Error: {e}")
client_socket.close()
clients.remove(client_socket)
print(f"Client {client_address} disconnected.")
break
# Broadcast messages to all clients
def broadcast(message, sender_socket):
for client_socket in clients:
if client_socket != sender_socket:
try:
client_socket.send(message.encode('utf-8'))
except Exception as e:
print(f"Error: {e}")
client_socket.close()
clients.remove(client_socket)
def main():
try:
# Set up server as a socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 8010))
server_socket.listen(5)
print("Chat server started...")
# Accept client connections
while True:
if server_socket._closed:
break
client_socket, client_address = server_socket.accept()
print(f"Connection from {client_address}")
client_handler = threading.Thread(target=handle_client, args=(client_socket, client_address))
client_handler.start()
except KeyboardInterrupt:
print("\nServer shutting down...")
for client_socket in clients:
client_socket.close()
server_socket.close()
if __name__ == "__main__":
main()
- - The server code sets up a TCP socket using
socket.socket()
withAF_INET
family for communicating over the internet using IPv4 addresses andSOCK_STREAM
type to create a stream socket which is used for TCP. - - It binds the socket to the localhost ('127.0.0.1') on port 8010 using
server_socket.bind()
. - - The server listens for up to five incoming connections using
server_socket.listen(5)
. - - In the
handle_client
function, each connected client is added to a list of clients. - - Messages from clients are received in a loop with
client_socket.recv()
. - - Received messages are broadcasted to all other connected clients using the
broadcast
function. - - A separate thread is created for each client using
threading
. This allows clients to not have to take turns when performing operations. - - The
main()
function continuously accepts incoming connections.
Additionally, we have client scripts that allow users to connect to the server and exchange messages. Here is the client code:
client1.py
#!/etc/bin/python3
import socket
import threading
# Receive message from server
def receive_messages(client_socket):
try:
while True:
message = client_socket.recv(1024).decode('utf-8')
print("\r" + message + "\n > ", end="", flush=True)
except Exception as e:
print(f"Error: {e}")
finally:
client_socket.close()
def main():
try:
# Connect to server
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('127.0.0.1', 8010))
# Receive messages in thread
receive_thread = threading.Thread(target=receive_messages, args=(client_socket,))
receive_thread.start()
# Send messages to server
while True:
message = input(" > ")
client_socket.send(message.encode('utf-8'))
except KeyboardInterrupt:
print("\nClient shutting down, press ctrl + c to close...")
client_socket.close()
try:
receive_thread.join()
except KeyboardInterrupt:
print("\nClient closed")
pass
if __name__ == "__main__":
main()
- - The client code also sets up a TCP socket using
socket.socket()
withAF_INET
family andSOCK_STREAM
type. - - It connects to the server at localhost ('127.0.0.1') on port 8010 using
client_socket.connect()
. - - A separate thread is created to receive messages from the server continuously in the
receive_messages
function. - - Messages received from the server are printed to the console.
- - The main thread continuously prompts the user for input and sends messages to the server using
client_socket.send()
.
TCP Chat Server Code
Example Run:
Let's walk through a sample interaction between the server and clients. For the sake of this example, I have two separate client files with the same contents called client1.py and client2.py:
# Example run from server perspective:
Chat server started...
Connection from ('127.0.0.1', 51072)
Connection from ('127.0.0.1', 51082)
# Example run from client1 perspective:
> Hello from client 1.
Hello from client 2!
>
# Example run from client2 perspective:
Hello from client 1.
> Hello from client 2!
>
Future Plans:
While our chat server currently allows communication between clients, it lacks robust security measures. Moving forward, we aim to address this by:
- Exploring Message Interception: Investigating potential vulnerabilities and methods of discreetly intercepting messages from an attacker's perspective.
- Implementing Encryption: Integrating encryption mechanisms such as SSL/TLS to ensure confidentiality.
- Establishing Secure Chat Rooms: Creating secure chat rooms with authentication and authorization mechanisms.
- Continuously Improving Security: Iteratively enhancing our chat server to stay ahead of emerging threats and vulnerabilities.
Conclusion:
As I continue to learn and experiment, I'm excited to share progress and insights. Stay tuned for future blog posts where I will delve deeper into each aspect of securing our TCP chat server. Together, let's continue on this journey towards building a robust and secure communication platform, developing and learning about future security-related projects, and learning as much about the fundamentals of cybersecurity as we can. Happy coding!