I am wondering how I would make a whitelist, or a list of allowed IPs. There is someone trying to join my server, and he uses a VPN to hide his IP and change it. Please help me, it’s shutting down my server every time he does this.
My code is:
import socket
import threading
class ChatServer:
clients_list = []
last_received_message = ""
def __init__(self):
self.server_socket = None
self.create_listening_server()
def create_listening_server(self):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
local_ip = '127.0.0.1'
local_port = 10319
# this will allow you to immediately restart a TCP server
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# this makes the server listen to requests coming from other computers on the network
self.server_socket.bind((local_ip, local_port))
print("Listening for incoming messages..")
self.server_socket.listen(5)
self.receive_messages_in_a_new_thread()
def receive_messages(self, so):
while True:
incoming_buffer = so.recv(256)
if not incoming_buffer:
break
self.last_received_message = incoming_buffer.decode('utf-8')
self.broadcast_to_all_clients(so) # send to all clients
so.close()
def broadcast_to_all_clients(self, senders_socket):
for client in self.clients_list:
socket, (ip, port) = client
if socket is not senders_socket:
socket.sendall(self.last_received_message.encode('utf-8'))
def receive_messages_in_a_new_thread(self):
while True:
client = so, (ip, port) = self.server_socket.accept()
self.add_to_clients_list(client)
print('Connected to ', ip, ':', str(port))
t = threading.Thread(target=self.receive_messages, args=(so,))
t.start()
def add_to_clients_list(self, client):
if client not in self.clients_list:
self.clients_list.append(client)
if __name__ == "__main__":
ChatServer()
In receive_messages_in_a_new_thread(self), I am getting an IP of the client. I tried using:
whitelist = [“client-ip”, “client-ip”]
if ip not in whitelist:
so.close()
else:
pass
But it still lets other IPs in. I even tried a blacklist:
blacklist = [“client-ip”, “client-ip”]
if ip in blacklist:
so.close()
else:
pass
What am I missing? Is there another thing that I should know about?
Related
Problem while making connection with server.
server side:
import socket
import threading
import sys
ip = "let ip address of server, cant type real one for security purposes, example: 1.2.3.4"
port = 9999
def make_socket(ip, port):
global server
try:
server = socket.socket()
server.bind((ip, port))
except:
make_socket(ip, port)
def handle_client(conn, addr):
print(f"Connected with {addr}\n")
connected = True
while connected:
msg = conn.recv(1024).decode("utf-8")
if msg == "exit()":
connected = False
if len(msg) > 0:
print(f"CLIENT: {msg}")
if connected:
msg = input("You: ")
if len(msg) > 0:
conn.send(msg.encode("utf-8"))
conn.close()
def make_connection():
server.listen(2)
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"ACTIVE CONNECTIONS:{threading.activeCount() - 1}")
print("SERVER INITIATED.")
make_socket(ip, port)
make_connection()
client side:
import socket
ip = "same address as written in server side, example: 1.2.3.4"
port = 9999
client = socket.socket()
client.connect((ip, port))
def send(msg):
message = msg.encode("utf-8")
client.send(message)
run = True
while run:
msg = input("You: ")
if msg == "exit()":
send(msg)
run = False
else:
send(msg)
print(f"Server: {client.recv(100).decode('utf-8')}")
It runs as expected in the same pc.
But when I am running client script and server script in 2 different pcs, they are not connecting. Even though the address is same. I have to type the ip address of server in server.bind and client.connect, right? They both should be same, right?
The IP address you pass to client.connect() should be the IP address of the computer where the server is running (if it's the same computer as where the client is running, you can just pass 127.0.0.1 as that address always means localhost). For the bind() call I recommend passing in '' (i.e. an empty string) as the address, so that your server will accept incoming connections from any active network interface. You only need to pass in an explicit IP address to bind() if you want limit incoming connections to only those coming through the local network card that is associated with the specified IP address.
I have made a multithreaded Python socket server.
It supports multiple socket client connections.
My code is:
import socket
from _thread import *
def multi_threaded_client(connection):
response = ''
while True:
data = connection.recv(10000000)
response += data.decode('utf-8')
if not data:
print(response)
break
connection.send(bytes(some_function_name(response), "utf-8"))
connection.close()
class socketserver:
def __init__(self, address='', port=9090):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.address = address
self.port = port
self.sock.bind((self.address, self.port))
self.cummdata = ''
def recvmsg(self):
self.sock.listen(65535)
self.conn, self.addr = self.sock.accept()
print('connected to', self.addr)
self.cummdata = ''
start_new_thread(multi_threaded_client, (self.conn, ))
return self.cummdata
def __del__(self):
self.sock.close()
serv = socketserver('127.0.0.1', 9090)
print('Socket Created at {}. Waiting for client..'.format(serv.sock.getsockname()))
while True:
msg = serv.recvmsg()
I also want the server to detect if any new client is connected to /disconnected from it.
Once all the clients are disconnected from it, I want the server to be closed on its own.
I could not figure this out
(I have the following code in which I would like to implement a server-side application and to send clients a response:
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
request = ''
while 1:
data = self.sock.recv(1024).decode() # The program hangs here with large message
if not data:
break
request += data
print(request, self.addr[1], self.addr[0]))
message = "test"
self.sock.send(message.encode())
def init_server():
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((host, int(port)))
serversocket.listen(5)
while 1:
clients, address = serversocket.accept()
client(clients, address)
return
Now I write a simple client:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 8000))
client_socket.send(message)
request = ''
while 1:
data = client_socket.recv(2048).decode()
if not data:
break
request += data
print(request)
client_socket.close()
The problem now is that the server hangs in recv with a large message. How can I solve it?
Your client socket and server socket are different sockets.
You can get server info using the serversocket object the same way you try self.sock.
I would recommend parsing serversocket as a third argument into your client class, and then using it within the class like so:
class client(Thread):
def __init__(self, socket, address, server):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.server = server
self.start()
def run(self):
request=''
while 1:
data=self.sock.recv(1024).decode()
if not data:
break
request+=data
print(request, self.server.getsockname()[1], self.server.getsockname()[0]))
def init_server():
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((host, int(port)))
serversocket.listen(5)
while 1:
clients, address = serversocket.accept()
client(clients, address, serversocket)
return
That should output the server information.
If you wanted the client information, it's parsed in the 'address' as a tuple, you can see the remote IP address and the socket port used to communicate on (not the open port).
Having a small problem with a multithreaded socket server in Python 3. I can't seem to start my socket listening in its own thread. I'm probably way off base.
Borrowed the code here: How to make a simple multithreaded socket server in Python that remembers clients
But I need to listen for clients within a thread or at least in the background. Can't figure out what I'm doing wrong.
Here's my code:
import socket
from threading import Thread
from cmd import Cmd
class ThreadedServer(Thread):
def __init__(self):
self.host = "127.0.0.1"
self.port = int(8080)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
def listen(self):
self.sock.listen(5)
print("[Info]: Listening for connections on {0}, port {1}".format(self.host,self.port))
while True:
print("Hello?") # Just debug for now
client, address = self.sock.accept()
client.settimeout(60)
threading.Thread(target = self.listenToClient,args = (client,address)).start()
def listenToClient(self, client, address):
size = 1024
while True:
try:
data = client.recv(size)
if data:
# Set the response to echo back the recieved data
response = data
client.send(response)
else:
raise error('Client disconnected')
except:
client.close()
return False
class CommandInput(Cmd):
# Able to accept user input here but is irrelevant right now
pass
print("[Info]: Loading complete.")
clientThread = ThreadedServer().listen()
clientThread.start()
print("[Info]: Server ready!")
prompt = CommandInput()
prompt.prompt = '> '
prompt.cmdloop("[Info]: Type \'help\' for a list of commands and their descriptions/use")
As you can see I have some code after my listening part where I need to be able to accept input on the terminal. However, the code never gets there.
Here's the output quite simply:
[Info]: Loading complete.
[Info]: Listening for connections on 127.0.0.1, port 8080
Hello?
I'm expecting:
[Info]: Loading complete.
[Info]: Listening for connections on 127.0.0.1, port 8080
Hello?
[Info]: Type \'help\' for a list of commands and their descriptions/use
>
with a cursor ready for me to type.
So how can I properly get my program to listen for clients in that loop in a proper thread so that I can enter prompts at the command line and process user input (for example one of the commands I want to implement is that of a client "send" which I would be able to send debug information to connected clients)
Thanks for any assistance you can provide.
This may not be the ideal structure for setting up what you want, but seems to solve the requirement you stated.
After launching this script on a terminal, you can make sample client connections by opening one, or more, browser tabs to localhost:8080
import socket
from threading import Thread
from cmd import Cmd
# basic threading tutorial: https://www.tutorialspoint.com/python3/python_multithreading.htm
class ThreadedServer(Thread):
def __init__(self):
Thread.__init__(self) # change here
self.host = "127.0.0.1"
self.port = int(8080)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
def run(self): # change here
self.sock.listen(5)
print("[Info]: Listening for connections on {0}, port {1}".format(self.host,self.port))
while True:
print("Hello?") # Just debug for now
client, address = self.sock.accept()
client.settimeout(60)
Thread(target = self.listenToClient, args = (client,address)).start() # change here
def listenToClient(self, client, address):
size = 1024
while True:
try:
data = client.recv(size)
if data:
# Set the response to echo back the recieved data
response = data
client.send(response)
else:
raise error('Client disconnected')
except:
client.close()
return False
class CommandInput(Cmd):
# Able to accept user input here but is irrelevant right now
pass
if __name__ == "__main__":
print("[Info]: Loading complete.")
server = ThreadedServer() # change here
server.start() # change here
print("[Info]: Server ready!")
prompt = CommandInput()
prompt.prompt = '> '
prompt.cmdloop("[Info]: Type \'help\' for a list of commands and their descriptions/use")
I am trying to send a TCP message at random time, depending on when the user input is received, to one of several clients from which I am receiving data on a thread for each client.
I am storing the IP of each client inside an SQL database and I decide to which IP i want to send data based on user input. How should I approach sending a message to a specific client ? I don't know how I can gain access over each socket connection and use it to send messages.
Any device, links of examples, or code snippets are greatly welcome.
This is the server code that I have so far :
import socket
import threading
from database import Database
d = Database()
def Read_RFID_tag():
while True:
receiveID = raw_input("tag input : ")
d.updateTable(receiveID, 1);
print(receiveID)
class ThreadedServer(object):
def __init__(self, host, port):
self.host = host
self.port = port
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
def listen(self):
self.sock.listen(5)
while True:
client, address = self.sock.accept()
print("new client")
client.settimeout(60)
threading.Thread(target = self.listenToClient,args = (client,address)).start()
def listenToClient(self, client, address):
size = 1024
while True:
query_result = d.existsWashedInTable(address)
try:
data = client.recv(size)
if data:
# Set the response to echo back the received data
print(data)
response = data
d.addEntryToTable(response,address, 0)
client.send(response)
else:
raise error('Client disconnected')
except:
client.close()
return False
if __name__ == "__main__":
port_num = 5005
d.createTable()
threading.Thread(target=Read_RFID_tag).start()
ThreadedServer('',port_num).listen()