portagent is a POSIX transparent proxy routing daemon that allows multiple arbitrary services to run on a single arbitrary port. The main intention of portagent is for situations that need more services open to the world than open ports prohibit.
portagent works by analyzing the first input sent to the proxy (portagent) then, based on that input, forwards the connection to a defined location; this makes portagent more of an art than a science. certain protocols work well together, and the more services on a single port the more degradation may occur.
some protocols expect the client to send data first, for example http/80 sends its request without expecting any data from the server, this is desired, and can be matched and forwarded immediately. on the other side a service like ssh/22 expects the server to send data first, for this portagent will 'tease' the client with a forwarded connection (using the TRY instruction listed further on) so that the server will send data to the client in an attempt to invoke a response from client to then be matched and forwarded.
the science part of portagent comes into play when using multiple TRY instructions to attempt to invoke a response from the client, by the second TRY instruction the connection will have invalid protocol data sent to it from the previous TRY, however this may or may not matter depending on the protocol. if a protocol is broken by this, it is usually easily noticeable when debugging/testing a portagent config file.
portagent config options have the following basic format: INSTRUCTION_NAME 'instruction_value', where instruction_value may contain the following escape codes: \\, \', \e, \v, \t, \r, \n, \xNN, and \NNN.
portagent config files themselves have a very flexible instruction hierarchy, a whole config file could be placed on one line with no spaces if needed. however, it is best understood in the following schema (format):
(items in '[]' indicate they are not required, '...' indicates allowance for multiple hierarchy instances, '|' indicates one of two choices)
sets a file to write connection events and other portagent related information to. this file will be locked until portagent exits and any other instances of portagent will exit if they attempt to access the same file. the CHROOT instruction does not affect this instruction's path.
sets a file to write the portagent background process id (pid) to. this file will be locked until portagent exits and any other instances of portagent will exit if they attempt to access the same file. the CHROOT instruction does not affect this instruction's path.
sets a specified directory to chroot to once portagent is loaded and running. this intended for security purposes, no files need to be accessed after the CHROOT instruction has been executed, so any blank directory will do. this instruction does not affect the paths of the LOGFILE or PIDFILE instructions.
switches the user id (uid) of portagent after all ports have been binded to and all files have been loaded. this intended for security purposes.
switches the group id (gid) of portagent after all ports have been binded to and all files have been loaded. this intended for security purposes.
sets the port to bind to accept new connections and initializes all instructions that follow to be applied to the specified port. LISTEN will also complete the previous LISTEN block, if there is one. (info: the protocol string representation can be used instead of the numeric port value, ie. 'http' instead of '80')
sets hostname/ip to bind the specified port to. for example, if '127.0.0.1' was used portagent would only allow incoming connections to connect if they connected to 127.0.0.1.
sets the number of allowed unhandled connections to be queued.
sets the total number of allowed incoming connections on the specified port. any connections after the specified limit will be dropped immediately.
sets the maximum size of the initial read buffer per incomming connection, this is what IF instructions are compared against. it should be noted that data can be dropped if this buffer is not set appropriately, it should be set to the maximum amount of data that can be received before being passed to a USE instruction. if data is still coming in before a USE instruction has been hit the exceeding data will be dropped. this instruction can be specified via an arbitrary number (assumed bytes) or a number followed by a B, K, M, or G. (ie. '8k' would be 8192 bytes)
sets the maximum size of the queue buffer per incomming connection. each connection has a send queue for situations where one side can send faster than the other can receive. if the queue grows larger than the specified limit the connection will be dropped. this instruction can be specified via an arbitrary number (assumed bytes) or a number followed by a B, K, M, or G. (ie. '8k' would be 8192 bytes)
writes the specified string to the incoming connection. no new-line character is appended, all normal escape formats are supported. (ie. '\r', '\n', '\xNN', '\NNN' and so on)
sets the number of seconds to wait for following IF instruction(s) to match incoming input. once the specified time has passed portagent will move on to the next TRY instruction or drop the connection if it is the last.
if the incoming connection's initial input/data matches the specified pre-defined protocol and any following IP or PORT instructions also match, the following USE instruction will be used--otherwise it will not. supported protocols are: any, input, ascii, extended-ascii, readable, unreadable, http, ssh, ftp, smtp, pop3, imap and auth. (any stands for any value including nothing, input stands for any value but must be something)
if the incoming connection's initial input/data matches the specified LIKE expression format and any following IP or PORT instructions also match, the following USE instruction will be used--otherwise it will not. the LIKE format is a basic wildcard comparison that can allow anything on the left or right to be wildcard matched via the '%' character. for example, '%test%' would match if the connection's input/data has the string 'test' anywhere in the input/data. this instruction is intended for when the IF DEFINED instruction has no suitable pre-defined value associated with the protocol, or you just need hands-on matching of the initial data. this instruction supports null-byte comparisons if needed. (signified by '\x00' or '\000')
if the incoming connection's initial input/data matches the specified the connection's input/data has the string 'test' anywhere in the input/data. this instruction does not support null-byte comparisons, use the IF LIKE instruction for that. this instruction is intended for when the IF DEFINED instruction has no suitable pre-defined value associated with the protocol, or you just need hands-on matching of the initial data.
if the specified ip format matches, along with any preceding or following IF or PORT restrictions, then the following USE instruction will be used. the ip format can be specified as an ip or a range. (ie. '127.0.0.1', '127.*.*.*' or '127.1-255.1-255.1-255')
if the specified port format matches, along with any preceding or following IF or IP restrictions, then the following USE instruction will be used. the port format can be specified as a number or a range of numbers. (ie. '4096' or '4000-4100')
sets the final forwarding location for the incoming connection, once this instruction has been executed no other instructions will be processed for the current connection. if '-' is used it will assume the active forwarding connection currently in use from a previous TRY instruction. (info: 'hostname' can be an ip; 'port' can be the protocol string representation, instead of the numeric port)
sets a (temporary) forward to forward data to the incoming connection in an attempt to invoke initial data from the incoming connection. this instruction is intended for protocols that expect the server to send the initial data first. USE '-' will commit the last TRY instruction as the (final) forward location. (info: 'hostname' can be an ip; 'port' can be the protocol string representation, instead of the numeric port)
Report bugs to <v9@fakehalo.us>.