Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 1 | intermud v2.5 |
| 2 | ************* |
| 3 | |
| 4 | Abstract |
| 5 | ======== |
| 6 | This documents describes how intermud data is send across the internet in the |
| 7 | protocol specification v2.5. |
| 8 | This specification is derived from Zebedee Intermud (aka Intermud 2) and |
| 9 | intends to be compatible to it, i.e. hosts conforming to both protocols should |
| 10 | be able to exchange data. The aim of v2.5 is to deprecate several historic |
| 11 | ambiguities, define a more consistent (stricter, less implementation-defined) |
| 12 | behaviour, add some optional system services and improve reliability and |
| 13 | remove spoofability of MUDs by introducing hash based message authentication |
| 14 | codes. |
| 15 | |
| 16 | Introduction |
| 17 | ============ |
| 18 | |
| 19 | Overview |
| 20 | -------- |
| 21 | The intermud protocols define, how (players on) different muds can |
| 22 | communicate with each other. There are several different variants. |
| 23 | In version 2 all muds are peers and directly talking to each other. There |
| 24 | is no central router. Version 2.5 keeps this behaviour but intends to |
| 25 | strengthen the P2P character of the intermud by defining a default |
| 26 | behaviour of learning other peers from one known peer. |
| 27 | The participants of the intermud are intended to be MUDs, not |
| 28 | individual players. |
| 29 | |
| 30 | Terminology |
| 31 | ----------- |
| 32 | The capitalized key words "MUST", "MUST NOT", "REQUIRED", "SHALL", |
| 33 | "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and |
| 34 | "OPTIONAL" in this document are to be interpreted as described in BCP |
| 35 | 14, RFC 2119 [TERMS]. |
| 36 | |
| 37 | MUD |
| 38 | multi user dungeon |
| 39 | intermud peer |
| 40 | a participant in the intermud |
| 41 | inetd |
| 42 | a program encoding and sending and receiving and decoding intermud data |
| 43 | peer address |
| 44 | IP address of a peer (MUD) |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 45 | MUD name / peer name / peer identifier |
| 46 | a name (string) for a peer (MUD). If a peer has a key, the name is just a |
| 47 | symbolic name for a peer with this key. Otherwise, the peer name is the |
| 48 | unique identifier. |
| 49 | An inetd implementation MAY accept more than one peer with the same name as |
| 50 | long as their keys are different. However, it SHOULD keep a consistent |
| 51 | mapping between key and peer name. |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 52 | |
Zesstra | 79cdbe5 | 2016-04-22 19:26:49 +0200 | [diff] [blame] | 53 | Host list / Peer data |
| 54 | ===================== |
| 55 | A peer **MUST** store the following data about other known peers: |
| 56 | |
| 57 | * peer name (unique) (name) |
| 58 | * public key (unique), if available (pkey) |
| 59 | * peer address (ip) |
| 60 | * receiving peer port (port) |
Zesstra | ca0502f | 2016-04-24 20:11:54 +0200 | [diff] [blame] | 61 | * time of last contact (last_contact) |
| 62 | * time of first contact (first_contact) |
Zesstra | 79cdbe5 | 2016-04-22 19:26:49 +0200 | [diff] [blame] | 63 | * reputation (trust) of that peer (reputation) |
| 64 | |
| 65 | A peer **SHOULD** store the following data about other known peers: |
| 66 | |
| 67 | * list of supported services (services) |
Zesstra | ca0502f | 2016-04-24 20:11:54 +0200 | [diff] [blame] | 68 | * last seen intermud version (im_version) |
Zesstra | 79cdbe5 | 2016-04-22 19:26:49 +0200 | [diff] [blame] | 69 | * expiration time (ncttl) |
| 70 | * MTU of the peer (mtu) |
| 71 | |
| 72 | A peers public key would be the best unique identifier. However, in the |
| 73 | intermud a peer needs a unique symbolic name to address it. So a peers name |
| 74 | and its public key should both be used as unique and long-lived identifier. |
| 75 | |
| 76 | But a peer MAY change its name by either announcing it or by just using a new |
| 77 | name. If the public key remains the same, the entry in the peer list should |
| 78 | be updated accordingly. |
| 79 | |
| 80 | If a peer claims to have a name that already exists, but its public key does |
| 81 | not match the known public key of the existing peer entry, the new peer **MUST |
| 82 | NOT** be entered in the peer list. Instead, any packets from that peer |
| 83 | **SHOULD** be discarded. An implementation MAY notify the operator about this. |
| 84 | |
| 85 | When a peer starts up, it **SHOULD** make itself known by pinging known peers |
| 86 | or sending a HELO packet. |
| 87 | |
| 88 | Host keys |
| 89 | --------- |
| 90 | Each host **MUST** have an elliptic curve private/public key pair for ECDSA or |
| 91 | EdDSA signatures using one of the following curves: |
| 92 | |
| 93 | * secp256r1 / prime256v1 |
| 94 | * Curve25519 |
| 95 | * secp521r1 |
| 96 | |
| 97 | This *identity key* is long-lived. Bascically, the intermud peer name and its |
| 98 | reputation tie to this identity key. |
| 99 | |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 100 | When receiving an IM 2.5+ packet from a peer with unknown public key, the |
| 101 | receiver requests the sender's public key with a HELO packet (see below) and |
| 102 | stores it (trust on first use). |
| 103 | |
| 104 | |
| 105 | Peer name |
| 106 | --------- |
| 107 | If a peer has a key, the name is just a symbolic name for a peer with this |
| 108 | key. Otherwise, the peer name is the unique identifier. |
| 109 | |
| 110 | An inetd implementation MAY accept more than one peer with the same name as |
| 111 | long as their keys are different. However, it SHOULD keep a consistent mapping |
| 112 | between key and peer name. |
| 113 | |
| 114 | |
Zesstra | 79cdbe5 | 2016-04-22 19:26:49 +0200 | [diff] [blame] | 115 | Reputation |
| 116 | ---------- |
| 117 | The reputation is a score that symbolizes how trustworthy a peer is. It may be |
| 118 | used for a number of decisions. By default, the reputation score is used for |
| 119 | the following: |
| 120 | |
| 121 | * scaling factor when exchanging peer information (see below) |
| 122 | * peer expiration time since last contact (ncttl) |
| 123 | * services that are offered to the other peer |
| 124 | |
| 125 | Specififally, to prevent spam and misuse, services like public channel |
| 126 | messages and intermud mail **SHOULD** be restricted to peers with a reputation |
| 127 | > 0. A peer may also restrict the accessibility of user depending on the |
| 128 | reputation of the sending peer (e.g. beginners can't be disturbed from freshly |
| 129 | known intermud peers). |
| 130 | |
| 131 | By default, a new peer starts with a score of 0 (which basically means, the |
| 132 | information it offers, is not trusted). After a peer has been known for some |
| 133 | time, its score gets increased: |
| 134 | |
| 135 | ========== ============== |
| 136 | time known score increase |
| 137 | ========== ============== |
| 138 | 7 days +1 |
| 139 | 3 months +1 |
| 140 | 1 year +1 |
| 141 | ========== ============== |
| 142 | |
| 143 | A reputation of more than 3 can only be assigned by an operator. |
| 144 | |
| 145 | A negative reputation is possible (e.g. manually assigned by operators) and |
| 146 | should be used to restrict services. Peers with negativ reputation should also |
| 147 | be kept longer in the peer list. |
| 148 | |
| 149 | Peer expiration |
| 150 | --------------- |
| 151 | A peer should expire peers from its host list some time after the last contact. The |
| 152 | expiration time may be chosen by the operator. |
| 153 | |
| 154 | However, to prevent rogue peers impersonating other peers, peers **MUST NOT** |
| 155 | be expired before 48h or a time this peer announced earlier (see module... |
| 156 | TODO) passed without contact. |
| 157 | |
| 158 | ========== =============== |
| 159 | reputation expiration time |
| 160 | ========== =============== |
| 161 | 0 72h |
| 162 | 1 14 days |
| 163 | 2 3 months |
| 164 | 3 6 months |
| 165 | 4+ 12 months |
| 166 | ========== =============== |
| 167 | |
| 168 | If a peer announces it wants to be remembered for longer than 72h without |
| 169 | contact, this wish MAY be respected and the decision MAY be based on its |
| 170 | reputation. A peer **SHOULD NOT** request more then 12 months. |
| 171 | |
| 172 | An implementation **MAY** may move offline peers to a separate list for |
| 173 | bookkeeping after some time and stop trying to contact it anymore. This keeps |
| 174 | the active peer list short and efficient. However the 'long offline' peers |
| 175 | should still be remembered to keep the binding of public key and name. |
| 176 | |
| 177 | If a peer has problems keeping track of peers, it **SHOULD** prefer to |
| 178 | temporarily stop accepting new peers instead of expiring known ones. |
| 179 | If a peer experiences too much intermud traffic (or other resource drains), it |
| 180 | **MAY** favor peers with higher reputation. |
| 181 | |
| 182 | Automatic update of peer data |
| 183 | ----------------------------- |
| 184 | When receiving a v2.5 packet with valid HMAC from an address and/or port that |
| 185 | differs from the one in the peer list, the peer entry **SHOULD** be updated to |
| 186 | the new address/port. |
| 187 | |
| 188 | If the address or port of a peer changes, this peer **SHOULD** send a ping to |
| 189 | known peers to announce the new address or port. |
| 190 | |
| 191 | When receiving a legacy mode packet, the peer entry **MAY** be updated. |
| 192 | However, this carries the risk of rogue peers successfully impersonating |
| 193 | another peer for an extended time. |
| 194 | |
| 195 | An inetd **SHOULD** contact the known peers at least once per 24h to check if |
| 196 | it is still online and reachable (ping or helo). |
| 197 | |
| 198 | Update of the public key |
| 199 | ------------------------ |
| 200 | There ist a way to perform an update of the public key without operator |
| 201 | intervention. The new public key **MUST** be received in a v2.5 packet with |
| 202 | valid signature. |
| 203 | |
| 204 | A peer may inform other peers about an update of its public key by |
| 205 | sending a push notification - TODO fill in module - Such an |
| 206 | update **SHOULD** be honored. |
| 207 | |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 208 | |
| 209 | Transport layer |
| 210 | =============== |
| 211 | Data between intermud peers is sent as UDP packets (datagrams) over |
| 212 | IP. |
| 213 | Each peer listens on one port and uses one to send data. This kind of |
| 214 | transfer is inherently unreliable, but it's fast and doesn't use up |
| 215 | file descriptors. |
| 216 | |
| 217 | Packet length (MTU) |
| 218 | ------------------- |
| 219 | A peer **MUST** be able to send and receive datagrams of at least 1024 |
| 220 | byte length. The default packet length **SHOULD** be 1024 bytes. If a peer |
| 221 | announces a greater possible length limit, that **SHOULD** be used by other peers |
| 222 | when sending packets to this peer. |
| 223 | |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 224 | A peer may announce the largest reliable packet (maximum transmission unit, |
| 225 | maximum size of datagram) it can receive when asked with the QUERY module |
| 226 | which should be the preferred way. |
| 227 | |
| 228 | If the MTU cannot be determined with a QUERY, the two peers should try to |
| 229 | determine them by sending heartbeat packets of increasing size to the other |
| 230 | peer (see below). |
| 231 | |
| 232 | The packet size that is used for sending **SHOULD** be the smaller of the |
| 233 | maximum packet length of the two communicating peers. |
| 234 | |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 235 | Packet format |
| 236 | ------------- |
| 237 | All information is encoded and transferred as a string of bytes. The header |
| 238 | names **SHOULD** consist of ASCII characters. |
| 239 | Each packet sent consists of a string as follows: |
| 240 | |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 241 | S:xxx|NAME:xxx|V:nnn|F:nnn|header1:body1|headerN:bodyN|DATA:body-data |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 242 | |
| 243 | In other words, a header name, followed by a : and then the data |
| 244 | associated with this header. Each field, consisting of a header/body pair, is |
| 245 | separated by the | character. This means that headers and their body cannot |
| 246 | contain the | character. Peers **SHOULD** check for this in outgoing |
| 247 | packets to avoid decoding errors at the receiving end. |
| 248 | |
| 249 | The exception to this is the DATA field. If it is present, it **MUST** |
| 250 | be positioned at the end of the packet. Once a DATA header is |
| 251 | found, everything following it is interpreted as the body of the DATA |
| 252 | field. This means it can contain special characters without error and |
| 253 | it is used to carry the main body or data of all packets. |
| 254 | |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 255 | The fields S (packet signature), NAME (the sending peers name), V (version) |
| 256 | and F (flags) **MUST** be in this order at the start of the packet before any |
| 257 | other fields. These 4 fields are also referred to as the 'packet header'. The |
| 258 | general layout of packets is: |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 259 | |
Zesstra@Morgengrauen | 18f4e04 | 2016-05-07 11:02:19 +0200 | [diff] [blame] | 260 | [fragmentation header|]packet header|packet payload/data |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 261 | |
| 262 | The packet header **MUST NOT** be larger than 512 bytes. |
| 263 | |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 264 | By convention, predefined system fields will use capital letters for |
| 265 | field headers and custom headers used by specific applications will |
| 266 | use lowercase names to avoid clashes. |
| 267 | |
| 268 | A header name **MUST** be unique in a packet. |
| 269 | |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 270 | An implemention **MUST** support at least 32 fields per packet. |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 271 | |
| 272 | Fragmented packets |
| 273 | ------------------ |
| 274 | If a packet exceeds the maximum packet length, it **MUST** be split |
| 275 | (fragmented) into individual packets small enough. |
| 276 | Each fragment **MUST** start with a fragmentation header describing how the |
| 277 | fragments are to be reassembled at the receiving end. |
| 278 | |
| 279 | These fragmentation headers are of the format: |
| 280 | |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 281 | PKT:peername:packet-id:packet-number/total-packets|S:xxx|rest-of-packet |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 282 | |
| 283 | In this case, the mudname and packet-id combine to form a unique id |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 284 | for the packet. The packet id is the same number used for the header field ID |
| 285 | (see below). The packet-number and total-packets information is |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 286 | used to determine when all buffered packets have been received. The |
| 287 | rest-of-packet part is not parsed, but is stored while the receiver |
| 288 | awaits the other parts of the packet. When/if all parts have been |
Zesstra | ca0502f | 2016-04-24 20:11:54 +0200 | [diff] [blame] | 289 | received they are concatenated (without the fragmentation header and S fields |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 290 | of the individual fragments) and decoded as a normal packet. |
| 291 | |
| 292 | When storing fragments of a packet, the receiver **MUST** use a unique packet |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 293 | id which uses the peer name and the sent packet-id. |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 294 | |
| 295 | Any peer **MUST** support at least 100 fragments per packet. |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 296 | |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 297 | Each fragment **MUST** contain its own valid signature in the field S. |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 298 | |
| 299 | The sender **SHOULD** send the fragments in the correct order. However, the |
| 300 | receiver **MUST** assume the fragments arrive in any order. |
| 301 | |
| 302 | The sender **MUST** send all fragments of a packet within 30 s from sending the |
| 303 | first fragment. |
| 304 | The receiver **MUST** wait for fragments at least 60 s after the first fragment |
| 305 | arrived. After this, the receiver may discard any fragments of this packet and |
| 306 | therefore the packet as a whole. |
| 307 | |
| 308 | Packet encoding |
| 309 | --------------- |
| 310 | Only 2 generic data types are supported (namely strings and integers). All |
| 311 | other data types **MUST** be expressed as strings or integers. |
| 312 | |
| 313 | On encoding integers are simply converted to a corresponding string. |
| 314 | Strings **MUST** be prefixed with the character $. If the first character of a |
| 315 | string is the $ character, it is escaped by prepending another $ character. |
| 316 | |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 317 | Packet signatures |
| 318 | ----------------- |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 319 | For packet validation and to prevent tampering on the wire and spoofing of |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 320 | peers, each packet sent **MUST** contain a field S containing the EC-DSA |
| 321 | signature of the packet. |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 322 | |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 323 | The first byte of the MAC field specifies the method and curve used. In intermud |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 324 | v2.5 the following algorithms **MUST** be supported: |
| 325 | |
Zesstra | ca0502f | 2016-04-24 20:11:54 +0200 | [diff] [blame] | 326 | * (a) Ed25519 + SHA512 |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 327 | |
Zesstra | ca0502f | 2016-04-24 20:11:54 +0200 | [diff] [blame] | 328 | The recommended method is Ed25519 + SHA512 |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 329 | |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 330 | The transferred data is the complete packet string **without** the field S. |
| 331 | After the packet (or fragment) is encoded (without the field S), the signature |
| 332 | is calculated using the private EC key and then inserted into the packet |
| 333 | string either at the beginning of the packet or (for fragments) at the end of |
| 334 | the fragmentation header. |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 335 | |
| 336 | Packet validation |
| 337 | ----------------- |
| 338 | Upon receiving a fragment or packet, the receiver **MUST** first try to |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 339 | validate the signature in the field S, if a public key for the sending peer is |
| 340 | known. The receiver extracts the whole field from the received string and |
| 341 | verifies the signature. If signature can't be verified, the receiver **MUST** |
| 342 | discard the fragment or packet. |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 343 | |
| 344 | Fragments are then stored until the packet is completed or the timeout is |
| 345 | exceeded. |
| 346 | |
| 347 | The receiver **SHOULD** parse and decode the packet only after this initial |
| 348 | validation. If the packet is malformed and cannot be parsed, the receiver |
| 349 | **MUST** discard the packet. |
| 350 | |
| 351 | The intermud protocol versions of peers **SHOULD** be stored and no packets in |
| 352 | an older protocol version **SHOULD** be accepted. |
| 353 | |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 354 | Packet decoding |
| 355 | --------------- |
| 356 | On decoding, any string with a $ as its first character will have it removed |
| 357 | and will then be treated as a string. |
| 358 | Any other strings will be converted to integers. |
| 359 | |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 360 | The fields S, V and F **SHOULD** be stripped from the packet data that is |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 361 | transferred from the inetd implementation to the application. |
| 362 | |
| 363 | Legacy mode packets and encoding |
| 364 | -------------------------------- |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 365 | Any intermud v2.5 peer **MUST** send data as described above. However, unless |
| 366 | in a so-called strict mode, a receiving peer **MUST** accept data in a relaxed |
| 367 | format that is sent by older intermud peers. Unless in strict mode, the following |
| 368 | deviations are acceptable when receiving: |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 369 | |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 370 | * The packet header (S, V and F fields) is missing. |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 371 | * A string **MAY** be prefixed with the character $, but does not have to, unless |
| 372 | there ambiguity as to wether they should be decoded as a string or an |
| 373 | integer. If a string is losslessly convertable to an integer and back to a |
| 374 | string, it **MUST** be prefixed by $. |
| 375 | This means however, that any string not starting with $ **MUST** be checked |
| 376 | whether it is to be interpreted as integer or string. |
| 377 | |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 378 | However, a packet **MUST NOT** be parsed as legacy mode packet, if one of the |
| 379 | following conditions are met: |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 380 | |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 381 | * the packet contains the field S |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 382 | * the packet contains a version field F with a version of at least 2500 |
| 383 | * the receiving peer operates in strict mode |
| 384 | |
| 385 | After a packet conforming to protocol version >= 2.5 (>=2500) was received |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 386 | from a peer (this implies the succesful validation of the signature), legacy mode |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 387 | packets from that peer **MUST NOT** be accepted without manual intervention of |
| 388 | an operator or expiration of the peer from the peer list. |
| 389 | |
| 390 | If a peer sends to a peer with a known protocol version older than v2.5 it |
| 391 | **MAY** send the data as a legacy mode packet. However, this is not recommended. |
| 392 | |
| 393 | Strict mode |
| 394 | ----------- |
| 395 | To prevent spoofing of other muds, an operator MAY decide to operate in strict |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 396 | mode. In this mode, the peer accepts intermud v2.5 packets with a valid S |
| 397 | field only and discards all other packets. |
| 398 | In other words, it disables the compatibility with peers older than v2.5 and |
| 399 | does not communicate with unknown peers. |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 400 | |
| 401 | Request bookkeeping |
| 402 | ------------------- |
| 403 | When sending a request that expects/requires an answer, the sender **MUST** |
| 404 | keep track of the request to relate any answers to the original request. |
| 405 | |
| 406 | Any peer **MUST** be able to keep track of at least 100 requests. |
| 407 | |
| 408 | If the answer of a request does not arrive within 60s, the request **SHOULD** |
| 409 | be expired (timeout). |
| 410 | |
| 411 | |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 412 | Defined system headers / fields |
| 413 | =============================== |
| 414 | The fields defined in this section **MUST NOT** be used in any application sending |
| 415 | data via intermud. The sending inetd **SHOULD** check for this during input |
| 416 | validation before assembling a packet. |
| 417 | |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 418 | V |
| 419 | Intermud version used by the sender (integer) |
| 420 | F |
| 421 | Packet flags (integer, binary complement of flags) |
| 422 | S |
| 423 | Signature of the packet |
| 424 | NAME |
| 425 | The name of the sending mud. |
| 426 | HST |
| 427 | The IP address of the host from which a request was received. |
| 428 | This is set by the receiving mud and is not contained in |
| 429 | outgoing packets. |
| 430 | UDP |
| 431 | The UDP port the local mud is receiving on. |
| 432 | This is set by the receiving mud and is not contained in |
| 433 | outgoing packets. |
| 434 | ID |
| 435 | The packet id. This field is simply an integer which is set by |
| 436 | the sending inetd. The number is incremented each time a packet |
| 437 | is sent (zero is never used). The ID **MAY** wrap-around to 1 after some |
| 438 | time. |
| 439 | This field is only needed if a reply is expected. REPLY packets **MUST** |
| 440 | include the original request id. This is not done by the inetd. However, |
| 441 | implementations **SHOULD** check for a sane ID field in outgoing replies. |
| 442 | PKT |
| 443 | The fragmentation header for packets which have been fragmented (see |
| 444 | above). |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 445 | REQ |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 446 | The name of the intermud request that is being made of the |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 447 | receiving mud. Standard requests that should be supported by |
| 448 | all systems are "ping" (PING), "query" (QUERY), and "reply" |
| 449 | (REPLY). The PING request is used to determine wether or not a |
| 450 | mud is active. The QUERY request is used to query a remote mud |
| 451 | for information about itself (look at the udp/query module for |
| 452 | details of what information can be requested). The REPLY request |
| 453 | is special in that it is the request name used for all replies |
| 454 | made to by mud B to an initial request made by a mud A. It is |
| 455 | mud A's responsibility to keep track of the original request |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 456 | type so that the reply can be handled appropriately. |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 457 | SND |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 458 | The name of the person or object which sent the request or to |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 459 | whom replies should be directed. This is essential if a reply |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 460 | is expected. |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 461 | RCPNT |
| 462 | The body of this field should contain the recipient the message |
| 463 | is to be sent to if applicable. |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 464 | DATA |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 465 | This field should contain the main body of any packet. It is |
| 466 | the only field that can contain special delimiting characters |
| 467 | without error. |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 468 | SYS |
| 469 | (SYSTEM) Contains special system flags. The only system flag used at |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 470 | present is TIME_OUT. This is included in packets returned due |
| 471 | to an expected reply timing out to differentiate it from an |
| 472 | actual reply. |
| 473 | |
| 474 | |
| 475 | Intermud requests / modules |
| 476 | =========================== |
| 477 | |
| 478 | Mandatory requests / modules |
| 479 | ---------------------------- |
| 480 | The following are standard request types that **MUST** be supported |
| 481 | by all systems: |
| 482 | |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 483 | ping |
| 484 | ^^^^ |
| 485 | This module should return a REPLY packet that contains the |
| 486 | original requests ID in it's ID field and the SENDER in it's |
| 487 | RECIPIENT field. It should also include an appropriate string |
| 488 | in the DATA field, eg. "Mud-Name is alive.\n" |
| 489 | |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 490 | Request:: |
| 491 | |
| 492 | "...|REQUEST:ping|ID:42|DATA:Morgengrauen is alive.\n" |
| 493 | |
| 494 | Answer:: |
| 495 | |
| 496 | "...|REQUEST:reply|ID:42|DATA:Unitopa is alive.\n" |
| 497 | |
| 498 | |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 499 | helo |
| 500 | ^^^^ |
Zesstra@Morgengrauen | f14175b | 2016-05-27 22:49:29 +0200 | [diff] [blame] | 501 | Used to exchange information like the public key. The sender sends its name |
| 502 | and public key, the receiver answers with its own name and public key, encoded |
| 503 | as JSON. |
| 504 | |
| 505 | Having to send one's own public key makes UDP amplification attacks (e.g. |
| 506 | sending a small packet with a faked source which causes a larger packet be |
| 507 | sent to the victim) more difficult, since there is no amplification. |
| 508 | |
| 509 | Optionally, more data **MAY** be included: desired mtu in bytes (mtu), ... |
| 510 | |
| 511 | Request:: |
| 512 | |
| 513 | "...|REQUEST:helo|ID:42|DATA:{ \"pkey\": \"xxx\", \"name\": \"Morgengrauen\" }" |
| 514 | |
| 515 | Answer:: |
| 516 | |
| 517 | "...|REQUEST:reply|ID:42|DATA:{ \"pkey\": \"yyy\", \"name\": \"Unitopia\" }" |
| 518 | |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 519 | |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 520 | query |
| 521 | ^^^^^ |
| 522 | This module expects the type of query requested to appear in the |
| 523 | recieved DATA field. It should return a REPLY packet containing |
| 524 | the original ID in the ID field, the SENDER in it's RECIPIENT |
| 525 | field, and the query type in a QUERY field. The DATA field should |
| 526 | contain the information requested. |
Zesstra@Morgengrauen | 09eef28 | 2016-04-21 23:00:38 +0200 | [diff] [blame] | 527 | TODO: include asking for peer list in JSON format. |
Zesstra@Morgengrauen | 5cad50a | 2016-04-19 21:44:10 +0200 | [diff] [blame] | 528 | |
| 529 | |
| 530 | Optional requests / modules |
| 531 | ---------------------------- |
Zesstra@Morgengrauen | 2021921 | 2016-04-20 22:34:41 +0200 | [diff] [blame] | 532 | These modules are completely optional and their availability at the discretion |
| 533 | of the operator of a peer. |
| 534 | |