Packet - Networking library

Update 1.1

Fixed vulnerability that allows client to resume a thread if that thread is yielded after a fire()

2 Likes

Nice writeup about some vulns which might help.

Thanks for reporting about the thread problem that is hopefully fixed in Verison 1.1 now


but Iā€™m not seeing a problem with the buffer overflow issue

when I send a string I get this error

game.ReplicatedStorage.Packet.RemoteEvent:FireServer(string.rep(" ", 1e3))

and

game.ReplicatedStorage.Packet.RemoteEvent:FireServer(buffer.create(7999))

will only work once per server heartbeat because its within the data limit and as long as its a valid buffer it will be read by the server

They are more minor but exploiters can be annoying by spamming error report with them and for me anyway i noticed a 15fps drop on the server when sending buffer.create(7999) and this error being spammed which seems to a setup issue


Not sure if youā€™re talking about spamming it many times because OnServerEvent is coroutined if Iā€™m not mistaken.

I had this same issue with another networking module when I was benchmarking to compare to my networking module I released.

I also noticed when testing ur module that it caused me to get 300 ping firing the server and significant frame drops

Oh ok I see what your talking about if there are any error messages in any case then it will slow the server down because printing is expensive

I think the best way to stop the overflow error would be to use pcall vs checking the size every time we read a type

and for the OnServerInvoke not found for error message maybe i should just show this error if your in studio or just remove it all together

and maybe remove the Response thread not found for packet warning as well

Iā€™d just do

if type(receivedBuffer) ~= "buffer" then
	return print("bruh")
end

Same for instances

right but this would not detect if there is a overflow

I had a good method for overflows in a old buffer lib Iā€™ll have a look for it to see what I did
Should probably continue in private messages to not flood your post

Ok but because the Any type is dynamic we would not be able to pre determine the full size of the buffer we would only be able to work it out while reading and I feel that using a pcall would be more efficient then checking the length before every read so i think the best option is pcall

but its getting late here so ill sleep on it and see how i feel in the morning about it with fresh eyes

Yeah pcall is fine just the overhead though

lets say you send a string Hello that has 5 characters the way it will look is

14 bytes for the remote event fire
2 bytes for the buffer
1 byte for the string length
5 bytes for the 5 characters in Hello

but if you send 2 strings Hello and Bye then it will be

14 bytes for the remote event fire
2 bytes for the buffer
1 byte for the Hello string length
5 bytes for the 5 characters in Hello
1 byte for the Bye string length
3 bytes for the 3 characters in Bye

but in short if your only sending a few packets here and there then using any network library is not really something you should do

but once you start to send more then 2 remote events per frame thatā€™s when a network library will start to be a more valid option

1 Like

Thanks for your nice message

I guess this is personal preference but to me

Packet("Name", Packet.Any :: string | number)

looks nicer and feels more elegant but maybe thatā€™s just me

another option is also

local Mix = Packet.Any :: string | number
local packet = Packet("Name", Mix)

but I donā€™t know I donā€™t really like this as well :stuck_out_tongue:

Incredible library suphi. Well done!

Thank you suphi for this great module. Please add a project thread of this module in the Roblox OSS community! It would be great to have a live discussion on the module

Neat library, I particularly like the ResponseTimeout and ResponseTimeoutValue properties, I think theyā€™re pretty nifty.

However, Iā€™m a little confused on how your library provides DDoS protection. You state:

But youā€™re not preventing the data from being sent to the server (afaik this isnā€™t possible).
Isnā€™t this the ā€œbadā€ part of DDoSing? Sure your module may skip processing it, but the bandwidth is still being consumed. Furthermore, while Iā€™m not familiar with ByteNet, I imagine any Packet which expects to receive nothing wouldnā€™t process the incoming data anyways.

Perhaps Iā€™m mistaken. Either way, Iā€™m curious

1 Like

This is a great module! One question I had was I was wondering why it is not possible to make a unreliable packet directly? I think it might be more convenient if there was some way to define a packet as unreliable or normal initially.

There is a discord channel on the first post where you will find me active and we have a thread there on Packet where you can have a live discussion

1 Like

your right that its not possible to stop a client from sending events to the server but that is not the bad part, the bad part is if this causes the server to crash let me give you a example

if I enter a server with 2 accounts then trade a item to my alt account then exit the server on my alt account causing my alt accounts datastore to save then I crash the server causing my original account datastore not to save I have now successfully duplicated items


because all packets are batched into a single packet we never expect there to be nothing

for example

if we have a packet like

packet = Packet("Name", Packet.NumberU8)
packet:Fire(7)

this will create a buffer like

buffer(0, 7) -- 0 is the packet id and 7 is the NumberU8

but what happens if we fire the packet many times

packet = Packet("Name", Packet.NumberU8)
packet:Fire(7)
packet:Fire(7)
packet:Fire(7)
packet:Fire(7)

now we have a buffer like this

buffer(0, 7, 0, 7, 0, 7, 0, 7) -- 0 is the packet id and 7 is the NumberU8

we can see that all the fires are batched into a single buffer
and if we sent

buffer(0, 0, 0, 0, 0, 0, 0, 0)

this is also a valid buffer we are just sending the value of 0 instead of 7 now 4 times

all networking libraries that use buffers do it the same way but with ByteNet packet ids start at 1 not 0

buffer(1, 7, 1, 7, 1, 7, 1, 7)
buffer(1, 0, 1, 0, 1, 0, 1, 0)
buffer(1, 1, 1, 1, 1, 1, 1, 1)

all these would be valid buffers for ByteNet and the server would try to read them all

but if a exploiter sends many huge buffers multiple times per frame and the server tries to read them all the server will crash and giving exploiters the power to crash the server opening up many other vulnerabilities like item duplicating

2 Likes

The main reason is adding more complexity to the module

even adding the remote function feature caused a 2x in complexity of the module but I felt it was worth the extra complexity

the way packet supports unreliable events does not introduce any complexity into the module

here is a little wrapper that you might find more convenient

--!strict
local RunService = game:GetService("RunService")
local Packet = require(game.ReplicatedStorage.Packet)

local unreliablePackets = {
	Packet1 = Packet("Packet1", Packet.NumberU8),
	Packet2 = Packet("Packet2", Packet.String),
}

for index, packet in unreliablePackets do
	local packet = packet :: Packet.Packet
	
	if RunService:IsServer() then
		local unreliableRemoteEvent = Instance.new("UnreliableRemoteEvent")
		unreliableRemoteEvent.Name = packet.Name
		unreliableRemoteEvent.Parent = game.ReplicatedStorage
		unreliableRemoteEvent.OnServerEvent:Connect(function(player, ...)
			packet.OnServerEvent:Fire(player, packet:Deserialize(...))
		end)
		
		packet.Fire = function(packet, ...)
			unreliableRemoteEvent:FireAllClients(packet:Serialize(...))
		end
		
		packet.FireClient = function(packet, player, ...)
			unreliableRemoteEvent:FireClient(player, packet:Serialize(...))
		end
	else
		local unreliableRemoteEvent = game.ReplicatedStorage:WaitForChild(packet.Name)
		unreliableRemoteEvent.OnClientEvent:Connect(function(...)
			packet.OnClientEvent:Fire(packet:Deserialize(...))
		end)
		
		packet.Fire = function(packet, ...)
			unreliableRemoteEvent:FireServer(packet:Serialize(...))
		end
	end
end

return unreliablePackets
1 Like