--[[
For reasons outlined here (https://wiki.computercraft.cc/Network_security), Rednet is not really a good choice for new networking setups, apart from its capability to relay messages (obsoleted by ender modems).

However, if you do want to keep using it, without the risk of it crashing due to the exploits I have identified (https://pastebin.com/pJnfSDcL), you can use this convenient, patched repeater. It doesn't alleviate the fundamental issues with Rednet, though.
]]

-- Find modems
local modems = {peripheral.find "modem"}

local comp_ID = os.getComputerID()

print(("%d modem(s) found"):format(#modems))

local function for_each_modem(fn)
	for _, m in pairs(modems) do
		fn(m)
	end
end

local function open(channel)
	for_each_modem(function(m) m.open(channel) end)
end

local function close(channel)
	for_each_modem(function(m) m.close(channel) end)
end

-- Open channels
open(rednet.CHANNEL_REPEAT)

-- Main loop (terminate to break)
local ok, error = pcall(function()
	local received_messages = {}
	local received_message_timers = {}
	local transmitted_messages = 0

	while true do
		local event, modem, channel, reply_channel, message, distance = os.pullEvent()
		if event == "modem_message" then
			-- Got a modem message, rebroadcast it if it's a rednet thing
			if channel == rednet.CHANNEL_REPEAT and type(message) == "table" then
				local id = message.nMessageID -- unfortunately we must keep the stupid rednet identifiers SOMEWHERE...
				local recipient = message.nRecipient
				local route = message.route -- protocol extension
				if type(route) ~= "table" then route = { reply_channel } end
				table.insert(route, comp_ID)
				message.route = route
				if id and recipient and (type(id) == "number" or type(id) == "string") and type(recipient) == "number" and recipient >= 0 and recipient <= 65535 then
					if not received_messages[id] then
						-- Ensure we only repeat a message once per 30 seconds
						received_messages[id] = true
						received_message_timers[os.startTimer(30)] = id

						-- Send on all other open modems, to the target and to other repeaters
						for_each_modem(function(m)
							m.transmit(rednet.CHANNEL_REPEAT, reply_channel, message)
							m.transmit(recipient, reply_channel, message)
						end)

						-- Log the event
						transmitted_messages = transmitted_messages + 1
						term.clear()
						term.setCursorPos(1, 1)
						print(("%d message(s) repeated"):format(transmitted_messages))
						print(string.format("%s\nfrom %d to %s dist %d", tostring(message.message), reply_channel, tostring(recipient), tostring(distance) or "[n/a]"))
					end
				end
			end

		elseif event == "timer" then
			-- Got a timer event, use it to clear the message history
			local timer = modem
			local id = received_message_timers[timer]
			if id then
				received_message_timers[timer] = nil
				received_messages[timer] = nil
			end

		end
	end
end)
if not ok then
	printError(error)
end

-- Close channels
close(rednet.CHANNEL_REPEAT)