Create a new file, write the following, and save it as a socket.py file. Put it in the folder where Ssserver.exe is located
#!/usr/bin/python
#-*-Coding:utf-8-*-
#
# Copyright Falseen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# You are not a use of this file except in compliance with the License.
# Obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# unless required by applicable or agreed to writing, software
# Distributed under the License is distributed on a "as is" BASIS,
# without warranties or CONDITIONS of any KIND, either express or implied.
# See the License for the specific language governing permissions and
# Limitations under the License.
#
#
# function: Limit the number of clients (based on IP judgment)
#
# Instructions for use: 1. Place this file in the SS root directory to take effect without additional setup (requires re-running SS).
# 2. Modify the Clean_time and ip_numbers of lines 53 and 54 to the number you want.
# 3. If your server has IPv6 and you want to restrict IP4 and IP6 separately, you can set the Only_port to False.
#
#
# principle: By default, the SS will refer to the socket file in the system when it is run, but after placing the socket file in the SS directory, the SS will refer to our custom socket file.
# then in this file again refer to the real socket package, and on the basis of the original socket to modify, the final SS call is through our modified socket file.
#
# so theoretically any Python program that references a socket package can use this file to limit the number of connected IPs.
#
From __future__ import absolute_import, Division, print_function, \
With_statement, Nested_scopes
Import Sys
Del sys.modules[' socket ']
Import Sys
Import time
Import logging
Import types
Path = Sys.path[0]
Sys.path.pop (0)
Import Socket # Importing a real socket package
Sys.path.insert (0, path)
Clean_time = 60 # Sets the time interval for cleaning up the IP, where no connected IP will be cleaned
Ip_numbers = 1 # Set the number of allowed IPs per port, that is, set the number of client ips
Only_port = true # Sets whether to determine only the port. If true, only the port is determined. If False, it is strictly judged on the ip+ port.
# Dynamic Path class method
Def re_class_method (_class, Method_name, Re_method):
method = GetAttr (_class, method_name)
info = sys.version_info
if info[0] >= 3:
& nbsp; setattr (_class, method_name,
types. Methodtype (Lambda *args, **kwds:re_method (method, *args, **kwds), _class))
else:
setattr (_class, method_name,
types. Methodtype (Lambda *args, **kwds:re_method (method, *args, **kwds), None, _class))
# Dynamic Path instance method
def re_self_method (self, Method_name, Re_method):
method = GetAttr (self, method_name)
SetAttr (self, method_name, types. Methodtype (Lambda *args, **kwds:re_method (method, *args, **kwds), Self, self))
# Processing TCP connections
def re_accept (Old_method, Self, *args, **kwds):
While True:
Return_value = Old_method (self, *args, **kwds)
Self_socket = return_value[0]
If Only_port:
Server_ip_port = '%s '% self.getsockname () [1]
Else
Server_ip_port = '%s_%s '% (self.getsockname () [0], Self.getsockname () [1])
CLIENT_IP = return_value[1][0]
Client_ip_list = [X[0].split (' # ') [0] for x in Self._list_client_ip[server_ip_port]]
If Len (self._list_client_ip[server_ip_port]) = = 0:
Logging.debug ("[Re_socket] first add%s"% client_ip)
Self._list_client_ip[server_ip_port].append (['%s#%s '% (Client_ip, Time.time ()), Self_socket])
Return Return_value
if client_ip in client_ip_list:
logging.debug ("[Re_socket] update socket in%s"% client_ip)
_ip_index = Client_ip_list.index (client_ip)
Self._list_client_ip[server_ip_port][_ip_index][0] = '%s#%s '% (Client_ip, Time.time ())
self._ List_client_ip[server_ip_port][_ip_index].append (self_socket)
return Return_value
Else:
If Len (Self._list_client_ip[server_ip_port]) < ip_numbers:
logging.debug ("[Re_socket] Add%s"% client_ip)
self._list_client_ip[ Server_ip_port].append (['%s#%s '% (Client_ip, Time.time ()), Self_socket])
return Return_value
For x in [x for X in Self._list_client_ip[server_ip_port]]:
is_closed = True
If Time.time ()-Float (X[0].split (' # ') [1]) > Clean_time:
For y in X[1:]:
Try
Y.getpeername () # To determine if the connection is closed
is_closed = False
Break
Except: # If an exception is thrown, the connection is closed and the socket can be closed
Logging.debug ("[Re_socket] Close and remove the time out socket 1/%s"% (Len (x[1:]))
X.remove (y)
if not is_closed:
logging.debug (' [Re_socket] the%s still exists and Update Last_time '% str (x[1].getpeername () [0])
_ip_index = Client_ip_list.index (x [0].split (' # ') [0])
self._list_client_ip[server_ip_port][_ip_index][0] = '%s#% S '% (X[0].split (' # ') [0], Time.time ())
Else:
logging.info ("[Re_socket] Remove Time Out IP and add new IP%s"% c LIENT_IP)
self._list_client_ip[server_ip_port].remove (x)
self._list_client_ip[server_ip_port].append (['%s#%s '% (Client_ip, Time.time ()), Self_socket])
return Return_value
if Int (time.time ())% 5 = = 0:
Logging.debug ("[Re_socket] the port%s client more then the%s"% (Server_ip_port, ip_numbers))
# Handling UDP connections
def re_recvfrom (Old_method, Self, *args, **kwds):
while True:
return_value = Old_method (*args, * * Kwds)
self_socket = '
If Only_port:
server_ip_port = '%s '% Self.getsockname () [1]
else:
server_ip_port = '%s_%s '% (self.getsockname () [0], Self.getsockname () [1])
client_ip = return_value[1][0]
Client_ip_list = [X[0].split (' # ') [0] for x in Self._list_client_ip[server_ip_port]]
If Len (self._list_client_ip[server_ip_port]) = = 0:
Logging.debug ("[Re_socket] first add%s"% client_ip)
Self._list_client_ip[server_ip_port].append (['%s#%s '% (Client_ip, Time.time ()), Self_socket])
Return Return_value
If client_ip in Client_ip_list:
Logging.debug ("[Re_socket] update socket in%s"% client_ip)
_ip_index = Client_ip_list.index (CLIENT_IP)
Self._list_client_ip[server_ip_port][_ip_index][0] = '%s#%s '% (Client_ip, time.time ())
Return Return_value
Else
If Len (Self._list_client_ip[server_ip_port]) < ip_numbers:
Logging.debug ("[Re_socket] Add%s"% client_ip)
Self._list_client_ip[server_ip_port].append (['%s#%s '% (Client_ip, Time.time ()), Self_socket])
Return Return_value
For x in [x for X in Self._list_client_ip[server_ip_port]]:
is_closed = True
If Time.time ()-Float (X[0].split (' # ') [1]) > Clean_time:
For y in X[1:]:
Try
Y.getpeername () # To determine if the connection is closed
is_closed = False
Break
Except: # If an exception is thrown, the connection is closed and the socket can be closed
Logging.debug ("[Re_socket] Close and remove the time out socket 1/%s"% (Len (x[1:]))
X.remove (y)
if not is_closed:
logging.debug (' [Re_socket] the%s still exists and Update Last_time '% str (x[1].getpeername () [0])
_ip_index = Client_ip_list.index (x [0].split (' # ') [0])
self._list_client_ip[server_ip_port][_ip_index][0] = '%s#% S '% (X[0].split (' # ') [0], Time.time ())
Else:
logging.info ("[Re_socket] Remove Time Out IP and add new IP%s"% c LIENT_IP)
self._list_client_ip[server_ip_port].remove (x)
self._list_client_ip[server_ip_port].append (['%s#%s '% (Client_ip, Time.time ()), Self_socket])
return Return_value
if Int (time.time ())% 5 = = 0:
Logging.debug ("[Re_socket] the port%s client more then the%s"% (Server_ip_port, ip_numbers))
New_tuple = [B ', return_value[1]]
Return_value = tuple (new_tuple)
Return Return_value
def re_bind (Old_method, Self, *args, **kwds):
If Only_port:
Port = '%s '% args[0][1]
Else
Port = '%s_%s '% (args[0][0], args[0][1])
Self._list_client_ip[port] = []
Re_self_method (self, ' recvfrom ', Re_recvfrom)
Old_method (self, *args, **kwds)
SetAttr (Socket.socket, ' _list_client_ip ', {})
Re_class_method (Socket.socket, ' bind ', re_bind)
Re_class_method (Socket.socket, ' accept ', re_accept)
Python build Ssserver limit port connection number