├── .codeclimate.yml ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── README.md ├── example ├── tcp-client.js └── udp-client.js ├── index.d.ts ├── index.js ├── package-lock.json ├── package.json ├── ref └── rfc │ └── rfc3164.txt └── test ├── certificate.pem ├── key.pem ├── syslog-client.js └── wrong.pem /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | duplication: 4 | enabled: true 5 | config: 6 | languages: 7 | - javascript 8 | eslint: 9 | enabled: true 10 | checks: 11 | complexity: 12 | enabled: false 13 | fixme: 14 | enabled: true 15 | ratings: 16 | paths: 17 | - "**.js" 18 | exclude_paths: 19 | - test/ 20 | - example/ 21 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*{.,-}min.js 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | ecmaFeatures: 2 | modules: true 3 | jsx: true 4 | 5 | env: 6 | amd: true 7 | browser: true 8 | es6: true 9 | jquery: true 10 | node: true 11 | 12 | # http://eslint.org/docs/rules/ 13 | rules: 14 | # Possible Errors 15 | comma-dangle: [2, never] 16 | no-cond-assign: 2 17 | no-console: 0 18 | no-constant-condition: 2 19 | no-control-regex: 2 20 | no-debugger: 2 21 | no-dupe-args: 2 22 | no-dupe-keys: 2 23 | no-duplicate-case: 2 24 | no-empty: 2 25 | no-empty-character-class: 2 26 | no-ex-assign: 2 27 | no-extra-boolean-cast: 2 28 | no-extra-parens: 0 29 | no-extra-semi: 2 30 | no-func-assign: 2 31 | no-inner-declarations: [2, functions] 32 | no-invalid-regexp: 2 33 | no-irregular-whitespace: 2 34 | no-negated-in-lhs: 2 35 | no-obj-calls: 2 36 | no-regex-spaces: 2 37 | no-sparse-arrays: 2 38 | no-unexpected-multiline: 2 39 | no-unreachable: 2 40 | use-isnan: 2 41 | valid-jsdoc: 0 42 | valid-typeof: 2 43 | 44 | # Best Practices 45 | accessor-pairs: 2 46 | block-scoped-var: 0 47 | complexity: [2, 6] 48 | consistent-return: 0 49 | curly: 0 50 | default-case: 0 51 | dot-location: 0 52 | dot-notation: 0 53 | eqeqeq: 2 54 | guard-for-in: 2 55 | no-alert: 2 56 | no-caller: 2 57 | no-case-declarations: 2 58 | no-div-regex: 2 59 | no-else-return: 0 60 | no-empty-pattern: 2 61 | no-eq-null: 2 62 | no-eval: 2 63 | no-extend-native: 2 64 | no-extra-bind: 2 65 | no-fallthrough: 2 66 | no-floating-decimal: 0 67 | no-implicit-coercion: 0 68 | no-implied-eval: 2 69 | no-invalid-this: 0 70 | no-iterator: 2 71 | no-labels: 0 72 | no-lone-blocks: 2 73 | no-loop-func: 2 74 | no-magic-number: 0 75 | no-multi-spaces: 0 76 | no-multi-str: 0 77 | no-native-reassign: 2 78 | no-new-func: 2 79 | no-new-wrappers: 2 80 | no-new: 2 81 | no-octal-escape: 2 82 | no-octal: 2 83 | no-proto: 2 84 | no-redeclare: 2 85 | no-return-assign: 2 86 | no-script-url: 2 87 | no-self-compare: 2 88 | no-sequences: 0 89 | no-throw-literal: 0 90 | no-unused-expressions: 2 91 | no-useless-call: 2 92 | no-useless-concat: 2 93 | no-void: 2 94 | no-warning-comments: 0 95 | no-with: 2 96 | radix: 2 97 | vars-on-top: 0 98 | wrap-iife: 2 99 | yoda: 0 100 | 101 | # Strict 102 | strict: 0 103 | 104 | # Variables 105 | init-declarations: 0 106 | no-catch-shadow: 2 107 | no-delete-var: 2 108 | no-label-var: 2 109 | no-shadow-restricted-names: 2 110 | no-shadow: 0 111 | no-undef-init: 2 112 | no-undef: 0 113 | no-undefined: 0 114 | no-unused-vars: 0 115 | no-use-before-define: 0 116 | 117 | # Node.js and CommonJS 118 | callback-return: 2 119 | global-require: 2 120 | handle-callback-err: 2 121 | no-mixed-requires: 0 122 | no-new-require: 0 123 | no-path-concat: 2 124 | no-process-exit: 2 125 | no-restricted-modules: 0 126 | no-sync: 0 127 | 128 | # Stylistic Issues 129 | array-bracket-spacing: 0 130 | block-spacing: 0 131 | brace-style: 0 132 | camelcase: 0 133 | comma-spacing: 0 134 | comma-style: 0 135 | computed-property-spacing: 0 136 | consistent-this: 0 137 | eol-last: 0 138 | func-names: 0 139 | func-style: 0 140 | id-length: 0 141 | id-match: 0 142 | indent: 0 143 | jsx-quotes: 0 144 | key-spacing: 0 145 | linebreak-style: 0 146 | lines-around-comment: 0 147 | max-depth: 0 148 | max-len: 0 149 | max-nested-callbacks: 0 150 | max-params: 0 151 | max-statements: [2, 30] 152 | new-cap: 0 153 | new-parens: 0 154 | newline-after-var: 0 155 | no-array-constructor: 0 156 | no-bitwise: 0 157 | no-continue: 0 158 | no-inline-comments: 0 159 | no-lonely-if: 0 160 | no-mixed-spaces-and-tabs: 0 161 | no-multiple-empty-lines: 0 162 | no-negated-condition: 0 163 | no-nested-ternary: 0 164 | no-new-object: 0 165 | no-plusplus: 0 166 | no-restricted-syntax: 0 167 | no-spaced-func: 0 168 | no-ternary: 0 169 | no-trailing-spaces: 0 170 | no-underscore-dangle: 0 171 | no-unneeded-ternary: 0 172 | object-curly-spacing: 0 173 | one-var: 0 174 | operator-assignment: 0 175 | operator-linebreak: 0 176 | padded-blocks: 0 177 | quote-props: 0 178 | quotes: 0 179 | require-jsdoc: 0 180 | semi-spacing: 0 181 | semi: 0 182 | sort-vars: 0 183 | space-after-keywords: 0 184 | space-before-blocks: 0 185 | space-before-function-paren: 0 186 | space-before-keywords: 0 187 | space-in-parens: 0 188 | space-infix-ops: 0 189 | space-return-throw-case: 0 190 | space-unary-ops: 0 191 | spaced-comment: 0 192 | wrap-regex: 0 193 | 194 | # ECMAScript 6 195 | arrow-body-style: 0 196 | arrow-parens: 0 197 | arrow-spacing: 0 198 | constructor-super: 0 199 | generator-star-spacing: 0 200 | no-arrow-condition: 0 201 | no-class-assign: 0 202 | no-const-assign: 0 203 | no-dupe-class-members: 0 204 | no-this-before-super: 0 205 | no-var: 0 206 | object-shorthand: 0 207 | prefer-arrow-callback: 0 208 | prefer-const: 0 209 | prefer-reflect: 0 210 | prefer-spread: 0 211 | prefer-template: 0 212 | require-yield: 0 213 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.swp 3 | coverage/ 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .hgignore 2 | .hgtags 3 | node_modules 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "15" 4 | - "14" 5 | - "10" 6 | - "8" 7 | script: 8 | - npm run coverage 9 | after_script: 10 | - npm install -g codeclimate-test-reporter 11 | - codeclimate-test-reporter < coverage/lcov.info 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # syslog-client 2 | 3 | [![Build Status](https://travis-ci.org/paulgrove/node-syslog-client.svg?branch=master)](https://travis-ci.org/paulgrove/node-syslog-client) [![Code Climate](https://codeclimate.com/github/paulgrove/node-syslog-client/badges/gpa.svg)](https://codeclimate.com/github/paulgrove/node-syslog-client) [![Test Coverage](https://codeclimate.com/github/paulgrove/node-syslog-client/badges/coverage.svg)](https://codeclimate.com/github/paulgrove/node-syslog-client/coverage) [![Issue Count](https://codeclimate.com/github/paulgrove/node-syslog-client/badges/issue_count.svg)](https://codeclimate.com/github/paulgrove/node-syslog-client) 4 | 5 | This module is a pure JavaScript implementation of the [BSD Syslog Protocol RFC 3164][1] and the [Syslog Protocol RFC 5424][2]. 6 | 7 | This module is installed using [node package manager (npm)][3]: 8 | 9 | ``` 10 | npm install syslog-client 11 | ``` 12 | 13 | It is loaded using the `require()` function: 14 | 15 | ```js 16 | var syslog = require("syslog-client"); 17 | ``` 18 | 19 | TCP or UDP clients can then be created to log messages to remote hosts. 20 | 21 | ```js 22 | var client = syslog.createClient("127.0.0.1"); 23 | 24 | client.log("example message"); 25 | ``` 26 | 27 | [1]: https://www.ietf.org/rfc/rfc3164.txt 28 | [2]: https://tools.ietf.org/html/rfc5424 29 | [3]: https://npmjs.org 30 | 31 | # Constants 32 | 33 | The following sections describe constants exported and used by this module. 34 | 35 | ## syslog.Transport 36 | 37 | This object contains constants for all valid values for the `transport` 38 | attribute passed to the `options` argument for the `createClient()` function. 39 | The following constants are defined in this object: 40 | 41 | * `Tcp` 42 | * `Udp` 43 | * `Tls` 44 | * `Unix` 45 | 46 | ## syslog.Facility 47 | 48 | This object contains constants for all valid values for the `facility` 49 | attribute passed to the `options` argument for the `log()` method on the 50 | `Client` class. The following constants are defined in this object: 51 | 52 | * `Kernel` - 0 53 | * `User` - 1 54 | * `Mail` - 2 55 | * `System` - 3 56 | * `Daemon` - 3 57 | * `Auth` - 4 58 | * `Syslog` - 5 59 | * `Lpr` - 6 60 | * `News` - 7 61 | * `Uucp` - 8 62 | * `Cron` - 9 63 | * `Authpriv` - 10 64 | * `Ftp` - 11 65 | * `Audit` - 13 66 | * `Alert` - 14 67 | * `Local0` - 16 68 | * `Local1` - 17 69 | * `Local2` - 18 70 | * `Local3` - 19 71 | * `Local4` - 20 72 | * `Local5` - 21 73 | * `Local6` - 22 74 | * `Local7` - 23 75 | 76 | ## syslog.Severity 77 | 78 | This object contains constants for all valid values for the `severity` 79 | attribute passed to the `options` argument for the `log()` method on the 80 | `Client` class. The following constants are defined in this object: 81 | 82 | * `Emergency` - 0 83 | * `Alert` - 1 84 | * `Critical` - 2 85 | * `Error` - 3 86 | * `Warning` - 4 87 | * `Notice` - 5 88 | * `Informational` - 6 89 | * `Debug` - 7 90 | 91 | # Using This Module 92 | 93 | All messages are sent using an instance of the `Client` class. This 94 | module exports the `createClient()` function which is used to create 95 | instances of the `Client` class. 96 | 97 | ## syslog.createClient([target], [options]) 98 | 99 | The `createClient()` function instantiates and returns an instance of the 100 | `Client` class: 101 | 102 | ```js 103 | // Default options 104 | var options = { 105 | syslogHostname: os.hostname(), 106 | transport: syslog.Transport.Udp, 107 | port: 514 108 | }; 109 | 110 | var client = syslog.createClient("127.0.0.1", options); 111 | ``` 112 | 113 | 114 | The optional `target` parameter defaults to `127.0.0.1`. The optional 115 | `options` parameter is an object, and can contain the following items: 116 | 117 | * `port` - TCP or UDP port to send messages to, defaults to `514` 118 | * `syslogHostname` - Value to place into the `HOSTNAME` part of the `HEADER` 119 | part of each message sent, defaults to `os.hostname()` 120 | * `tcpTimeout` - Number of milliseconds to wait for a connection attempt to 121 | the specified Syslog target, and the number of milliseconds to wait for 122 | TCP acknowledgements when sending messages using the TCP transport, 123 | defaults to `10000` (i.e. 10 seconds) 124 | * `transport` - Specify the transport to use, can be either 125 | `syslog.Transport.Udp` or `syslog.Transport.Tcp` or `syslog.Transport.Unix`, defaults to 126 | `syslog.Transport.Udp` 127 | * `facility` - set default for `client.log()`; default is `syslog.Facility.Local0`. 128 | * `severity` - set default for `client.log()`; default is `syslog.Severity.Informational`. 129 | * `rfc3164` - set to false to use [RFC 5424](https://tools.ietf.org/html/rfc5424) 130 | syslog header format; default is true for the older [RFC 3164](https://tools.ietf.org/html/rfc3164) 131 | format. 132 | * `appName` - set the APP-NAME field when using `rfc5424`; default uses `process.title` 133 | * `dateFormatter` - change the default date formatter when using `rfc5424`; interface: `function(date) { return string; }`; defaults to `function(date) { return date.toISOString(); }` 134 | * `udpBindAddress` - set to bind an UDP socket only on a specific address; default node behavior is to bind to `0.0.0.0` (all network adresses of the machine) 135 | 136 | For Unix sockets (TCP only), set `target` to the path of Unix socket. 137 | 138 | ## client.on("close", callback) 139 | 140 | The `close` event is emitted by the client when the clients underlying TCP or 141 | UDP socket is closed. 142 | 143 | No arguments are passed to the callback. 144 | 145 | The following example prints a message to the console when a clients 146 | underlying TCP or UDP socket is closed: 147 | 148 | ```js 149 | client.on("close", function () { 150 | console.log("socket closed"); 151 | }); 152 | ``` 153 | 154 | ## client.on("error", callback) 155 | 156 | The `error` event is emitted by the client when the clients underlying TCP or 157 | UDP socket emits an error. 158 | 159 | The following arguments will be passed to the `callback` function: 160 | 161 | * `error` - An instance of the `Error` class, the exposed `message` attribute 162 | will contain a detailed error message. 163 | 164 | The following example prints a message to the console when an error occurs 165 | with a clients underlying TCP or UDP socket: 166 | 167 | ```js 168 | client.on("error", function (error) { 169 | console.error(error); 170 | }); 171 | ``` 172 | 173 | ## client.close() 174 | 175 | The `close()` method closes the clients underlying TCP or UDP socket. This 176 | will result in the `close` event being emitted by the clients underlying TCP 177 | or UDP socket which is passed through to the client, resulting in the client 178 | also emitting a `close` event. 179 | 180 | The following example closes a clients underlying TCP or UDP socket: 181 | 182 | ```js 183 | client.close(); 184 | ``` 185 | 186 | ## client.log(message, [options], [callback]) 187 | 188 | The `log()` method sends a Syslog message to a remote host. 189 | 190 | The `message` parameter is a string containing the message to be logged. 191 | 192 | The optional `options` parameter is an object, and can contain the following 193 | items: 194 | 195 | * `facility` - Either one of the constants defined in the `syslog.Facility` 196 | object or the facility number to use for the message, defaults to 197 | `syslog.Facility.Local0` (see `syslog.createClient()`) 198 | * `severity` - Either one of the constants defined in the `syslog.Severity` 199 | object or the severity number to use for the message, defaults to 200 | `syslog.Severity.Informational` (see `syslog.createClient()`) 201 | * `rfc3164` - set to false to use [RFC 5424](https://tools.ietf.org/html/rfc5424) 202 | syslog header format; default is true for the older [RFC 3164](https://tools.ietf.org/html/rfc3164) 203 | format. 204 | * `timestamp` - Optional Javascript Date() object to back-date the message. 205 | * `msgid` - Optional [RFC 5424](https://tools.ietf.org/html/rfc5424) message-id. 206 | 207 | The `callback` function is called once the message has been sent to the remote 208 | host, or an error occurred. The following arguments will be passed to the 209 | `callback` function: 210 | 211 | * `error` - Instance of the `Error` class or a sub-class, or `null` if no 212 | error occurred 213 | 214 | Each message sent to the remote host will have a newline character appended 215 | to it, if one is not already appended. Care should be taken to ensure newline 216 | characters are not embedded within the message passed to this method (i.e. not 217 | appearing at the end), as this may cause some syslog relays/servers to 218 | incorrectly parse the message. 219 | 220 | The following example sends a message to a remote host: 221 | 222 | ```js 223 | var options = { 224 | facility: syslog.Facility.Daemon, 225 | severity: syslog.Severity.Critical 226 | }; 227 | 228 | var message "something is wrong with this daemon!"; 229 | 230 | client.log(message, options, function(error) { 231 | if (error) { 232 | console.error(error); 233 | } else { 234 | console.log("sent message successfully"); 235 | } 236 | }); 237 | ``` 238 | 239 | # Example Programs 240 | 241 | Example programs are included under the modules `example` directory. 242 | 243 | # Running tests and test coverage 244 | 245 | Tests can be run with: 246 | 247 | ``` 248 | npm test 249 | ``` 250 | 251 | Install dev dependencies before running test coverage: 252 | 253 | ``` 254 | npm install --dev 255 | npm run coverage 256 | ``` 257 | 258 | Coverage should be generated into `coverage/lcov-report/index.html`. 259 | 260 | # Changes 261 | 262 | ## Version 1.0.0 - 31/07/2015 263 | 264 | * Initial release 265 | 266 | ## Version 1.0.1 - 31/07/2015 267 | 268 | * Correct typo in README.md 269 | 270 | ## Version 1.0.2 - 31/07/2015 271 | 272 | * Correct typo in README.md :( 273 | 274 | ## Version 1.0.3 - 01/08/2015 275 | 276 | * Correct typo in README.md :( :( 277 | 278 | ## Version 1.0.4 - 08/08/2015 279 | 280 | * Transport error events are not propagated to an error event in the Syslog 281 | client 282 | 283 | ## Version 1.0.5 - 22/10/2015 284 | 285 | * Redundant release 286 | 287 | ## Version 1.0.6 - 22/10/2015 288 | 289 | * Slight formatting error in the README.md file 290 | 291 | ## Version 1.0.7 - 08/02/2016 292 | 293 | * Remove debug `console.dir()` statement accidently left in code 294 | 295 | ## Version 1.0.8 - 26/08/2016 296 | 297 | * Variable `key` in `_expandConstantObject()` missing `var` declaration 298 | 299 | ## Version 1.0.9 - 27/10/2016 300 | 301 | * Added mocha test framework 302 | * Added istanbul test coverage 303 | * Added tests for aprox 89% coverage 304 | * Fixed bug where transports where not being reused 305 | * Fixed bug where some connections would not `close()` 306 | * Made `options` in `.log()` optional as per existing documentation 307 | * Make `cb` in `.log()` optional and update documentation 308 | * Fixed bug where `error` event and `.log` callback wouldn't predictably receive error 309 | * `close` event is now always fired when `.close()` is called, regarless of open connection 310 | * New maintainer Paul Grove 311 | * Updated License 312 | * Travis-CI and codeclimate build automation and badges 313 | * Code linted using eslint 314 | 315 | ## Version 1.0.10 - 27/10/2016 316 | 317 | * No changes, issues with publishing to npm 318 | 319 | ## Version 1.0.11 - 14/11/2016 320 | 321 | * Fix miscalculation of PRI for Emegency and Kernel Facitilty/Severity 322 | 323 | ## Version 1.1.0 - 18/05/2017 324 | 325 | * Fix issue resolving IP class from hostname 326 | * Call log callback asynchronously, preventing issues when closing in that callback 327 | * Support for RFC 5424 328 | * Fix erroneous space after PRI 329 | 330 | # Additional Contributors 331 | 332 | * SirWumpus (github) 333 | * acanimal (github) 334 | * cdscott (github) 335 | * mccarthy (github) 336 | * MarkHerhold (github) 337 | * JeremyBernier (github) 338 | 339 | # License 340 | 341 | Copyright (c) 2017 Paul Grove 342 | 343 | Permission is hereby granted, free of charge, to any person obtaining a copy 344 | of this software and associated documentation files (the "Software"), to deal 345 | in the Software without restriction, including without limitation the rights 346 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 347 | copies of the Software, and to permit persons to whom the Software is 348 | furnished to do so, subject to the following conditions: 349 | 350 | The above copyright notice and this permission notice shall be included in 351 | all copies or substantial portions of the Software. 352 | 353 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 354 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 355 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 356 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 357 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 358 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 359 | THE SOFTWARE. 360 | -------------------------------------------------------------------------------- /example/tcp-client.js: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2015 Stephen Vickers 3 | 4 | var syslog = require ("../"); 5 | 6 | if (process.argv.length < 5) { 7 | console.log ("usage: tcp-client " 8 | + " "); 9 | process.exit (1); 10 | } 11 | 12 | var target = process.argv[2]; 13 | var port = parseInt(process.argv[3]); 14 | var facility = process.argv[4]; 15 | var severity = process.argv[5]; 16 | var syslogHostname = process.argv[6]; 17 | var message = process.argv[7]; 18 | 19 | var createOptions = { 20 | syslogHostname: syslogHostname, 21 | transport: syslog.Transport.Tcp, 22 | port: port 23 | }; 24 | 25 | var client = syslog.createClient(target, createOptions); 26 | 27 | client.on("error", function(error) { 28 | console.error(error); 29 | client.close(); 30 | }); 31 | 32 | client.on("close", function() { 33 | console.log("connection closed"); 34 | }); 35 | 36 | var logOptions = { 37 | facility: syslog.Facility[facility], 38 | severity: syslog.Severity[severity] 39 | }; 40 | 41 | for (var i = 0; i < 10; i++) { 42 | client.log(message, logOptions, function(error) { 43 | if (error) { 44 | console.error(error); 45 | } else { 46 | console.log("sent message successfully"); 47 | } 48 | }); 49 | } 50 | -------------------------------------------------------------------------------- /example/udp-client.js: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2015 Stephen Vickers 3 | 4 | var syslog = require ("../"); 5 | 6 | if (process.argv.length < 5) { 7 | console.log ("usage: udp-client " 8 | + " "); 9 | process.exit (1); 10 | } 11 | 12 | var target = process.argv[2]; 13 | var port = parseInt(process.argv[3]); 14 | var facility = process.argv[4]; 15 | var severity = process.argv[5]; 16 | var syslogHostname = process.argv[6]; 17 | var message = process.argv[7]; 18 | 19 | var createOptions = { 20 | syslogHostname: syslogHostname, 21 | transport: syslog.Transport.Udp, 22 | port: port 23 | }; 24 | 25 | var client = syslog.createClient(target, createOptions); 26 | 27 | client.on("error", function(error) { 28 | console.error(error); 29 | client.close(); 30 | }); 31 | 32 | client.on("close", function() { 33 | console.log("connection closed"); 34 | }); 35 | 36 | var logOptions = { 37 | facility: syslog.Facility[facility], 38 | severity: syslog.Severity[severity] 39 | }; 40 | 41 | for (var i = 0; i < 10; i++) { 42 | client.log(message, logOptions, function(error) { 43 | if (error) { 44 | console.error(error); 45 | } else { 46 | console.log("sent message successfully"); 47 | } 48 | }); 49 | } 50 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for syslog-client 2 | import { EventEmitter } from 'events'; 3 | 4 | export enum Transport { 5 | Tcp = 1, 6 | Udp = 2, 7 | Tls = 3, 8 | Unix = 4 9 | } 10 | 11 | export enum Facility { 12 | Kernel = 0, 13 | User = 1, 14 | Mail = 2, 15 | System = 3, 16 | Daemon = 3, 17 | Auth = 4, 18 | Syslog = 5, 19 | Lpr = 6, 20 | News = 7, 21 | Uucp = 8, 22 | Cron = 9, 23 | Authpriv = 10, 24 | Ftp = 11, 25 | Audit = 13, 26 | Alert = 14, 27 | Local0 = 16, 28 | Local1 = 17, 29 | Local2 = 18, 30 | Local3 = 19, 31 | Local4 = 20, 32 | Local5 = 21, 33 | Local6 = 22, 34 | Local7 = 23 35 | } 36 | 37 | export enum Severity { 38 | Emergency = 0, 39 | Alert = 1, 40 | Critical = 2, 41 | Error = 3, 42 | Warning = 4, 43 | Notice = 5, 44 | Informational = 6, 45 | Debug = 7 46 | } 47 | 48 | export interface ClientOptions { 49 | syslogHostname?: string, 50 | port?: number, 51 | tcpTimeout?: number, 52 | facility?: Facility, 53 | severity?: Severity, 54 | rfc3164?: boolean, 55 | appName?: string, 56 | dateFormatter?: (() => string), 57 | transport?: Transport, 58 | timestamp?: Date, 59 | msgid?: string, 60 | udpBindAddress: string 61 | } 62 | 63 | export interface MessageOptions { 64 | syslogHostname?: string, 65 | facility?: Facility, 66 | severity?: Severity, 67 | rfc3164?: boolean, 68 | appName?: string, 69 | timestamp?: Date, 70 | msgid?: string 71 | } 72 | 73 | export class Client extends EventEmitter { 74 | constructor(target?: string, options?: ClientOptions); 75 | buildFormattedMessage(message: string, options: MessageOptions): Buffer; 76 | close(): Client; 77 | log(message: string, options?: MessageOptions, cb?: ((error: Error | null) => void)): Client; 78 | getTransport(cb: ((error: Error | null, transport: Transport) => void)): void; 79 | onClose(): Client; 80 | onError(error: Error): Client; 81 | } 82 | 83 | export function createClient(target: string, options: ClientOptions): Client; 84 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2015-2016 Stephen Vickers 3 | // with contributions 2017 by Seth Blumberg 4 | 5 | var dgram = require("dgram"); 6 | var events = require("events"); 7 | var net = require("net"); 8 | var os = require("os"); 9 | var tls = require("tls"); 10 | var util = require("util"); 11 | 12 | function _expandConstantObject(object) { 13 | var keys = []; 14 | for (var key in object) 15 | if (Object.hasOwnProperty.call(object, key)) 16 | keys.push(key); 17 | for (var i = 0; i < keys.length; i++) 18 | object[object[keys[i]]] = parseInt(keys[i], 10); 19 | } 20 | 21 | var Transport = { 22 | Tcp: 1, 23 | Udp: 2, 24 | Tls: 3, 25 | Unix: 4 26 | }; 27 | 28 | _expandConstantObject(Transport); 29 | 30 | var Facility = { 31 | Kernel: 0, 32 | User: 1, 33 | Mail: 2, 34 | System: 3, 35 | Daemon: 3, 36 | Auth: 4, 37 | Syslog: 5, 38 | Lpr: 6, 39 | News: 7, 40 | Uucp: 8, 41 | Cron: 9, 42 | Authpriv: 10, 43 | Ftp: 11, 44 | Audit: 13, 45 | Alert: 14, 46 | Local0: 16, 47 | Local1: 17, 48 | Local2: 18, 49 | Local3: 19, 50 | Local4: 20, 51 | Local5: 21, 52 | Local6: 22, 53 | Local7: 23 54 | }; 55 | 56 | _expandConstantObject(Facility); 57 | 58 | var Severity = { 59 | Emergency: 0, 60 | Alert: 1, 61 | Critical: 2, 62 | Error: 3, 63 | Warning: 4, 64 | Notice: 5, 65 | Informational: 6, 66 | Debug: 7 67 | }; 68 | 69 | _expandConstantObject(Severity); 70 | 71 | function Client(target, options) { 72 | this.target = target || "127.0.0.1"; 73 | 74 | if (!options) 75 | options = {} 76 | 77 | this.syslogHostname = options.syslogHostname || os.hostname(); 78 | this.port = options.port || 514; 79 | this.tcpTimeout = options.tcpTimeout || 10000; 80 | this.getTransportRequests = []; 81 | this.facility = typeof options.facility !== "number" || Facility.Local0; 82 | this.severity = typeof options.severity !== "number" || Severity.Informational; 83 | this.rfc3164 = typeof options.rfc3164 === 'boolean' ? options.rfc3164 : true; 84 | this.appName = options.appName || process.title.substring(process.title.lastIndexOf("/")+1, 48); 85 | this.dateFormatter = options.dateFormatter || function() { return this.toISOString(); }; 86 | this.udpBindAddress = options.udpBindAddress; 87 | 88 | this.transport = Transport.Udp; 89 | if (options.transport && 90 | options.transport === Transport.Udp || 91 | options.transport === Transport.Tcp || 92 | options.transport === Transport.Unix || 93 | options.transport === Transport.Tls) 94 | this.transport = options.transport; 95 | if (this.transport === Transport.Tls) { 96 | this.tlsCA = options.tlsCA; 97 | } 98 | 99 | return this; 100 | } 101 | 102 | util.inherits(Client, events.EventEmitter); 103 | 104 | Client.prototype.buildFormattedMessage = function buildFormattedMessage(message, options) { 105 | // Some applications, like LTE CDR collection, need to be able to 106 | // back-date log messages based on CDR timestamps across different 107 | // time zones, because of delayed record collection with 3rd parties. 108 | // Particular useful in when feeding CDRs to Splunk for indexing. 109 | var date = (typeof options.timestamp === 'undefined') ? new Date() : options.timestamp; 110 | 111 | var pri = (options.facility * 8) + options.severity; 112 | 113 | var newline = message[message.length - 1] === "\n" ? "" : "\n"; 114 | 115 | var timestamp, formattedMessage; 116 | if (typeof options.rfc3164 !== 'boolean' || options.rfc3164) { 117 | // RFC 3164 uses an obsolete date/time format and header. 118 | var elems = date.toString().split(/\s+/); 119 | 120 | var month = elems[1]; 121 | var day = elems[2]; 122 | var time = elems[4]; 123 | 124 | /** 125 | ** BSD syslog requires leading 0's to be a space. 126 | **/ 127 | if (day[0] === "0") 128 | day = " " + day.substr(1, 1); 129 | 130 | timestamp = month + " " + day + " " + time; 131 | 132 | formattedMessage = "<" 133 | + pri 134 | + ">" 135 | + timestamp 136 | + " " 137 | + options.syslogHostname 138 | + " " 139 | + message 140 | + newline; 141 | } else { 142 | // RFC 5424 obsoletes RFC 3164 and requires RFC 3339 143 | // (ISO 8601) timestamps and slightly different header. 144 | 145 | var msgid = (typeof options.msgid === 'undefined') ? "-" : options.msgid; 146 | 147 | 148 | formattedMessage = "<" 149 | + pri 150 | + ">1" // VERSION 1 151 | + " " 152 | + this.dateFormatter.call(date) 153 | + " " 154 | + options.syslogHostname 155 | + " " 156 | + options.appName 157 | + " " 158 | + process.pid 159 | + " " 160 | + msgid 161 | + " - " // no STRUCTURED-DATA 162 | + message 163 | + newline; 164 | } 165 | 166 | return Buffer.from(formattedMessage); 167 | }; 168 | 169 | Client.prototype.close = function close() { 170 | if (this.transport_) { 171 | if (this.transport === Transport.Tcp || this.transport === Transport.Tls || this.transport === Transport.Unix) 172 | this.transport_.destroy(); 173 | if (this.transport === Transport.Udp) 174 | this.transport_.close(); 175 | this.transport_ = undefined; 176 | } else { 177 | this.onClose(); 178 | } 179 | 180 | return this; 181 | }; 182 | 183 | Client.prototype.log = function log() { 184 | var message, options = {}, cb; 185 | 186 | if (typeof arguments[0] === "string") 187 | message = arguments[0]; 188 | else 189 | throw new Error("first argument must be string"); 190 | 191 | if (typeof arguments[1] === "function") 192 | cb = arguments[1]; 193 | else if (typeof arguments[1] === "object") 194 | options = arguments[1]; 195 | if (typeof arguments[2] === "function") 196 | cb = arguments[2]; 197 | 198 | if (!cb) 199 | cb = function () {}; 200 | 201 | if (typeof options.facility === "undefined") { 202 | options.facility = this.facility; 203 | } 204 | if (typeof options.severity === "undefined") { 205 | options.severity = this.severity; 206 | } 207 | if (typeof options.rfc3164 !== "boolean") { 208 | options.rfc3164 = this.rfc3164; 209 | } 210 | if (typeof options.appName === "undefined") { 211 | options.appName = this.appName; 212 | } 213 | if (typeof options.syslogHostname === "undefined") { 214 | options.syslogHostname = this.syslogHostname; 215 | } 216 | 217 | var fm = this.buildFormattedMessage(message, options); 218 | 219 | var me = this; 220 | 221 | me.getTransport(function(error, transport) { 222 | if (error) 223 | return cb(error); 224 | 225 | try { 226 | if (me.transport === Transport.Tcp || me.transport === Transport.Tls || me.transport === Transport.Unix) { 227 | transport.write(fm, function(error) { 228 | if (error) 229 | return cb(new Error("net.write() failed: " + error.message)); 230 | return cb(); 231 | }); 232 | } else if (me.transport === Transport.Udp) { 233 | transport.send(fm, 0, fm.length, me.port, me.target, function(error, bytes) { 234 | if (error) { 235 | return cb(new Error("dgram.send() failed: " + error.message)); 236 | } 237 | return cb(); 238 | }); 239 | } else { 240 | return cb(new Error("unknown transport '%s' specified to Client", me.transport)); 241 | } 242 | } catch (err) { 243 | me.onError(err); 244 | return cb(err); 245 | } 246 | }); 247 | 248 | return this; 249 | }; 250 | 251 | Client.prototype.getTransport = function getTransport(cb) { 252 | if (this.transport_ !== undefined) 253 | return cb(null, this.transport_); 254 | 255 | this.getTransportRequests.push(cb); 256 | 257 | if (this.connecting) 258 | return this; 259 | else 260 | this.connecting = true; 261 | 262 | var af = net.isIPv6(this.target) ? 6 : 4; 263 | 264 | var me = this; 265 | 266 | function doCb(error, transport) { 267 | while (me.getTransportRequests.length > 0) { 268 | var nextCb = me.getTransportRequests.shift(); 269 | nextCb(error, transport); 270 | } 271 | 272 | me.connecting = false; 273 | } 274 | 275 | if (this.transport === Transport.Tcp || this.transport === Transport.Unix) { 276 | var options; 277 | if (this.transport === Transport.Unix) { 278 | options = { 279 | path: this.target 280 | }; 281 | } 282 | else { 283 | options = { 284 | host: this.target, 285 | port: this.port, 286 | family: af 287 | }; 288 | } 289 | 290 | var transport; 291 | try { 292 | transport = net.createConnection(options, function() { 293 | me.transport_ = transport; 294 | doCb(null, me.transport_); 295 | }); 296 | } catch (err) { 297 | doCb(err); 298 | me.onError(err); 299 | } 300 | 301 | if (!transport) 302 | return; 303 | 304 | transport.setTimeout(this.tcpTimeout, function() { 305 | var err = new Error("connection timed out"); 306 | transport.destroy(); 307 | me.emit("error", err); 308 | doCb(err); 309 | }); 310 | 311 | transport.once("connect", function () { 312 | transport.setTimeout(0); 313 | }); 314 | 315 | transport.on("end", function() { 316 | var err = new Error("connection closed"); 317 | me.emit("error", err); 318 | doCb(err); 319 | }); 320 | 321 | transport.on("close", me.onClose.bind(me)); 322 | transport.on("error", function (err) { 323 | transport.destroy(); 324 | doCb(err); 325 | me.onError(err); 326 | }); 327 | 328 | transport.unref(); 329 | } else if (this.transport === Transport.Tls) { 330 | var tlsOptions = { 331 | host: this.target, 332 | port: this.port, 333 | family: af, 334 | ca: this.tlsCA, 335 | secureProtocol: 'TLSv1_2_method' 336 | }; 337 | 338 | var tlsTransport; 339 | try { 340 | tlsTransport = tls.connect(tlsOptions, function() { 341 | me.transport_ = tlsTransport; 342 | doCb(null, me.transport_); 343 | }); 344 | } catch (err) { 345 | doCb(err); 346 | me.onError(err); 347 | } 348 | 349 | if (!tlsTransport) 350 | 351 | return; 352 | 353 | tlsTransport.setTimeout(this.tcpTimeout, function() { 354 | var err = new Error("connection timed out"); 355 | me.emit("error", err); 356 | doCb(err); 357 | }); 358 | 359 | tlsTransport.once("connect", function () { 360 | tlsTransport.setTimeout(0); 361 | }); 362 | 363 | tlsTransport.on("end", function() { 364 | var err = new Error("connection closed"); 365 | me.emit("error", err); 366 | doCb(err); 367 | }); 368 | 369 | tlsTransport.on("close", me.onClose.bind(me)); 370 | tlsTransport.on("error", function (err) { 371 | doCb(err); 372 | me.onError(err); 373 | }); 374 | 375 | tlsTransport.unref(); 376 | } else if (this.transport === Transport.Udp) { 377 | try { 378 | this.transport_ = dgram.createSocket("udp" + af); 379 | 380 | // if not binding on a particular address 381 | // node will bind to 0.0.0.0 382 | if (this.udpBindAddress) { 383 | // avoid binding to all addresses 384 | this.transport_.bind({ address: this.udpBindAddress }) 385 | } 386 | } 387 | catch (err) { 388 | try { 389 | this.transport_.destroy(); 390 | } catch (err2) { 391 | // ignore cleanup error 392 | } 393 | doCb(err); 394 | this.onError(err); 395 | } 396 | 397 | if (!this.transport_) 398 | return; 399 | 400 | this.transport_.on("close", this.onClose.bind(this)); 401 | this.transport_.on("error", function (err) { 402 | me.onError(err); 403 | doCb(err); 404 | }); 405 | 406 | this.transport_.unref(); 407 | 408 | doCb(null, this.transport_); 409 | } else { 410 | doCb(new Error("unknown transport '%s' specified to Client", this.transport)); 411 | } 412 | }; 413 | 414 | Client.prototype.onClose = function onClose() { 415 | if (this.transport_) { 416 | if (this.transport_.destroy) 417 | this.transport_.destroy(); 418 | this.transport_ = undefined; 419 | } 420 | 421 | this.emit("close"); 422 | 423 | return this; 424 | }; 425 | 426 | Client.prototype.onError = function onError(error) { 427 | if (this.transport_) { 428 | if (this.transport_.destroy) 429 | this.transport_.destroy(); 430 | this.transport_ = undefined; 431 | } 432 | 433 | this.emit("error", error); 434 | 435 | return this; 436 | }; 437 | 438 | exports.Client = Client; 439 | 440 | exports.createClient = function createClient(target, options) { 441 | return new Client(target, options); 442 | }; 443 | 444 | exports.Transport = Transport; 445 | exports.Facility = Facility; 446 | exports.Severity = Severity; 447 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "syslog-client", 3 | "version": "1.2.0", 4 | "description": "TCP and UDP syslog client RFC 5424 & RFC 3164", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha --reporter spec --exit", 8 | "coverage": "nyc --reporter=lcov --reporter=text-summary npm run test" 9 | }, 10 | "directories": { 11 | "example": "example" 12 | }, 13 | "dependencies": {}, 14 | "contributors": [ 15 | { 16 | "name": "Paul Grove", 17 | "email": "paul.a.grove@gmail.com" 18 | }, 19 | { 20 | "name": "Stephen Vickers", 21 | "email": "stephen.vickers.sv@gmail.com" 22 | }, 23 | { 24 | "name": "Tim Garthwaite", 25 | "email": "tim@mividstudios.com" 26 | }, 27 | { 28 | "name": "Seth Blumberg", 29 | "email": "sethb@pobox.com" 30 | } 31 | ], 32 | "repository": { 33 | "type": "git", 34 | "url": "git://github.com/paulgrove/node-syslog-client.git" 35 | }, 36 | "keywords": [ 37 | "logger", 38 | "logging", 39 | "syslog", 40 | "syslog-client", 41 | "syslog-logger", 42 | "syslog-logging", 43 | "tcp-syslog", 44 | "tcp-syslog-client", 45 | "udp-syslog", 46 | "udp-syslog-client", 47 | "tls" 48 | ], 49 | "author": "Paul Grove ", 50 | "license": "MIT", 51 | "devDependencies": { 52 | "bluebird": "^3.4.6", 53 | "chai": "^3.5.0", 54 | "mocha": "^10.1.0", 55 | "nyc": "^15.1.0" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ref/rfc/rfc3164.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Network Working Group C. Lonvick 8 | Request for Comments: 3164 Cisco Systems 9 | Category: Informational August 2001 10 | 11 | 12 | The BSD syslog Protocol 13 | 14 | Status of this Memo 15 | 16 | This memo provides information for the Internet community. It does 17 | not specify an Internet standard of any kind. Distribution of this 18 | memo is unlimited. 19 | 20 | Copyright Notice 21 | 22 | Copyright (C) The Internet Society (2001). All Rights Reserved. 23 | 24 | Abstract 25 | 26 | This document describes the observed behavior of the syslog protocol. 27 | This protocol has been used for the transmission of event 28 | notification messages across networks for many years. While this 29 | protocol was originally developed on the University of California 30 | Berkeley Software Distribution (BSD) TCP/IP system implementations, 31 | its value to operations and management has led it to be ported to 32 | many other operating systems as well as being embedded into many 33 | other networked devices. 34 | 35 | Table of Contents 36 | 37 | 1. Introduction....................................................2 38 | 1.1 Events and Generated Messages..................................3 39 | 1.2 Operations of the Message Receivers............................5 40 | 2. Transport Layer Protocol........................................5 41 | 3. Definitions and Architecture....................................5 42 | 4. Packet Format and Contents......................................7 43 | 4.1 syslog Message Parts...........................................8 44 | 4.1.1 PRI Part.....................................................8 45 | 4.1.2 HEADER Part of a syslog Packet..............................10 46 | 4.1.3 MSG Part of a syslog Packet.................................11 47 | 4.2 Original syslog Packets Generated by a Device.................12 48 | 4.3 Relayed syslog Packets........................................12 49 | 4.3.1 Valid PRI and TIMESTAMP.....................................13 50 | 4.3.2 Valid PRI but no TIMESTAMP or invalid TIMESTAMP.............13 51 | 4.3.3 No PRI or Unidentifiable PRI................................14 52 | 5. Conventions....................................................14 53 | 5.1 Dates and Times...............................................15 54 | 5.2 Domain Name and Address.......................................15 55 | 56 | 57 | 58 | Lonvick Informational [Page 1] 59 | 60 | RFC 3164 The BSD syslog Protocol August 2001 61 | 62 | 63 | 5.3 Originating Process Information...............................15 64 | 5.4 Examples......................................................16 65 | 6. Security Considerations........................................18 66 | 6.1 Packet Parameters.............................................19 67 | 6.2 Message Authenticity..........................................19 68 | 6.2.1 Authentication Problems.....................................19 69 | 6.2.2 Message Forgery.............................................20 70 | 6.3 Sequenced Delivery............................................20 71 | 6.3.1 Single Source to a Destination..............................20 72 | 6.3.2 Multiple Sources to a Destination...........................21 73 | 6.3.3 Multiple Sources to Multiple Destinations...................21 74 | 6.3.4 Replaying...................................................22 75 | 6.4 Reliable Delivery.............................................22 76 | 6.5 Message Integrity.............................................22 77 | 6.6 Message Observation...........................................22 78 | 6.7 Message Prioritization and Differentiation....................23 79 | 6.8 Misconfiguration..............................................24 80 | 6.9 Forwarding Loop...............................................24 81 | 6.10 Load Considerations..........................................25 82 | 7. IANA Considerations............................................25 83 | 8. Conclusion and Other Efforts...................................25 84 | Acknowledgements..................................................26 85 | References........................................................27 86 | Author's Address..................................................28 87 | Full Copyright Statement..........................................29 88 | 89 | 1. Introduction 90 | 91 | Since the beginning, life has relied upon the transmission of 92 | messages. For the self-aware organic unit, these messages can relay 93 | many different things. The messages may signal danger, the presence 94 | of food or the other necessities of life, and many other things. In 95 | many cases, these messages are informative to other units and require 96 | no acknowledgement. As people interacted and created processes, this 97 | same principle was applied to societal communications. As an 98 | example, severe weather warnings may be delivered through any number 99 | of channels - a siren blowing, warnings delivered over television and 100 | radio stations, and even through the use of flags on ships. The 101 | expectation is that people hearing or seeing these warnings would 102 | realize their significance and take appropriate action. In most 103 | cases, no responding acknowledgement of receipt of the warning is 104 | required or even desired. Along these same lines, operating systems, 105 | processes and applications were written to send messages of their own 106 | status, or messages to indicate that certain events had occurred. 107 | These event messages generally had local significance to the machine 108 | operators. As the operating systems, processes and applications grew 109 | ever more complex, systems were devised to categorize and log these 110 | diverse messages and allow the operations staff to more quickly 111 | 112 | 113 | 114 | Lonvick Informational [Page 2] 115 | 116 | RFC 3164 The BSD syslog Protocol August 2001 117 | 118 | 119 | differentiate the notifications of problems from simple status 120 | messages. The syslog process was one such system that has been 121 | widely accepted in many operating systems. Flexibility was designed 122 | into this process so the operations staff have the ability to 123 | configure the destination of messages sent from the processes running 124 | on the device. In one dimension, the events that were received by 125 | the syslog process could be logged to different files and also 126 | displayed on the console of the device. In another dimension, the 127 | syslog process could be configured to forward the messages across a 128 | network to the syslog process on another machine. The syslog process 129 | had to be built network-aware for some modicum of scalability since 130 | it was known that the operators of multiple systems would not have 131 | the time to access each system to review the messages logged there. 132 | The syslog process running on the remote devices could therefore be 133 | configured to either add the message to a file, or to subsequently 134 | forward it to another machine. 135 | 136 | In its most simplistic terms, the syslog protocol provides a 137 | transport to allow a machine to send event notification messages 138 | across IP networks to event message collectors - also known as syslog 139 | servers. Since each process, application and operating system was 140 | written somewhat independently, there is little uniformity to the 141 | content of syslog messages. For this reason, no assumption is made 142 | upon the formatting or contents of the messages. The protocol is 143 | simply designed to transport these event messages. In all cases, 144 | there is one device that originates the message. The syslog process 145 | on that machine may send the message to a collector. No 146 | acknowledgement of the receipt is made. 147 | 148 | One of the fundamental tenets of the syslog protocol and process is 149 | its simplicity. No stringent coordination is required between the 150 | transmitters and the receivers. Indeed, the transmission of syslog 151 | messages may be started on a device without a receiver being 152 | configured, or even actually physically present. Conversely, many 153 | devices will most likely be able to receive messages without explicit 154 | configuration or definitions. This simplicity has greatly aided the 155 | acceptance and deployment of syslog. 156 | 157 | 1.1 Events and Generated Messages 158 | 159 | The writers of the operating systems, processes and applications have 160 | had total control over the circumstances that would generate any 161 | message. In some cases, messages are generated to give status. These 162 | can be either at a certain period of time, or at some other interval 163 | such as the invocation or exit of a program. In other cases, the 164 | messages may be generated due to a set of conditions being met. In 165 | those cases, either a status message or a message containing an alarm 166 | of some type may be generated. It was considered that the writers of 167 | 168 | 169 | 170 | Lonvick Informational [Page 3] 171 | 172 | RFC 3164 The BSD syslog Protocol August 2001 173 | 174 | 175 | the operating systems, processes and applications would quantify 176 | their messages into one of several broad categories. These broad 177 | categories generally consist of the facility that generated them, 178 | along with an indication of the severity of the message. This was so 179 | that the operations staff could selectively filter the messages and 180 | be presented with the more important and time sensitive notifications 181 | quickly, while also having the ability to place status or informative 182 | messages in a file for later perusal. Other options for displaying 183 | or storing messages have been seen to exist as well. 184 | 185 | Devices MUST be configured with rules for displaying and/or 186 | forwarding the event messages. The rules that have been seen are 187 | generally very flexible. An administrator may want to have all 188 | messages stored locally as well as to have all messages of a high 189 | severity forwarded to another device. They may find it appropriate 190 | to also have messages from a particular facility sent to some or all 191 | of the users of the device and displayed on the system console. 192 | However the administrator decides to configure the disposition of the 193 | event messages, the process of having them sent to a syslog collector 194 | generally consists of deciding which facility messages and which 195 | severity levels will be forwarded, and then defining the remote 196 | receiver. For example, an administrator may want all messages that 197 | are generated by the mail facility to be forwarded to one particular 198 | event message collector. Then the administrator may want to have all 199 | kernel generated messages sent to a different syslog receiver while, 200 | at the same time, having the critically severe messages from the 201 | kernel also sent to a third receiver. It may also be appropriate to 202 | have those messages displayed on the system console as well as being 203 | mailed to some appropriate people, while at the same time, being sent 204 | to a file on the local disk of the device. Conversely, it may be 205 | appropriate to have messages from a locally defined process only 206 | displayed on the console but not saved or forwarded from the device. 207 | In any event, the rules for this will have to be generated on the 208 | device. Since the administrators will then know which types of 209 | messages will be received on the collectors, they should then make 210 | appropriate rules on those syslog servers as well. 211 | 212 | The contents of a message have also been at the discretion of its 213 | creator. It has been considered to be good form to write the 214 | messages so that they are informative to the person who may be 215 | reading them. It has also been considered good practice to include a 216 | timestamp and some indication of the sending device and the process 217 | that originated it in the messages. However, none of those are 218 | stringently required. 219 | 220 | It should be assumed that any process on any device might generate an 221 | event message. This may include processes on machines that do not 222 | have any local storage - e.g., printers, routers, hubs, switches, and 223 | 224 | 225 | 226 | Lonvick Informational [Page 4] 227 | 228 | RFC 3164 The BSD syslog Protocol August 2001 229 | 230 | 231 | diskless workstations. In that case, it may be imperative that event 232 | messages are transported to a collector so that they may be recorded 233 | and hopefully viewed by an operator. 234 | 235 | 1.2 Operations of the Message Receivers 236 | 237 | It is beyond the scope of this document to specify how event messages 238 | should be processed when they are received. Like the operations 239 | described in Section 1.1, they generally may be displayed to the 240 | appropriate people, saved onto disk, further forwarded, or any 241 | combination of these. The rules for determining the disposition of 242 | received messages have been seen to be identical to the rules for 243 | determining the disposition of locally generated messages. 244 | 245 | As a very general rule, there are usually many devices sending 246 | messages to relatively fewer collectors. This fan-in process allows 247 | an administrator to aggregate messages into relatively few 248 | repositories. 249 | 250 | 2. Transport Layer Protocol 251 | 252 | syslog uses the user datagram protocol (UDP) [1] as its underlying 253 | transport layer mechanism. The UDP port that has been assigned to 254 | syslog is 514. It is RECOMMENDED that the source port also be 514 to 255 | indicate that the message is from the syslog process of the sender, 256 | but there have been cases seen where valid syslog messages have come 257 | from a sender with a source port other than 514. If the sender uses 258 | a source port other than 514 then it is RECOMMENDED and has been 259 | considered to be good form that subsequent messages are from a single 260 | consistent port. 261 | 262 | 3. Definitions and Architecture 263 | 264 | The following definitions will be used in this document. 265 | 266 | A machine that can generate a message will be called a 267 | "device". 268 | 269 | A machine that can receive the message and forward it to 270 | another machine will be called a "relay". 271 | 272 | A machine that receives the message and does not relay it to 273 | any other machines will be called a "collector". This has been 274 | commonly known as a "syslog server". 275 | 276 | Any device or relay will be known as the "sender" when it sends 277 | a message. 278 | 279 | 280 | 281 | 282 | Lonvick Informational [Page 5] 283 | 284 | RFC 3164 The BSD syslog Protocol August 2001 285 | 286 | 287 | Any relay or collector will be known as the "receiver" when it 288 | receives the message. 289 | 290 | The architecture of the devices may be summarized as follows: 291 | 292 | Senders send messages to relays or collectors with no knowledge 293 | of whether it is a collector or relay. 294 | 295 | Senders may be configured to send the same message to multiple 296 | receivers. 297 | 298 | Relays may send all or some of the messages that they receive 299 | to a subsequent relay or collector. In the case where they do 300 | not forward all of their messages, they are acting as both a 301 | collector and a relay. In the following diagram, these devices 302 | will be designated as relays. 303 | 304 | Relays may also generate their own messages and send them on to 305 | subsequent relays or collectors. In that case it is acting as 306 | a device. These devices will also be designated as a relay in 307 | the following diagram. 308 | 309 | The following architectures shown in Diagram 1 are valid while the 310 | first one has been known to be the most prevalent. Other 311 | arrangements of these examples are also acceptable. As noted above, 312 | in the following diagram relays may pass along all or some of the 313 | messages that they receive along with passing along messages that 314 | they internally generate. 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | Lonvick Informational [Page 6] 339 | 340 | RFC 3164 The BSD syslog Protocol August 2001 341 | 342 | 343 | +------+ +---------+ 344 | |Device|---->----|Collector| 345 | +------+ +---------+ 346 | 347 | +------+ +-----+ +---------+ 348 | |Device|---->----|Relay|---->----|Collector| 349 | +------+ +-----+ +---------+ 350 | 351 | +------+ +-----+ +-----+ +---------+ 352 | |Device|-->--|Relay|-->--..-->--|Relay|-->--|Collector| 353 | +------+ +-----+ +-----+ +---------+ 354 | 355 | +------+ +-----+ +---------+ 356 | |Device|---->----|Relay|---->----|Collector| 357 | | |-\ +-----+ +---------+ 358 | +------+ \ 359 | \ +-----+ +---------+ 360 | \-->--|Relay|---->----|Collector| 361 | +-----+ +---------+ 362 | 363 | +------+ +---------+ 364 | |Device|---->----|Collector| 365 | | |-\ +---------+ 366 | +------+ \ 367 | \ +-----+ +---------+ 368 | \-->--|Relay|---->----|Collector| 369 | +-----+ +---------+ 370 | 371 | +------+ +-----+ +---------+ 372 | |Device|---->----|Relay|---->-------|Collector| 373 | | |-\ +-----+ /--| | 374 | +------+ \ / +---------+ 375 | \ +-----+ / 376 | \-->--|Relay|-->--/ 377 | +-----+ 378 | 379 | Diagram 1. Some Possible syslog Architectures 380 | 381 | 4. Packet Format and Contents 382 | 383 | The payload of any IP packet that has a UDP destination port of 514 384 | MUST be treated as a syslog message. There MAY be differences 385 | between the format of an originally transmitted syslog message and 386 | the format of a relayed message. In essence, it is RECOMMENDED to 387 | transmit a syslog message in the format specified in this document, 388 | but it is not required. If a relay is able to recognize the message 389 | as adhering to that format then it MUST retransmit the message 390 | without making any changes to it. However, if a relay receives a 391 | 392 | 393 | 394 | Lonvick Informational [Page 7] 395 | 396 | RFC 3164 The BSD syslog Protocol August 2001 397 | 398 | 399 | message but cannot discern the proper implementation of the format, 400 | it is REQUIRED to modify the message so that it conforms to that 401 | format before it retransmits it. Section 4.1 will describe the 402 | RECOMMENDED format for syslog messages. Section 4.2 will describe 403 | the requirements for originally transmitted messages and Section 4.3 404 | will describe the requirements for relayed messages. 405 | 406 | 4.1 syslog Message Parts 407 | 408 | The full format of a syslog message seen on the wire has three 409 | discernable parts. The first part is called the PRI, the second part 410 | is the HEADER, and the third part is the MSG. The total length of 411 | the packet MUST be 1024 bytes or less. There is no minimum length of 412 | the syslog message although sending a syslog packet with no contents 413 | is worthless and SHOULD NOT be transmitted. 414 | 415 | 4.1.1 PRI Part 416 | 417 | The PRI part MUST have three, four, or five characters and will be 418 | bound with angle brackets as the first and last characters. The PRI 419 | part starts with a leading "<" ('less-than' character), followed by a 420 | number, which is followed by a ">" ('greater-than' character). The 421 | code set used in this part MUST be seven-bit ASCII in an eight-bit 422 | field as described in RFC 2234 [2]. These are the ASCII codes as 423 | defined in "USA Standard Code for Information Interchange" [3]. In 424 | this, the "<" character is defined as the Augmented Backus-Naur Form 425 | (ABNF) %d60, and the ">" character has ABNF value %d62. The number 426 | contained within these angle brackets is known as the Priority value 427 | and represents both the Facility and Severity as described below. 428 | The Priority value consists of one, two, or three decimal integers 429 | (ABNF DIGITS) using values of %d48 (for "0") through %d57 (for "9"). 430 | 431 | The Facilities and Severities of the messages are numerically coded 432 | with decimal values. Some of the operating system daemons and 433 | processes have been assigned Facility values. Processes and daemons 434 | that have not been explicitly assigned a Facility may use any of the 435 | "local use" facilities or they may use the "user-level" Facility. 436 | Those Facilities that have been designated are shown in the following 437 | table along with their numerical code values. 438 | 439 | Numerical Facility 440 | Code 441 | 442 | 0 kernel messages 443 | 1 user-level messages 444 | 2 mail system 445 | 3 system daemons 446 | 4 security/authorization messages (note 1) 447 | 448 | 449 | 450 | Lonvick Informational [Page 8] 451 | 452 | RFC 3164 The BSD syslog Protocol August 2001 453 | 454 | 455 | 5 messages generated internally by syslogd 456 | 6 line printer subsystem 457 | 7 network news subsystem 458 | 8 UUCP subsystem 459 | 9 clock daemon (note 2) 460 | 10 security/authorization messages (note 1) 461 | 11 FTP daemon 462 | 12 NTP subsystem 463 | 13 log audit (note 1) 464 | 14 log alert (note 1) 465 | 15 clock daemon (note 2) 466 | 16 local use 0 (local0) 467 | 17 local use 1 (local1) 468 | 18 local use 2 (local2) 469 | 19 local use 3 (local3) 470 | 20 local use 4 (local4) 471 | 21 local use 5 (local5) 472 | 22 local use 6 (local6) 473 | 23 local use 7 (local7) 474 | 475 | Table 1. syslog Message Facilities 476 | 477 | Note 1 - Various operating systems have been found to utilize 478 | Facilities 4, 10, 13 and 14 for security/authorization, 479 | audit, and alert messages which seem to be similar. 480 | Note 2 - Various operating systems have been found to utilize 481 | both Facilities 9 and 15 for clock (cron/at) messages. 482 | 483 | Each message Priority also has a decimal Severity level indicator. 484 | These are described in the following table along with their numerical 485 | values. 486 | 487 | Numerical Severity 488 | Code 489 | 490 | 0 Emergency: system is unusable 491 | 1 Alert: action must be taken immediately 492 | 2 Critical: critical conditions 493 | 3 Error: error conditions 494 | 4 Warning: warning conditions 495 | 5 Notice: normal but significant condition 496 | 6 Informational: informational messages 497 | 7 Debug: debug-level messages 498 | 499 | Table 2. syslog Message Severities 500 | 501 | 502 | 503 | 504 | 505 | 506 | Lonvick Informational [Page 9] 507 | 508 | RFC 3164 The BSD syslog Protocol August 2001 509 | 510 | 511 | The Priority value is calculated by first multiplying the Facility 512 | number by 8 and then adding the numerical value of the Severity. For 513 | example, a kernel message (Facility=0) with a Severity of Emergency 514 | (Severity=0) would have a Priority value of 0. Also, a "local use 4" 515 | message (Facility=20) with a Severity of Notice (Severity=5) would 516 | have a Priority value of 165. In the PRI part of a syslog message, 517 | these values would be placed between the angle brackets as <0> and 518 | <165> respectively. The only time a value of "0" will follow the "<" 519 | is for the Priority value of "0". Otherwise, leading "0"s MUST NOT be 520 | used. 521 | 522 | 4.1.2 HEADER Part of a syslog Packet 523 | 524 | The HEADER part contains a timestamp and an indication of the 525 | hostname or IP address of the device. The HEADER part of the syslog 526 | packet MUST contain visible (printing) characters. The code set used 527 | MUST also be seven-bit ASCII in an eight-bit field like that used in 528 | the PRI part. In this code set, the only allowable characters are 529 | the ABNF VCHAR values (%d33-126) and spaces (SP value %d32). 530 | 531 | The HEADER contains two fields called the TIMESTAMP and the HOSTNAME. 532 | The TIMESTAMP will immediately follow the trailing ">" from the PRI 533 | part and single space characters MUST follow each of the TIMESTAMP 534 | and HOSTNAME fields. HOSTNAME will contain the hostname, as it knows 535 | itself. If it does not have a hostname, then it will contain its own 536 | IP address. If a device has multiple IP addresses, it has usually 537 | been seen to use the IP address from which the message is 538 | transmitted. An alternative to this behavior has also been seen. In 539 | that case, a device may be configured to send all messages using a 540 | single source IP address regardless of the interface from which the 541 | message is sent. This will provide a single consistent HOSTNAME for 542 | all messages sent from a device. 543 | 544 | The TIMESTAMP field is the local time and is in the format of "Mmm dd 545 | hh:mm:ss" (without the quote marks) where: 546 | 547 | Mmm is the English language abbreviation for the month of the 548 | year with the first character in uppercase and the other two 549 | characters in lowercase. The following are the only acceptable 550 | values: 551 | 552 | Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec 553 | 554 | dd is the day of the month. If the day of the month is less 555 | than 10, then it MUST be represented as a space and then the 556 | number. For example, the 7th day of August would be 557 | represented as "Aug 7", with two spaces between the "g" and 558 | the "7". 559 | 560 | 561 | 562 | Lonvick Informational [Page 10] 563 | 564 | RFC 3164 The BSD syslog Protocol August 2001 565 | 566 | 567 | hh:mm:ss is the local time. The hour (hh) is represented in a 568 | 24-hour format. Valid entries are between 00 and 23, 569 | inclusive. The minute (mm) and second (ss) entries are between 570 | 00 and 59 inclusive. 571 | 572 | A single space character MUST follow the TIMESTAMP field. 573 | 574 | The HOSTNAME field will contain only the hostname, the IPv4 address, 575 | or the IPv6 address of the originator of the message. The preferred 576 | value is the hostname. If the hostname is used, the HOSTNAME field 577 | MUST contain the hostname of the device as specified in STD 13 [4]. 578 | It should be noted that this MUST NOT contain any embedded spaces. 579 | The Domain Name MUST NOT be included in the HOSTNAME field. If the 580 | IPv4 address is used, it MUST be shown as the dotted decimal notation 581 | as used in STD 13 [5]. If an IPv6 address is used, any valid 582 | representation used in RFC 2373 [6] MAY be used. A single space 583 | character MUST also follow the HOSTNAME field. 584 | 585 | 4.1.3 MSG Part of a syslog Packet 586 | 587 | The MSG part will fill the remainder of the syslog packet. This will 588 | usually contain some additional information of the process that 589 | generated the message, and then the text of the message. There is no 590 | ending delimiter to this part. The MSG part of the syslog packet 591 | MUST contain visible (printing) characters. The code set 592 | traditionally and most often used has also been seven-bit ASCII in an 593 | eight-bit field like that used in the PRI and HEADER parts. In this 594 | code set, the only allowable characters are the ABNF VCHAR values 595 | (%d33-126) and spaces (SP value %d32). However, no indication of the 596 | code set used within the MSG is required, nor is it expected. Other 597 | code sets MAY be used as long as the characters used in the MSG are 598 | exclusively visible characters and spaces similar to those described 599 | above. The selection of a code set used in the MSG part SHOULD be 600 | made with thoughts of the intended receiver. A message containing 601 | characters in a code set that cannot be viewed or understood by a 602 | recipient will yield no information of value to an operator or 603 | administrator looking at it. 604 | 605 | The MSG part has two fields known as the TAG field and the CONTENT 606 | field. The value in the TAG field will be the name of the program or 607 | process that generated the message. The CONTENT contains the details 608 | of the message. This has traditionally been a freeform message that 609 | gives some detailed information of the event. The TAG is a string of 610 | ABNF alphanumeric characters that MUST NOT exceed 32 characters. Any 611 | non-alphanumeric character will terminate the TAG field and will be 612 | assumed to be the starting character of the CONTENT field. Most 613 | commonly, the first character of the CONTENT field that signifies the 614 | 615 | 616 | 617 | 618 | Lonvick Informational [Page 11] 619 | 620 | RFC 3164 The BSD syslog Protocol August 2001 621 | 622 | 623 | conclusion of the TAG field has been seen to be the left square 624 | bracket character ("["), a colon character (":"), or a space 625 | character. This is explained in more detail in Section 5.3. 626 | 627 | 4.2 Original syslog Packets Generated by a Device 628 | 629 | There are no set requirements on the contents of the syslog packet as 630 | it is originally sent from a device. It should be reiterated here 631 | that the payload of any IP packet destined to UDP port 514 MUST be 632 | considered to be a valid syslog message. It is, however, RECOMMENDED 633 | that the syslog packet have all of the parts described in Section 4.1 634 | - PRI, HEADER and MSG - as this enhances readability by the recipient 635 | and eliminates the need for a relay to modify the message. 636 | 637 | For implementers that do choose to construct syslog messages with the 638 | RECOMMENDED format, the following guidance is offered. 639 | 640 | If the originally formed message has a TIMESTAMP in the HEADER 641 | part, then it SHOULD be the local time of the device within its 642 | timezone. 643 | 644 | If the originally formed message has a HOSTNAME field, then it 645 | will contain the hostname as it knows itself. If it does not 646 | have a hostname, then it will contain its own IP address. 647 | 648 | If the originally formed message has a TAG value, then that 649 | will be the name of the program or process that generated the 650 | message. 651 | 652 | 4.3 Relayed syslog Packets 653 | 654 | When a relay receives a packet, it will check for a valid PRI. If 655 | the first character is not a less-than sign, the relay MUST assume 656 | that the packet does not contain a valid PRI. If the 3rd, 4th, or 657 | 5th character is not a right angle bracket character, the relay again 658 | MUST assume that the PRI was not included in the original message. 659 | If the relay does find a valid PRI part then it must check for a 660 | valid TIMESTAMP in the HEADER part. From these rules, there will be 661 | three general cases of received messages. Table 3 gives the general 662 | characteristics of these cases and lists the subsequent section of 663 | this document that describes the handling of that case. 664 | 665 | Case Section 666 | Valid PRI and TIMESTAMP 4.3.1 667 | Valid PRI but no TIMESTAMP or invalid TIMESTAMP 4.3.2 668 | No PRI or unidentifiable PRI 4.3.3 669 | 670 | Table 3. Cases of Received syslog Messages 671 | 672 | 673 | 674 | Lonvick Informational [Page 12] 675 | 676 | RFC 3164 The BSD syslog Protocol August 2001 677 | 678 | 679 | 4.3.1 Valid PRI and TIMESTAMP 680 | 681 | If the relay does find a valid PRI and a valid TIMESTAMP, then it 682 | will check its internal configuration. Relays MUST be configured to 683 | forward syslog packets on the basis of their Priority value. If the 684 | relay finds that it is configured to forward the received packet, 685 | then it MUST do so without making any changes to the packet. To 686 | emphasize the point one more time, it is for this reason that it is 687 | RECOMMENDED that the syslog message originally transmitted adhere to 688 | the format described in Section 4.1. 689 | 690 | It should be noted here that the message receiver does not need to 691 | validate the time in the TIMESTAMP field. The assumption may be made 692 | that a device whose date has not been correctly set will still have 693 | the ability to send valid syslog messages. Additionally, the relay 694 | does not need to validate that the value in the HOSTNAME field 695 | matches the hostname or IP address of the device sending the message. 696 | A reason for this behavior may be found in Section 4.1.2. 697 | 698 | 4.3.2 Valid PRI but no TIMESTAMP or invalid TIMESTAMP 699 | 700 | If a relay does not find a valid TIMESTAMP in a received syslog 701 | packet, then it MUST add a TIMESTAMP and a space character 702 | immediately after the closing angle bracket of the PRI part. It 703 | SHOULD additionally add a HOSTNAME and a space character after the 704 | TIMESTAMP. These fields are described here and detailed in Section 705 | 4.1.2. The remainder of the received packet MUST be treated as the 706 | CONTENT field of the MSG and appended. Since the relay would have no 707 | way to determine the originating process from the device that 708 | originated the message, the TAG value cannot be determined and will 709 | not be included. 710 | 711 | The TIMESTAMP will be the current local time of the relay. 712 | 713 | The HOSTNAME will be the name of the device, as it is known by the 714 | relay. If the name cannot be determined, the IP address of the 715 | device will be used. 716 | 717 | If the relay adds a TIMESTAMP, or a TIMESTAMP and HOSTNAME, after the 718 | PRI part, then it MUST check that the total length of the packet is 719 | still 1024 bytes or less. If the packet has been expanded beyond 720 | 1024 bytes, then the relay MUST truncate the packet to be 1024 bytes. 721 | This may cause the loss of vital information from the end of the 722 | original packet. It is for this reason that it is RECOMMENDED that 723 | the PRI and HEADER parts of originally generated syslog packets 724 | contain the values and fields documented in Section 4.1. 725 | 726 | 727 | 728 | 729 | 730 | Lonvick Informational [Page 13] 731 | 732 | RFC 3164 The BSD syslog Protocol August 2001 733 | 734 | 735 | 4.3.3 No PRI or Unidentifiable PRI 736 | 737 | If the relay receives a syslog message without a PRI, or with an 738 | unidentifiable PRI, then it MUST insert a PRI with a Priority value 739 | of 13 as well as a TIMESTAMP as described in Section 4.3.2. The 740 | relay SHOULD also insert a HOSTNAME as described in Section 4.3.2. 741 | The entire contents of the received packet will be treated as the 742 | CONTENT of the relayed MSG and appended. 743 | 744 | An example of an unidentifiable PRI would be "<00>", without the 745 | double quotes. It may be that these are the first 4 characters of 746 | the message. To continue this example, if a relay does receive a 747 | syslog message with the first four characters of "<00>", then it will 748 | consult its configuration. If it is configured to forward syslog 749 | messages with a Priority value of 13 to another relay or collector, 750 | then it MUST modify the packet as described above. The specifics of 751 | doing this, including the RECOMMENDED insertion of the HOSTNAME, are 752 | given below. 753 | 754 | Originally received message 755 | <00>... 756 | Relayed message 757 | <13>TIMESTAMP HOSTNAME <00>... 758 | 759 | If the relay adds a TIMESTAMP, or a TIMESTAMP and HOSTNAME, after the 760 | PRI part, then it MUST check that the total length of the packet is 761 | still 1024 bytes or less. If the packet has been expanded beyond 762 | 1024 bytes, then the relay MUST truncate the packet to be 1024 bytes. 763 | This may cause the loss of vital information from the end of the 764 | original packet. It is for this reason that it is RECOMMENDED that 765 | the PRI and HEADER parts of originally generated syslog packets 766 | contain the values and fields documented in Section 4.1. 767 | 768 | 5. Conventions 769 | 770 | Although Section 4 of this document specifies all requirements for 771 | the syslog protocol format and contents, certain conventions have 772 | come about over time for the inclusion of additional information 773 | within the syslog message. It must be plainly stated that these 774 | items are not mandated but may be considered by implementers for 775 | completeness and to give the recipient some additional clues of their 776 | origin and nature. 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | Lonvick Informational [Page 14] 787 | 788 | RFC 3164 The BSD syslog Protocol August 2001 789 | 790 | 791 | 5.1 Dates and Times 792 | 793 | It has been found that some network administrators like to archive 794 | their syslog messages over long periods of time. It has been seen 795 | that some original syslog messages contain a more explicit time stamp 796 | in which a 2 character or 4 character year field immediately follows 797 | the space terminating the TIMESTAMP. This is not consistent with the 798 | original intent of the order and format of the fields. If 799 | implementers wish to contain a more specific date and time stamp 800 | within the transmitted message, it should be within the CONTENT 801 | field. Implementers may wish to utilize the ISO 8601 [7] date and 802 | time formats if they want to include more explicit date and time 803 | information. 804 | 805 | Additional methods to address this desire for long-term archiving 806 | have been proposed and some have been successfully implemented. One 807 | such method is that the network administrators may choose to modify 808 | the messages stored on their collectors. They may run a simple 809 | script to add the year, and any other information, to each stored 810 | record. Alternatively, the script may replace the stored time with a 811 | format more appropriate for the needs of the network administrators. 812 | Another alternative has been to insert a record into the file that 813 | contains the current year. By association then, all other records 814 | near that informative record should have been received in that same 815 | year. Neither of these however, addresses the issue of associating a 816 | correct timezone with each record. 817 | 818 | 5.2 Domain Name and Address 819 | 820 | To readily identify the device that originated the message, it may be 821 | a good practice to include its fully qualified domain name (FQDN) and 822 | its IP address within the CONTENT field. Traditionally, however, 823 | only the hostname has been included in the HOSTNAME field. 824 | 825 | 5.3 Originating Process Information 826 | 827 | It has also been considered to be a good practice to include some 828 | information about the process on the device that generated the 829 | message - if that concept exists. This is usually the process name 830 | and process id (often known as the "pid") for robust operating 831 | systems. The process name is commonly displayed in the TAG field. 832 | Quite often, additional information is included at the beginning of 833 | the CONTENT field. The format of "TAG[pid]:" - without the quote 834 | marks - is common. The left square bracket is used to terminate the 835 | TAG field in this case and is then the first character in the CONTENT 836 | field. If the process id is immaterial, it may be left off. 837 | 838 | 839 | 840 | 841 | 842 | Lonvick Informational [Page 15] 843 | 844 | RFC 3164 The BSD syslog Protocol August 2001 845 | 846 | 847 | In that case, a colon and a space character usually follow the TAG. 848 | This would be displayed as "TAG: " without the quotes. In that case, 849 | the colon is the first character in the CONTENT field. 850 | 851 | 5.4 Examples 852 | 853 | As examples, these are valid messages as they may be observed on the 854 | wire between two devices. In the following examples, each message 855 | has been indented, with line breaks inserted in this document for 856 | readability. 857 | 858 | Example 1 859 | 860 | <34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick 861 | on /dev/pts/8 862 | 863 | This example shows an authentication error in an attempt to acquire 864 | additional privileges. It also shows the command attempted and the 865 | user attempting it. This was recorded as an original message from 866 | the device called mymachine. A relay receiving this would not make 867 | any changes before sending it along as it contains a properly 868 | formatted PRI part and TIMESTAMP field in the HEADER part. The TAG 869 | value in this example is the process "su". The colon has terminated 870 | the TAG field and is the first character of the CONTENT field. In 871 | this case, the process id (pid) would be considered transient and 872 | anyone looking at this syslog message would gain no useful 873 | information from knowing the pid. It has not been included so the 874 | first two characters of the CONTENT field are the colon and a space 875 | character. 876 | 877 | Example 2 878 | 879 | Use the BFG! 880 | 881 | While this is a valid message, it has extraordinarily little useful 882 | information. This message does not have any discernable PRI part. It 883 | does not contain a timestamp or any indication of the source of the 884 | message. If this message is stored on paper or disk, subsequent 885 | review of the message will not yield anything of value. 886 | 887 | This example is obviously an original message from a device. A relay 888 | MUST make changes to the message as described in Section 4.3 before 889 | forwarding it. The resulting relayed message is shown below. 890 | 891 | <13>Feb 5 17:32:18 10.0.0.99 Use the BFG! 892 | 893 | 894 | 895 | 896 | 897 | 898 | Lonvick Informational [Page 16] 899 | 900 | RFC 3164 The BSD syslog Protocol August 2001 901 | 902 | 903 | In this relayed message, the entire message has been treated as the 904 | CONTENT portion of the MSG part. First, a valid PRI part has been 905 | added using the default priority value of 13. Next, a TIMESTAMP has 906 | been added along with a HOSTNAME in the HEADER part. Subsequent 907 | relays will not make any further changes to this message. It should 908 | be noted in this example that the day of the month is less than 10. 909 | Since single digits in the date (5 in this case) are preceded by a 910 | space in the TIMESTAMP format, there are two spaces following the 911 | month in the TIMESTAMP before the day of the month. Also, the relay 912 | appears to have no knowledge of the host name of the device sending 913 | the message so it has inserted the IPv4 address of the device into 914 | the HOSTNAME field. 915 | 916 | Example 3 917 | 918 | <165>Aug 24 05:34:00 CST 1987 mymachine myproc[10]: %% It's 919 | time to make the do-nuts. %% Ingredients: Mix=OK, Jelly=OK # 920 | Devices: Mixer=OK, Jelly_Injector=OK, Frier=OK # Transport: 921 | Conveyer1=OK, Conveyer2=OK # %% 922 | 923 | This message does have a valid PRI part with a Priority value 924 | indicating that it came from a locally defined facility (local4) with 925 | a severity of Notice. The HEADER part has a proper TIMESTAMP field 926 | in the message. A relay will not modify this message before sending 927 | it. However, the HOSTNAME and TAG fields are not consistent with the 928 | definitions in Section 4. The HOSTNAME field would be construed to 929 | be "CST" and the beginning of the MSG part would be "1987". 930 | 931 | It should be noted that the information contained in the CONTENT of 932 | this example is not telemetry data, nor is it supervisory control or 933 | data acquisition information. Due to the security concerns listed in 934 | Section 6 of this document, information of that nature should 935 | probably not be conveyed across this protocol. 936 | 937 | Example 4 938 | 939 | <0>1990 Oct 22 10:52:01 TZ-6 scapegoat.dmz.example.org 10.1.2.3 940 | sched[0]: That's All Folks! 941 | 942 | This example has a lot of extraneous information throughout. A human 943 | or sufficiently adaptable automated parser would be able to determine 944 | the date and time information as well as a fully qualified domain 945 | name (FQDN) [4] and IP address. The information about the nature of 946 | the event is, however, limited. Due to the indicated severity of the 947 | event, the process may not have been able to gather or send anything 948 | more informative. It may have been fortunate to have generated and 949 | sent this message at all. 950 | 951 | 952 | 953 | 954 | Lonvick Informational [Page 17] 955 | 956 | RFC 3164 The BSD syslog Protocol August 2001 957 | 958 | 959 | This example is obviously an original message from a device. Since 960 | the first field in the HEADER part is not a TIMESTAMP in the format 961 | defined in Section 4.1.2, it MUST be modified by a relay. A relay 962 | will add a TIMESTAMP and SHOULD add a HOSTNAME as follows and will 963 | treat the entire received packet after the PRI part from the original 964 | packet as the CONTENT field of the new packet. The value used in the 965 | HOSTNAME field is only the hostname without the domain name as it is 966 | known by the relay. A TAG value will not be added to the relayed 967 | packet. While the inclusion of the domain name and IPv4 address in 968 | the original message is a noble endeavor, it is not consistent with 969 | the use of the field as described in Section 4.1.2. 970 | 971 | <0>Oct 22 10:52:12 scapegoat 1990 Oct 22 10:52:01 TZ-6 972 | scapegoat.dmz.example.org 10.1.2.3 sched[0]: That's All Folks! 973 | 974 | 6. Security Considerations 975 | 976 | An odor may be considered to be a message that does not require any 977 | acknowledgement. People tend to avoid bad odors but are drawn to 978 | odors that they associate with good food. The acknowledgement of the 979 | receipt of the odor or scent is not required and indeed it may be the 980 | height of discretion to totally ignore some odors. On the other 981 | hand, it is usually considered good civility to acknowledge the 982 | prowess of the cook merely from the ambiance wafting from the 983 | kitchen. Similarly, various species have been found to utilize odors 984 | to attract mates. One species of moth uses this scent to find each 985 | other. However, it has been found that bolas spiders can mimic the 986 | odor of the female moths of this species. This scent will then 987 | attract male moths, which will follow it with the expectation of 988 | finding a mate. Instead, when they arrive at the source of the 989 | scent, they will be eaten [8]. This is a case of a false message 990 | being sent out with inimical intent. 991 | 992 | In its local use, the syslog process places event notification 993 | messages into files on that system. This relies upon the integrity 994 | of the system for the protection of the messages. The subsequent 995 | configuration of the syslog process to use the syslog protocol to 996 | transport the messages to a remote collector was an extension of the 997 | delivery of event notification messages and it exhibits the same 998 | trust of the network. There are several security consequences of the 999 | fundamental simplicity of syslog and there are some concerns about 1000 | the applicability of this protocol in situations that require robust 1001 | delivery. Along the lines of the analogy, computer event messages 1002 | may be sent accidentally, erroneously and even maliciously. At the 1003 | time of this writing, however, there have not been any reports of any 1004 | networked device consuming any other device. 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | Lonvick Informational [Page 18] 1011 | 1012 | RFC 3164 The BSD syslog Protocol August 2001 1013 | 1014 | 1015 | 6.1 Packet Parameters 1016 | 1017 | As was described above, the message length MUST NOT exceed 1024 1018 | bytes. Attacks have seen where syslog messages are sent to a 1019 | receiver that have message lengths greater than 1024 bytes. In some 1020 | older versions of syslog, the receipt of syslog packets that had a 1021 | message greater than 1024 bytes caused problems. syslog message 1022 | receivers must not malfunction upon the receipt of packets where the 1023 | message length is greater than 1024 bytes. Various behaviors have 1024 | been seen on receivers that do receive messages greater than 1024 1025 | bytes. Some have been seen to log the entire contents of the 1026 | message, while others have been seen to log only portions of the 1027 | message. Still others have been known to discard the message 1028 | altogether. Devices MUST NOT retransmit messages whose received 1029 | length exceeds 1024 bytes. 1030 | 1031 | Similarly, the receiver must rigidly enforce the correctness of the 1032 | message body. syslog collectors must not malfunction if received 1033 | messages do not have the less-than and greater-than characters around 1034 | a valid Priority value. They MUST treat these messages as the 1035 | unformatted CONTENT as was described in Section 4.3.3 if they relay 1036 | it. 1037 | 1038 | Also, received messages must contain printable text in the message as 1039 | was described throughout Section 4. Devices must not malfunction if 1040 | they receive a message containing characters other than the 1041 | characters described above. 1042 | 1043 | 6.2 Message Authenticity 1044 | 1045 | The syslog delivery mechanism does not strongly associate the message 1046 | with the message sender. The receiver of that packet will not be 1047 | able to ascertain that the message was indeed sent from the reported 1048 | sender, or if the packet was sent from another device. It should be 1049 | noted here that the message receiver does not need to verify that the 1050 | HOSTNAME in the HEADER part match the name of the IP address 1051 | contained in the Source Address field of the IP packet. 1052 | 1053 | 6.2.1 Authentication Problems 1054 | 1055 | One possible consequence of this behavior is that a misconfigured 1056 | machine may send syslog messages to a collector representing itself 1057 | as another machine. The administrative staff may become confused 1058 | that the status of the supposed sender of the messages may not be 1059 | accurately reflected in the received messages. The administrators 1060 | may not be able to readily discern that there are two or more 1061 | machines representing themselves as the same machine. 1062 | 1063 | 1064 | 1065 | 1066 | Lonvick Informational [Page 19] 1067 | 1068 | RFC 3164 The BSD syslog Protocol August 2001 1069 | 1070 | 1071 | It should also be noted that some cases of filling the HOSTNAME field 1072 | in the HEADER part might only have local significance and that may 1073 | only be ephemeral. If the device had obtained an IP address from a 1074 | DHCP pool, then any association between an identifier and an actual 1075 | source would not always hold true. The inclusion of a fully 1076 | qualified domain name in the CONTENT may give the administrators the 1077 | best chance of identifying the source of each message if it can 1078 | always be associated with an IP address or if it can always be 1079 | associated with a unique machine. 1080 | 1081 | 6.2.2 Message Forgery 1082 | 1083 | Malicious exploits of this behavior have also been noted. An 1084 | attacker may transmit syslog messages (either from the machine from 1085 | which the messages are purportedly sent or from any other machine) to 1086 | a collector. In one case, an attacker may hide the true nature of an 1087 | attack amidst many other messages. As an example, an attacker may 1088 | start generating forged messages indicating a problem on some 1089 | machine. This may get the attention of the system administrators who 1090 | will spend their time investigating the alleged problem. During this 1091 | time, the attacker may be able to compromise a different machine, or 1092 | a different process on the same machine. Additionally, an attacker 1093 | may generate false syslog messages to give untrue indications of 1094 | status or of events. As an example, an attacker may stop a critical 1095 | process on a machine, which may generate a notification of exit. The 1096 | attacker may subsequently generate a forged notification that the 1097 | process had been restarted. The system administrators may accept 1098 | that misinformation and not verify that the process had indeed been 1099 | restarted. 1100 | 1101 | 6.3 Sequenced Delivery 1102 | 1103 | As a general rule, the forensics of a network anomaly rely upon 1104 | reconstructing the sequence of events. In a perfect world, the 1105 | messages would be received on the syslog collector in the order of 1106 | their generation from the other devices and anyone looking at these 1107 | records would have an accurate picture of the sequence of events. 1108 | Unfortunately, the syslog process and protocol do not ensure ordered 1109 | delivery. This section details some of the problems that may be 1110 | encountered from this. 1111 | 1112 | 6.3.1 Single Source to a Destination 1113 | 1114 | The syslog records are usually presented (placed in a file, displayed 1115 | on the console, etc.) in the order in which they are received. This 1116 | is not always in accordance with the sequence in which they were 1117 | generated. As they are transported across an IP network, some out of 1118 | order receipt should be expected. This may lead to some confusion as 1119 | 1120 | 1121 | 1122 | Lonvick Informational [Page 20] 1123 | 1124 | RFC 3164 The BSD syslog Protocol August 2001 1125 | 1126 | 1127 | messages may be received that would indicate that a process has 1128 | stopped before it was started. This may be somewhat rectified if the 1129 | originating process had timestamped or numbered each of the messages 1130 | before transmission. In this, the sending device should utilize an 1131 | authoritative time source. It should be remembered, however, that 1132 | not all devices are capable of receiving time updates, and not all 1133 | devices can timestamp their messages. 1134 | 1135 | 6.3.2 Multiple Sources to a Destination 1136 | 1137 | In syslog, there is no concept of unified event numbering. Single 1138 | devices are free to include a sequence number within the CONTENT but 1139 | that can hardly be coordinated between multiple devices. In such 1140 | cases, multiple devices may report that each one is sending message 1141 | number one. Again, this may be rectified somewhat if the sending 1142 | devices utilize a timestamp from an authoritative source in their 1143 | messages. As has been noted, however, even messages from a single 1144 | device to a single collector may be received out of order. This 1145 | situation is compounded when there are several devices configured to 1146 | send their syslog messages to a single collector. Messages from one 1147 | device may be delayed so the collector receives messages from another 1148 | device first even though the messages from the first device were 1149 | generated before the messages from the second. If there is no 1150 | timestamp or coordinated sequence number, then the messages may be 1151 | presented in the order in which they were received which may give an 1152 | inaccurate view of the sequence of actual events. 1153 | 1154 | 6.3.3 Multiple Sources to Multiple Destinations 1155 | 1156 | The plethora of configuration options available to the network 1157 | administrators may further skew the perception of the order of 1158 | events. It is possible to configure a group of devices to send the 1159 | status messages -or other informative messages- to one collector, 1160 | while sending messages of relatively higher importance to another 1161 | collector. Additionally, the messages may be sent to different files 1162 | on the same collector. If the messages do not contain timestamps 1163 | from the source, it may be difficult to order the messages if they 1164 | are kept in different places. An administrator may not be able to 1165 | determine if a record in one file occurred before or after a record 1166 | in a different file. This may be somewhat alleviated by placing 1167 | marking messages with a timestamp into all destination files. If 1168 | these have coordinated timestamps, then there will be some indication 1169 | of the time of receipt of the individual messages. 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | Lonvick Informational [Page 21] 1179 | 1180 | RFC 3164 The BSD syslog Protocol August 2001 1181 | 1182 | 1183 | 6.3.4 Replaying 1184 | 1185 | Without any sequence indication or timestamp, messages may be 1186 | recorded and replayed at a later time. An attacker may record a set 1187 | of messages that indicate normal activity of a machine. At a later 1188 | time, that attacker may remove that machine from the network and 1189 | replay the syslog messages to the collector. Even with a TIMESTAMP 1190 | field in the HEADER part, an attacker may record the packets and 1191 | could simply modify them to reflect the current time before 1192 | retransmitting them. The administrators may find nothing unusual in 1193 | the received messages and their receipt would falsely indicate normal 1194 | activity of the machine. 1195 | 1196 | 6.4 Reliable Delivery 1197 | 1198 | As there is no mechanism within either the syslog process or the 1199 | protocol to ensure delivery, and since the underlying transport is 1200 | UDP, some messages may be lost. They may either be dropped through 1201 | network congestion, or they may be maliciously intercepted and 1202 | discarded. The consequences of the drop of one or more syslog 1203 | messages cannot be determined. If the messages are simple status 1204 | updates, then their non-receipt may either not be noticed, or it may 1205 | cause an annoyance for the system operators. On the other hand, if 1206 | the messages are more critical, then the administrators may not 1207 | become aware of a developing and potentially serious problem. 1208 | Messages may also be intercepted and discarded by an attacker as a 1209 | way to hide unauthorized activities. 1210 | 1211 | 6.5 Message Integrity 1212 | 1213 | Besides being discarded, syslog messages may be damaged in transit, 1214 | or an attacker may maliciously modify them. In the case of a packet 1215 | containing a syslog message being damaged, there are various 1216 | mechanisms built into the link layer as well as into the IP [9] and 1217 | UDP protocols which may detect the damage. An intermediary router 1218 | may discard a damaged IP packet [10]. Damage to a UDP packet may be 1219 | detected by the receiving UDP module, which may silently discard it. 1220 | In any case, the original contents of the message will not be 1221 | delivered to the collector. Additionally, if an attacker is 1222 | positioned between the sender and collector of syslog messages, they 1223 | may be able to intercept and modify those messages while in-transit 1224 | to hide unauthorized activities. 1225 | 1226 | 6.6 Message Observation 1227 | 1228 | While there are no strict guidelines pertaining to the event message 1229 | format, most syslog messages are generated in human readable form 1230 | with the assumption that capable administrators should be able to 1231 | 1232 | 1233 | 1234 | Lonvick Informational [Page 22] 1235 | 1236 | RFC 3164 The BSD syslog Protocol August 2001 1237 | 1238 | 1239 | read them and understand their meaning. Neither the syslog protocol 1240 | nor the syslog application have mechanisms to provide confidentiality 1241 | of the messages in transit. In most cases passing clear-text 1242 | messages is a benefit to the operations staff if they are sniffing 1243 | the packets off of the wire. The operations staff may be able to 1244 | read the messages and associate them with other events seen from 1245 | other packets crossing the wire to track down and correct problems. 1246 | Unfortunately, an attacker may also be able to observe the human- 1247 | readable contents of syslog messages. The attacker may then use the 1248 | knowledge gained from those messages to compromise a machine or do 1249 | other damage. 1250 | 1251 | 6.7 Message Prioritization and Differentiation 1252 | 1253 | While the processes that create the messages may signify the 1254 | importance of the events through the use of the message Priority 1255 | value, there is no distinct association between this value and the 1256 | importance of delivery of the packet. As an example of this, 1257 | consider an application that generates two event messages. The first 1258 | is a normal status message but the second could be an important 1259 | message denoting a problem with the process. This second message 1260 | would have an appropriately higher Severity value associated with the 1261 | importance of that event. If the operators had configured that both 1262 | of these messages be transported to a syslog collector then they 1263 | would, in turn, be given to UDP for transmission. Under normal 1264 | conditions, no distinction would be made between them and they would 1265 | be transmitted in their order. 1266 | 1267 | Again, under normal circumstances, the receiver would accept syslog 1268 | messages as they are received. If many devices are transmitting 1269 | normal status messages, but one is transmitting an important event 1270 | message, there is no inherent mechanism within the syslog protocol to 1271 | prioritize the important message over the other messages. 1272 | 1273 | On a case-by-case basis, device operators may find some way to 1274 | associate the different levels with the quality of service 1275 | identifiers. As an example, the operators may elect to define some 1276 | linkage between syslog messages that have a specific Priority value 1277 | with a specific value to be used in the IPv4 Precedence field [9], 1278 | the IPv6 Traffic Class octet [11], or the Differentiated Services 1279 | field [12]. In the above example, the operators may have the ability 1280 | to associate the status message with normal delivery while 1281 | associating the message indicating a problem with a high reliability, 1282 | low latency queue as it goes through the network. This would have 1283 | the affect of prioritizing the essential messages before the normal 1284 | status messages. Even with this hop-by-hop prioritization, this 1285 | queuing mechanism could still lead to head of line blocking on the 1286 | transmitting device as well as buffer starvation on the receiving 1287 | 1288 | 1289 | 1290 | Lonvick Informational [Page 23] 1291 | 1292 | RFC 3164 The BSD syslog Protocol August 2001 1293 | 1294 | 1295 | device if there are many near-simultaneous messages being sent or 1296 | received. This behavior is not unique to syslog but is endemic to 1297 | all operations that transmit messages serially. 1298 | 1299 | There are security concerns for this behavior. Head of line blocking 1300 | of the transmission of important event messages may relegate the 1301 | conveyance of important messages behind less important messages. If 1302 | the queue is cleared appropriately, this may only add seconds to the 1303 | transmission of the important message. On the other hand, if the 1304 | queue is not cleared, then important messages may not be transmitted. 1305 | Also at the receiving side, if the syslog receiver is suffering from 1306 | buffer starvation due to large numbers of messages being received 1307 | near-simultaneously, important messages may be dropped 1308 | indiscriminately along with other messages. While these are problems 1309 | with the devices and their capacities, the protocol security concern 1310 | is that there is no prioritization of the relatively more important 1311 | messages over the less important messages. 1312 | 1313 | 6.8 Misconfiguration 1314 | 1315 | Since there is no control information distributed about any messages 1316 | or configurations, it is wholly the responsibility of the network 1317 | administrator to ensure that the messages are actually going to the 1318 | intended recipient. Cases have been noted where devices were 1319 | inadvertently configured to send syslog messages to the wrong 1320 | receiver. In many cases, the inadvertent receiver may not be 1321 | configured to receive syslog messages and it will probably discard 1322 | them. In certain other cases, the receipt of syslog messages has 1323 | been known to cause problems for the unintended recipient [13]. If 1324 | messages are not going to the intended recipient, then they cannot be 1325 | reviewed or processed. 1326 | 1327 | 6.9 Forwarding Loop 1328 | 1329 | As it is shown in Figure 1, machines may be configured to relay 1330 | syslog messages to subsequent relays before reaching a collector. In 1331 | one particular case, an administrator found that he had mistakenly 1332 | configured two relays to forward messages with certain Priority 1333 | values to each other. When either of these machines either received 1334 | or generated that type of message, it would forward it to the other 1335 | relay. That relay would, in turn, forward it back. This cycle did 1336 | cause degradation to the intervening network as well as to the 1337 | processing availability on the two devices. Network administrators 1338 | must take care to not cause such a death spiral. 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | Lonvick Informational [Page 24] 1347 | 1348 | RFC 3164 The BSD syslog Protocol August 2001 1349 | 1350 | 1351 | 6.10 Load Considerations 1352 | 1353 | Network administrators must take the time to estimate the appropriate 1354 | size of the syslog receivers. An attacker may perform a Denial of 1355 | Service attack by filling the disk of the collector with false 1356 | messages. Placing the records in a circular file may alleviate this 1357 | but that has the consequence of not ensuring that an administrator 1358 | will be able to review the records in the future. Along this line, a 1359 | receiver or collector must have a network interface capable of 1360 | receiving all messages sent to it. 1361 | 1362 | Administrators and network planners must also critically review the 1363 | network paths between the devices, the relays, and the collectors. 1364 | Generated syslog messages should not overwhelm any of the network 1365 | links. 1366 | 1367 | 7. IANA Considerations 1368 | 1369 | The syslog protocol has been assigned UDP port 514. This port 1370 | assignment will be maintained by IANA exclusively for this protocol. 1371 | 1372 | The syslog protocol provides for the definition of named attributes 1373 | to indicate the Severity of each message and the Facility that 1374 | generated the message as described in Section 4. The name space 1375 | identifiers for these attributes are defined as numbers. The 1376 | protocol does not define the specific assignment of the name space 1377 | for these numbers; the application developer or system vendor is 1378 | allowed to define the attribute, its semantics, and the associated 1379 | numbers. This name space will not be controlled to prevent 1380 | collisions as systems are expected to use the same attributes, 1381 | semantics and associated numbers to describe events that are deemed 1382 | similar even between heterogeneous devices. 1383 | 1384 | 8. Conclusion and Other Efforts 1385 | 1386 | The syslog protocol may be effectively used to transport event 1387 | notification messages across a network. In all cases, it is 1388 | important that the syslog message receiver embody the principle of 1389 | "be liberal in what you accept". It is highly recommended that the 1390 | network operators who choose to use this understand the 1391 | characteristics of the protocol and its security implications. 1392 | 1393 | There have been attempts in the past to standardize the format of the 1394 | syslog message. The most notable attempt culminated in a BOF at the 1395 | Fortieth Internet Engineering Task Force meeting in 1997. This was 1396 | the Universal Logging Protocol (ulp) BOF and the minutes of their 1397 | meeting are on-line at the IETF Proceedings web site [14]. 1398 | 1399 | 1400 | 1401 | 1402 | Lonvick Informational [Page 25] 1403 | 1404 | RFC 3164 The BSD syslog Protocol August 2001 1405 | 1406 | 1407 | Many good thoughts came from that effort and interested implementers 1408 | may want to find some of the notes or papers produced from that 1409 | effort. 1410 | 1411 | At the time of this writing, efforts are underway to allow the usage 1412 | of international character sets in applications that have been 1413 | traditionally thought of as being text-only. The HOSTNAME and 1414 | TIMESTAMP fields described above are representative of this. Also, 1415 | the entire CONTENT field has traditionally been printing characters 1416 | and spaces in the code set known as US-ASCII. It is hoped that the 1417 | proponents of these internationalization efforts will find a suitable 1418 | way to allow the use of international character sets within syslog 1419 | messages without being disruptive. It should also be hoped that 1420 | implementers will allow for the future acceptance of additional code 1421 | sets and that they may make appropriate plans. Again, it must be 1422 | cautioned that the simplicity of the existing system has been a 1423 | tremendous value to its acceptance. Anything that lessens that 1424 | simplicity may diminish that value. 1425 | 1426 | Acknowledgements 1427 | 1428 | The following people provided content feedback during the writing of 1429 | this document: 1430 | 1431 | Jon Knight 1432 | Magosanyi Arpad 1433 | Balazs Scheidler 1434 | Jon Callas 1435 | Eliot Lear 1436 | Petter Reinholdtsen 1437 | Darren Reed 1438 | Alfonso De Gregorio 1439 | Eric Allman 1440 | Andrew Ross 1441 | George Maslyar 1442 | Albert Mietus 1443 | Russ Allbery 1444 | Titus D. Winters 1445 | Edwin P. Boon 1446 | Jeroen M. Mostert 1447 | 1448 | Eric Allman is the original inventor and author of the syslog daemon 1449 | and protocol. The author of this memo and the community at large 1450 | would like to express their appreciation for this work and for the 1451 | usefulness that it has provided over the years. 1452 | 1453 | 1454 | 1455 | 1456 | 1457 | 1458 | Lonvick Informational [Page 26] 1459 | 1460 | RFC 3164 The BSD syslog Protocol August 2001 1461 | 1462 | 1463 | A large amount of additional information about this de-facto standard 1464 | operating system feature may usually be found in the syslog.conf file 1465 | as well as in the man pages for syslog.conf, syslog, syslogd, and 1466 | logger, of many Unix and Unix-like devices. 1467 | 1468 | References 1469 | 1470 | 1 Postel, J., "User Datagram Protocol", STD 6, RFC 768, August 1980. 1471 | 1472 | 2 Crocker, D. and P. Overell, "Augmented BNF for Syntax 1473 | Specifications: ABNF", RFC 2234, November 1997. 1474 | 1475 | 3 USA Standard Code for Information Interchange, USASI X3.4-1968 1476 | 1477 | 4 Mockapetris, P., "Domain Names - Concepts and Facilities", STD 13, 1478 | RFC 1034, November 1987. 1479 | 1480 | 5 Mockapetris, P., "Domain names - Implementation and 1481 | Specification", STD 13, RFC 1035, November 1987. 1482 | 1483 | 6 Hinden, R. and S. Deering, "IP Version 6 Addressing Architecture", 1484 | RFC 2373, July 1998. 1485 | 1486 | 7 Data elements and interchange formats - Information exchange - 1487 | Representation of dates and times, International Organization for 1488 | Standardization, Reference number ISO 8601 : 1988 (E), 1988 1489 | 1490 | 8 Stowe, M., et al, "Chemical Mimicry: Bolas Spiders Emit Components 1491 | of Moth Prey Species Sex Pheromones", Science, 1987 1492 | 1493 | 9 Postel, J., "Internet Protocol", STD 5, RFC 791, September 1981. 1494 | 1495 | 10 Baker, F., "Requirements for IP Version 4 Routers", RFC 1812, June 1496 | 1995. 1497 | 1498 | 11 Deering, S. and R. Hinden, "Internet Protocol, Version 6 (IPv6) 1499 | Specification", RFC 2460, December 1998. 1500 | 1501 | 12 Nichols, K., Blake, S., Baker, F. and D. Black, "Definition of the 1502 | Differentiated Services Field (DS Field) in the IPv4 and IPv6 1503 | Headers", RFC 2474, December 1998. 1504 | 1505 | 13 Cisco Systems Product Security Incident Response Team (PSIRT), 1506 | "Field Notice: Cisco IOS(r) Syslog Crash", January 11, 1999 1507 | http://www.cisco.com/warp/public/707/advisory.html 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | 1514 | Lonvick Informational [Page 27] 1515 | 1516 | RFC 3164 The BSD syslog Protocol August 2001 1517 | 1518 | 1519 | 14 Walker, D., IETF Secretariat, "Proceedings of the Fortieth 1520 | Internet Engineering Task Force, Washington, DC, USA, December 8- 1521 | 12, 1997 1522 | http://www.ietf.org/proceedings/97dec/index.html 1523 | 1524 | Author's Address 1525 | 1526 | Chris Lonvick 1527 | Cisco Systems 1528 | 12515 Research Blvd. 1529 | Austin, TX, USA 1530 | 1531 | Phone: +1.512.378.1182 1532 | EMail: clonvick@cisco.com 1533 | 1534 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | 1553 | 1554 | 1555 | 1556 | 1557 | 1558 | 1559 | 1560 | 1561 | 1562 | 1563 | 1564 | 1565 | 1566 | 1567 | 1568 | 1569 | 1570 | Lonvick Informational [Page 28] 1571 | 1572 | RFC 3164 The BSD syslog Protocol August 2001 1573 | 1574 | 1575 | Full Copyright Statement 1576 | 1577 | Copyright (C) The Internet Society (2001). All Rights Reserved. 1578 | 1579 | This document and translations of it may be copied and furnished to 1580 | others, and derivative works that comment on or otherwise explain it 1581 | or assist in its implementation may be prepared, copied, published 1582 | and distributed, in whole or in part, without restriction of any 1583 | kind, provided that the above copyright notice and this paragraph are 1584 | included on all such copies and derivative works. However, this 1585 | document itself may not be modified in any way, such as by removing 1586 | the copyright notice or references to the Internet Society or other 1587 | Internet organizations, except as needed for the purpose of 1588 | developing Internet standards in which case the procedures for 1589 | copyrights defined in the Internet Standards process must be 1590 | followed, or as required to translate it into languages other than 1591 | English. 1592 | 1593 | The limited permissions granted above are perpetual and will not be 1594 | revoked by the Internet Society or its successors or assigns. 1595 | 1596 | This document and the information contained herein is provided on an 1597 | "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING 1598 | TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING 1599 | BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION 1600 | HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF 1601 | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 1602 | 1603 | Acknowledgement 1604 | 1605 | Funding for the RFC Editor function is currently provided by the 1606 | Internet Society. 1607 | 1608 | 1609 | 1610 | 1611 | 1612 | 1613 | 1614 | 1615 | 1616 | 1617 | 1618 | 1619 | 1620 | 1621 | 1622 | 1623 | 1624 | 1625 | 1626 | Lonvick Informational [Page 29] 1627 | 1628 | -------------------------------------------------------------------------------- /test/certificate.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDqTCCApGgAwIBAgIJAPXOT0ui5C28MA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV 3 | BAYTAkdCMRIwEAYDVQQIDAlCZXJrc2hpcmUxEDAOBgNVBAcMB1JlYWRpbmcxITAf 4 | BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxo 5 | b3N0MCAXDTIwMTEwNjIzMjcwNFoYDzIxMjAxMDEzMjMyNzA0WjBqMQswCQYDVQQG 6 | EwJHQjESMBAGA1UECAwJQmVya3NoaXJlMRAwDgYDVQQHDAdSZWFkaW5nMSEwHwYD 7 | VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9z 8 | dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN6Q7wa6vPKDNUe6LVF6 9 | gGjXhzTWbgkuv4w8tSXO9qHEEjlovzoUWhvIqySCm6LnDi/9e9qfPiTz/Ny/vCw/ 10 | sDBu8uCmq3edVoEmxOpyzq/ilrNSDogtLrqvmy6/WGE6lQkunFD611EaiqX0qPWT 11 | ZjKOs4DAnParVQsq8LGeF5P74j6maIWt3L5pincrd0upj9pxwp7cDyzd4Qkgc2kj 12 | ujdfp1MvwJXCW11NYeCmxsgTPz/O6bo/BHUhHl6vw8Fkma2uG/oHTjA3xCn4EHJd 13 | Vv71Ld07GBZ0gbxt0TpIun0VMCFvN4q3MhKKOi7TLlM1ar0yGshrtUKyRpvOo3dc 14 | /x0CAwEAAaNQME4wHQYDVR0OBBYEFN7lnOPoPRagFeU8pPGxYYFrXtXDMB8GA1Ud 15 | IwQYMBaAFN7lnOPoPRagFeU8pPGxYYFrXtXDMAwGA1UdEwQFMAMBAf8wDQYJKoZI 16 | hvcNAQELBQADggEBAJNDw5Vo1b872EUtlc1m92Dhzsyr0K7oq40Si0AqAfMv/kC5 17 | +Ucp1O7LMLJ5JjDD0pP05heb3dt7C+fZM9ETZmZH4aQrgtR2jsv2cDhxcukXyLqy 18 | 4tXWg0MUelWbgUPSYygEpdcVMn+CLgFni8Ge4zLv1y7cwFqQxwFpF6yYeCwrJOJt 19 | WSouvvtcfnzO6LHVaF/z4BGoJ6ztGKXMjxNexa230kiSswWoP9inyYsjaRRQ8ITS 20 | ybsnTYIlvc5lns3W63iI/0qzzT8wNzPWeF0plTJAhJqhAqcApAtfPKuW+f15c2Xh 21 | toOy41o3wLUdIOcH0NbfGk5CIkooAI/rt8E+2ts= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDekO8GurzygzVH 3 | ui1ReoBo14c01m4JLr+MPLUlzvahxBI5aL86FFobyKskgpui5w4v/Xvanz4k8/zc 4 | v7wsP7AwbvLgpqt3nVaBJsTqcs6v4pazUg6ILS66r5suv1hhOpUJLpxQ+tdRGoql 5 | 9Kj1k2YyjrOAwJz2q1ULKvCxnheT++I+pmiFrdy+aYp3K3dLqY/accKe3A8s3eEJ 6 | IHNpI7o3X6dTL8CVwltdTWHgpsbIEz8/zum6PwR1IR5er8PBZJmtrhv6B04wN8Qp 7 | +BByXVb+9S3dOxgWdIG8bdE6SLp9FTAhbzeKtzISijou0y5TNWq9MhrIa7VCskab 8 | zqN3XP8dAgMBAAECggEAP2B6ECqAv3YJaAFmAjul8TTedXdSIh9DwEVROBD1Ph89 9 | KUfgnENLXXoI8f6XHw44hgXijOCnq5ImwR2AEgGYxFHzq3EKhqcxCNnnXPOQU5ls 10 | XGfTZ4emNNbok6k9G4K5CcJSFOU5BwlNzfAbZMKyaVclWlZ+2+bx8poprApeoG6j 11 | PyHz2ubTGa1vKdUOcmEbNVY0eqtK6q96YOeDzNQD+iWVdboDU04Wxe1I5BGLRRVp 12 | PpdEwJwrSl3gaiFg6yb2kmJ+xT85HeLEuH/7OciblfHMKW5Obi81itZ4IXoXYeyP 13 | B9P/mWXcywIq9t5yY5qlYaf3g11Gxk1d5howjqbTKQKBgQD/ZtPuLtGrg/QF4On7 14 | WDh0s740860ur9+4nk3vYJ3eoOHN0GfRHMPT92wnxckOm9UQxReExY4DHT6VwS5f 15 | BUDp1youYlx780ZSJu/8H+mdhdaaOyMDtBp9b5RCN2H97xkTiDj6+B+hHPTNJgyn 16 | VWSS2Y+cz2hEtz0BqsJMPfCDVwKBgQDfFmnTWwVfcz45V3P9Lfe8xGiFH9BzKIqH 17 | xw/L/eFmFGYYkSMPvv11NUNvQZlU/DGxpeuO4Prq69QCdLY4QTr0tbciWrSxaPqE 18 | pol+/oeDnBuqxZbOR6lyNLTdOwDz+VcoJLv+AC0yS42bcNieEGAY/USzpUUJLICK 19 | 4bzu/E5cqwKBgF41IctjvbdUbviUI/qwafKyMmD52VG1UgKZcgnwS4tJMMFoNEMw 20 | JxPS2jQ5gpY+6PLMoIY7EM0ZRnKa1W37VBxtX4PIiHC4JaI79p27b8LJEYXGdn3x 21 | Oyw1sixSnXS7czZ/MvVv/MrDEZFyjYxTtUttsMmYv89I/9nTkOPqnQL1AoGAS0hh 22 | BfYdZgyZ3vfoKHQuugD91I7b5UC1HwTKC+js+2m+2mOAFXw6RCdpTk4w1EEW9AAt 23 | 8dVyV3yl2v5Pz8QThSkdV/aMK6JliAY7OCPkz0ELBSIQtiPwxp2Ku22B8NMf2mgr 24 | GJguqF5etynpr82O4F/3ozgOh/4Akt2CyJNUTmkCgYBA2wQ1vSRcLS4/DqyKFbvL 25 | mACq1tP1TIbicC4UZG2IYHfc4TybMg8gqL8WDqAk8e/fobHjaPtBhbrbDaU9wu81 26 | +2agKnYoXL8SHkYilDm8lffJEbQPc63xXCYwCpwgQ+/rPZEkF85qou38ZG7vE8t/ 27 | +Z388xz8l0ukyDPIEzDZEA== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /test/syslog-client.js: -------------------------------------------------------------------------------- 1 | var chai = require("chai"), 2 | expect = chai.expect, 3 | assert = chai.assert, 4 | fs = require("fs"), 5 | path = require("path"), 6 | net = require("net"), 7 | tls = require("tls"), 8 | syslogClient = require("../index.js"), 9 | syslogUdpPort = 5514, 10 | syslogTcpPort = 5514, 11 | syslogTlsPort = 6514, 12 | dgram = require("dgram"), 13 | rl = require("readline"), 14 | os = require("os"), 15 | Promise = require("bluebird"), 16 | queuedSyslogUdpMessages = [], 17 | pendingSyslogUdpPromises = [], 18 | queuedSyslogTcpMessages = [], 19 | pendingSyslogTcpPromises = [], 20 | queuedSyslogTlsMessages = [], 21 | pendingSyslogTlsPromises = []; 22 | 23 | var tlsPrivateKey = fs.readFileSync(path.join(__dirname, "key.pem"), "utf8"); 24 | var tlsCertificate = fs.readFileSync(path.join(__dirname, "certificate.pem"), "utf8"); 25 | var wrongCertificate = fs.readFileSync(path.join(__dirname, "wrong.pem"), "utf8"); 26 | 27 | chai.should(); 28 | 29 | function awaitSyslogUdpMsg() { 30 | return new Promise(function (resolve, reject) { 31 | var queued = queuedSyslogUdpMessages.shift(); 32 | if (queued) 33 | return resolve(queued); 34 | pendingSyslogUdpPromises.push(resolve); 35 | }); 36 | } 37 | function awaitSyslogTcpMsg() { 38 | return new Promise(function (resolve, reject) { 39 | var queued = queuedSyslogTcpMessages.shift(); 40 | if (queued) 41 | return resolve(queued); 42 | pendingSyslogTcpPromises.push(resolve); 43 | }); 44 | } 45 | function awaitSyslogTlsMsg() { 46 | return new Promise(function (resolve, reject) { 47 | var queued = queuedSyslogTlsMessages.shift(); 48 | if (queued) 49 | return resolve(queued); 50 | pendingSyslogTlsPromises.push(resolve); 51 | }); 52 | } 53 | 54 | function escapeRegExp(string) { 55 | return (""+string).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&'); 56 | } 57 | 58 | function constructSyslogRegex(pri, hostname, msg, timestamp) { 59 | 60 | var pat_date; 61 | if (typeof timestamp === 'undefined') { 62 | pat_date = "\\w+\\s{1,2}\\d{1,2} \\d{2}:\\d{2}:\\d{2}"; 63 | } else { 64 | var elems = timestamp.toString().split(/\s+/); 65 | 66 | var month = elems[1]; 67 | var day = elems[2]; 68 | var time = elems[4]; 69 | 70 | if (day[0] === "0") 71 | day = " " + day.substr(1, 1); 72 | 73 | pat_date = escapeRegExp(month + " " + day + " " + time); 74 | } 75 | 76 | return new RegExp( 77 | "^<"+ 78 | escapeRegExp(pri)+ 79 | ">"+ 80 | pat_date+ 81 | " "+ 82 | escapeRegExp(hostname)+ 83 | " "+ 84 | escapeRegExp(msg)+ 85 | "\\n?$" 86 | ); 87 | } 88 | 89 | function constructRfc5424Regex(pri, hostname, msg, msgid, timestamp) { 90 | var pat_date = typeof timestamp === 'undefined' ? 91 | "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\.\\d+)Z" : 92 | escapeRegExp(timestamp.toISOString()); 93 | return new RegExp( 94 | "^<"+ 95 | escapeRegExp(pri)+ 96 | ">\\d+ "+ 97 | pat_date+ 98 | " "+ 99 | escapeRegExp(hostname)+ 100 | " \\S{1,48} \\d+ "+ 101 | escapeRegExp(msgid)+ 102 | " - "+ 103 | escapeRegExp(msg)+ 104 | "\\n?$" 105 | ); 106 | } 107 | 108 | var udpServer = dgram.createSocket("udp4"), 109 | tcpServer, 110 | tlsServer; 111 | 112 | before(function (_done) { 113 | var count = 3; 114 | var done = function () { 115 | count--; 116 | if (count === 0) 117 | _done(); 118 | }; 119 | udpServer.on("message", function (msg, rinfo) { 120 | var pend = pendingSyslogUdpPromises.shift(); 121 | if (pend) 122 | return pend(msg.toString()); 123 | queuedSyslogUdpMessages.push(msg.toString()); 124 | }); 125 | udpServer.on("listening", function () { 126 | console.log("Started UDP syslog server"); 127 | done(); 128 | }); 129 | udpServer.on("error", function (err) { 130 | throw new Error(err); 131 | }); 132 | udpServer.bind(syslogUdpPort); 133 | 134 | tcpServer = net.createServer(function (socket) { 135 | var lines = rl.createInterface(socket, socket); 136 | lines.on("line", function (line) { 137 | var pend = pendingSyslogTcpPromises.shift(); 138 | if (pend) 139 | return pend(line); 140 | queuedSyslogTcpMessages.push(line); 141 | }); 142 | }); 143 | tcpServer.on("error", function (err) { 144 | throw new Error(err); 145 | }); 146 | tcpServer.listen(syslogTcpPort, function () { 147 | console.log("Started TCP syslog server"); 148 | done(); 149 | }); 150 | 151 | tlsServer = tls.createServer({ 152 | key: tlsPrivateKey, 153 | cert: tlsCertificate, 154 | secureProtocol: "TLSv1_2_method" 155 | }, function (socket) { 156 | var lines = rl.createInterface(socket, socket); 157 | lines.on("line", function (line) { 158 | var pend = pendingSyslogTlsPromises.shift(); 159 | if (pend) 160 | return pend(line); 161 | queuedSyslogTlsMessages.push(line); 162 | }); 163 | }); 164 | tlsServer.on("error", function (err) { 165 | throw new Error(err); 166 | }); 167 | tlsServer.listen(syslogTlsPort, function () { 168 | console.log("Started TLS syslog server"); 169 | done(); 170 | }); 171 | }); 172 | 173 | after(function (done) { 174 | udpServer.close(); 175 | tlsServer.close(); 176 | tcpServer.close(); 177 | done(); 178 | }); 179 | 180 | describe("Syslog Client", function () { 181 | // eslint-disable-next-line max-statements 182 | it("should set options correctly with defaults", function (done) { 183 | var client; 184 | client = new syslogClient.createClient(); 185 | client.target.should.equal("127.0.0.1"); 186 | client.port.should.equal(514); 187 | client.syslogHostname.should.equal(os.hostname()); 188 | client.tcpTimeout.should.equal(10000); 189 | client.transport.should.equal(syslogClient.Transport.Udp); 190 | 191 | client = new syslogClient.createClient("127.0.0.2"); 192 | client.target.should.equal("127.0.0.2"); 193 | client.port.should.equal(514); 194 | client.syslogHostname.should.equal(os.hostname()); 195 | client.tcpTimeout.should.equal(10000); 196 | client.transport.should.equal(syslogClient.Transport.Udp); 197 | 198 | client = new syslogClient.createClient("127.0.0.2", {}); 199 | client.target.should.equal("127.0.0.2"); 200 | client.port.should.equal(514); 201 | client.syslogHostname.should.equal(os.hostname()); 202 | client.tcpTimeout.should.equal(10000); 203 | client.transport.should.equal(syslogClient.Transport.Udp); 204 | 205 | client = new syslogClient.createClient("127.0.0.2", { 206 | syslogHostname: "test" 207 | }); 208 | client.target.should.equal("127.0.0.2"); 209 | client.port.should.equal(514); 210 | client.syslogHostname.should.equal("test"); 211 | client.tcpTimeout.should.equal(10000); 212 | client.transport.should.equal(syslogClient.Transport.Udp); 213 | 214 | client = new syslogClient.createClient("127.0.0.2", { 215 | syslogHostname: "test", 216 | port: 5555 217 | }); 218 | client.target.should.equal("127.0.0.2"); 219 | client.port.should.equal(5555); 220 | client.syslogHostname.should.equal("test"); 221 | client.tcpTimeout.should.equal(10000); 222 | client.transport.should.equal(syslogClient.Transport.Udp); 223 | 224 | client = new syslogClient.createClient("127.0.0.2", { 225 | syslogHostname: "test", 226 | port: 5555, 227 | tcpTimeout: 50 228 | }); 229 | client.target.should.equal("127.0.0.2"); 230 | client.port.should.equal(5555); 231 | client.syslogHostname.should.equal("test"); 232 | client.tcpTimeout.should.equal(50); 233 | client.transport.should.equal(syslogClient.Transport.Udp); 234 | 235 | client = new syslogClient.createClient("127.0.0.2", { 236 | syslogHostname: "test", 237 | port: 5555, 238 | tcpTimeout: 50, 239 | transport: syslogClient.Transport.Tcp 240 | }); 241 | client.target.should.equal("127.0.0.2"); 242 | client.port.should.equal(5555); 243 | client.syslogHostname.should.equal("test"); 244 | client.tcpTimeout.should.equal(50); 245 | client.transport.should.equal(syslogClient.Transport.Tcp); 246 | 247 | client = new syslogClient.createClient("127.0.0.2", { 248 | syslogHostname: "test", 249 | port: 5555, 250 | tcpTimeout: 50, 251 | transport: syslogClient.Transport.Tls, 252 | tlsCA: tlsCertificate 253 | }); 254 | client.target.should.equal("127.0.0.2"); 255 | client.port.should.equal(5555); 256 | client.syslogHostname.should.equal("test"); 257 | client.tcpTimeout.should.equal(50); 258 | client.transport.should.equal(syslogClient.Transport.Tls); 259 | client.tlsCA.should.equal(tlsCertificate); 260 | 261 | client = new syslogClient.createClient("127.0.0.2", { 262 | syslogHostname: "test", 263 | port: 5555, 264 | tcpTimeout: 50, 265 | transport: "Not a valid transport" 266 | }); 267 | client.target.should.equal("127.0.0.2"); 268 | client.port.should.equal(5555); 269 | client.syslogHostname.should.equal("test"); 270 | client.tcpTimeout.should.equal(50); 271 | client.transport.should.equal(syslogClient.Transport.Udp); 272 | 273 | done(); 274 | }); 275 | it("should connect to UDP and send log(s)", function () { 276 | var hostname = "testhostname"; 277 | var client = new syslogClient.createClient("127.0.0.1", { 278 | port: syslogUdpPort, 279 | syslogHostname: hostname, 280 | transport: syslogClient.Transport.Udp 281 | }); 282 | 283 | client.log("This is a test"); 284 | 285 | return awaitSyslogUdpMsg() 286 | .then(function (msg) { 287 | assert.match(msg, constructSyslogRegex(9, hostname, "This is a test")); 288 | client.log("This is a second test"); 289 | return awaitSyslogUdpMsg(); 290 | }) 291 | .then(function (msg) { 292 | assert.match(msg, constructSyslogRegex(9, hostname, "This is a second test")); 293 | client.close(); 294 | }) 295 | }); 296 | it("should bind UDP socket to specific network address and send log(s)", function () { 297 | var hostname = "testhostname"; 298 | var client = new syslogClient.createClient("127.0.0.1", { 299 | port: syslogUdpPort, 300 | syslogHostname: hostname, 301 | transport: syslogClient.Transport.Udp, 302 | udpBindAddress: "127.0.0.1" 303 | }); 304 | 305 | client.log("This is a test"); 306 | 307 | return awaitSyslogUdpMsg() 308 | .then(function (msg) { 309 | assert.match(msg, constructSyslogRegex(9, hostname, "This is a test")); 310 | client.log("This is a second test"); 311 | return awaitSyslogUdpMsg(); 312 | }) 313 | .then(function (msg) { 314 | assert.match(msg, constructSyslogRegex(9, hostname, "This is a second test")); 315 | client.close(); 316 | }); 317 | }); 318 | it("should fail when binding UDP socket to unknown network address", function (done) { 319 | var hostname = "testhostname"; 320 | var client = new syslogClient.createClient("127.0.0.1", { 321 | port: syslogUdpPort, 322 | syslogHostname: hostname, 323 | transport: syslogClient.Transport.Udp, 324 | udpBindAddress: "500.500.500.500" // invalid IP 325 | }); 326 | 327 | var count = 2, 328 | decFn = function () { 329 | count--; 330 | if (count === 0) { 331 | client.close(); 332 | done(); 333 | } 334 | }; 335 | 336 | client.on("error", function (err) { 337 | err.should.be.instanceof(Error); 338 | if (decFn) 339 | decFn(); 340 | }); 341 | 342 | client.log("shouldn't work", function (err) { 343 | err.should.be.instanceof(Error); 344 | decFn(); 345 | }); 346 | }); 347 | it("should connect to TCP and send log(s)", function () { 348 | var hostname = "testhostname"; 349 | var client = new syslogClient.createClient("127.0.0.1", { 350 | port: syslogTcpPort, 351 | syslogHostname: hostname, 352 | transport: syslogClient.Transport.Tcp 353 | }); 354 | 355 | client.log("This is a test"); 356 | 357 | return awaitSyslogTcpMsg() 358 | .then(function (msg) { 359 | assert.match(msg, constructSyslogRegex(9, hostname, "This is a test")); 360 | client.log("This is a second test"); 361 | return awaitSyslogTcpMsg(); 362 | }) 363 | .then(function (msg) { 364 | assert.match(msg, constructSyslogRegex(9, hostname, "This is a second test")); 365 | client.close(); 366 | }); 367 | }); 368 | it("should connect to TCP with TLS and send log(s)", function () { 369 | var hostname = "testhostname"; 370 | var client = new syslogClient.createClient("localhost", { 371 | port: syslogTlsPort, 372 | syslogHostname: hostname, 373 | transport: syslogClient.Transport.Tls, 374 | tlsCA: tlsCertificate 375 | }); 376 | 377 | client.log("This is a test"); 378 | 379 | return awaitSyslogTlsMsg() 380 | .then(function (msg) { 381 | assert.match(msg, constructSyslogRegex(9, hostname, "This is a test")); 382 | client.log("This is a second test"); 383 | return awaitSyslogTlsMsg(); 384 | }) 385 | .then(function (msg) { 386 | assert.match(msg, constructSyslogRegex(9, hostname, "This is a second test")); 387 | client.close(); 388 | }); 389 | }); 390 | it("should reuse the UDP transport", function () { 391 | var hostname = "testhostname"; 392 | var client = new syslogClient.createClient("127.0.0.1", { 393 | port: syslogUdpPort, 394 | syslogHostname: hostname, 395 | transport: syslogClient.Transport.Udp 396 | }); 397 | 398 | client.log("Transport reuse test"); 399 | var transport_; 400 | 401 | return awaitSyslogUdpMsg() 402 | .then(function (msg) { 403 | transport_ = client.transport_; 404 | client.log("Transport reuse test 2"); 405 | assert.typeOf(transport_, "object"); 406 | return awaitSyslogUdpMsg(); 407 | }) 408 | .then(function (msg) { 409 | assert.equal(transport_, client.transport_); 410 | client.close(); 411 | }); 412 | }); 413 | it("should reuse the TCP transport", function () { 414 | var hostname = "testhostname"; 415 | var client = new syslogClient.createClient("127.0.0.1", { 416 | port: syslogTcpPort, 417 | syslogHostname: hostname, 418 | transport: syslogClient.Transport.Tcp 419 | }); 420 | 421 | client.log("Transport reuse test"); 422 | var transport_; 423 | 424 | return awaitSyslogTcpMsg() 425 | .then(function (msg) { 426 | transport_ = client.transport_; 427 | assert.typeOf(transport_, "object"); 428 | client.log("Transport reuse test 2"); 429 | return awaitSyslogTcpMsg(); 430 | }) 431 | .then(function (msg) { 432 | assert.equal(transport_, client.transport_); 433 | client.close(); 434 | }); 435 | }); 436 | it("should reuse the TLS transport", function () { 437 | var hostname = "testhostname"; 438 | var client = new syslogClient.createClient("localhost", { 439 | port: syslogTlsPort, 440 | syslogHostname: hostname, 441 | transport: syslogClient.Transport.Tls, 442 | tlsCA: tlsCertificate 443 | }); 444 | 445 | client.log("Transport reuse test"); 446 | var transport_; 447 | 448 | return awaitSyslogTlsMsg() 449 | .then(function (msg) { 450 | transport_ = client.transport_; 451 | assert.typeOf(transport_, "object"); 452 | client.log("Transport reuse test 2"); 453 | return awaitSyslogTlsMsg(); 454 | }) 455 | .then(function (msg) { 456 | assert.equal(transport_, client.transport_); 457 | client.close(); 458 | }); 459 | }); 460 | it("should call close event when closed UDP", function (done) { 461 | var hostname = "testhostname"; 462 | var client = new syslogClient.createClient("127.0.0.1", { 463 | port: syslogUdpPort, 464 | syslogHostname: hostname, 465 | transport: syslogClient.Transport.Udp 466 | }); 467 | 468 | client.log("Transport close test"); 469 | client.once("close", function () { 470 | assert.equal(client.transport_, undefined); 471 | client.once("close", function () { 472 | assert.equal(client.transport_, undefined); 473 | done(); 474 | }); 475 | client.close(); 476 | }); 477 | 478 | awaitSyslogUdpMsg() 479 | .then(function (msg) { 480 | client.close(); 481 | }) 482 | }); 483 | it("should call close event when closed TCP", function (done) { 484 | var hostname = "testhostname"; 485 | var client = new syslogClient.createClient("127.0.0.1", { 486 | port: syslogTcpPort, 487 | syslogHostname: hostname, 488 | transport: syslogClient.Transport.Tcp 489 | }); 490 | 491 | client.log("Transport close test"); 492 | client.once("close", function () { 493 | assert.equal(client.transport_, undefined); 494 | client.once("close", function () { 495 | assert.equal(client.transport_, undefined); 496 | done(); 497 | }); 498 | client.close(); 499 | }); 500 | 501 | awaitSyslogTcpMsg() 502 | .then(function (msg) { 503 | client.close(); 504 | }) 505 | }); 506 | it("should call close event when closed TLS", function (done) { 507 | var hostname = "testhostname"; 508 | var client = new syslogClient.createClient("localhost", { 509 | port: syslogTlsPort, 510 | syslogHostname: hostname, 511 | transport: syslogClient.Transport.Tls, 512 | tlsCA: tlsCertificate 513 | }); 514 | 515 | client.log("Transport close test"); 516 | client.once("close", function () { 517 | assert.equal(client.transport_, undefined); 518 | client.once("close", function () { 519 | assert.equal(client.transport_, undefined); 520 | done(); 521 | }); 522 | client.close(); 523 | }); 524 | 525 | awaitSyslogTlsMsg() 526 | .then(function (msg) { 527 | client.close(); 528 | }) 529 | }); 530 | it("should reconnect after connection is closed UDP", function (done) { 531 | var hostname = "testhostname"; 532 | var client = new syslogClient.createClient("127.0.0.1", { 533 | port: syslogUdpPort, 534 | syslogHostname: hostname, 535 | transport: syslogClient.Transport.Udp 536 | }); 537 | 538 | client.log("Transport close test"); 539 | client.once("close", function () { 540 | client.log("Restart connection test"); 541 | awaitSyslogUdpMsg() 542 | .then(function (msg) { 543 | assert.match(msg, constructSyslogRegex(9, hostname, 544 | "Restart connection test")); 545 | client.close(); 546 | done(); 547 | }) 548 | }); 549 | 550 | awaitSyslogUdpMsg() 551 | .then(function (msg) { 552 | client.close(); 553 | }) 554 | }); 555 | it("should reconnect after connection is closed TCP", function (done) { 556 | var hostname = "testhostname"; 557 | var client = new syslogClient.createClient("127.0.0.1", { 558 | port: syslogTcpPort, 559 | syslogHostname: hostname, 560 | transport: syslogClient.Transport.Tcp 561 | }); 562 | 563 | client.log("Transport close test"); 564 | client.once("close", function () { 565 | client.log("Restart connection test"); 566 | awaitSyslogTcpMsg() 567 | .then(function (msg) { 568 | assert.match(msg, constructSyslogRegex(9, hostname, 569 | "Restart connection test")); 570 | client.close(); 571 | done(); 572 | }) 573 | }); 574 | 575 | awaitSyslogTcpMsg() 576 | .then(function (msg) { 577 | client.close(); 578 | }) 579 | }); 580 | it("should reconnect after connection is closed TLS", function (done) { 581 | var hostname = "testhostname"; 582 | var client = new syslogClient.createClient("localhost", { 583 | port: syslogTlsPort, 584 | syslogHostname: hostname, 585 | transport: syslogClient.Transport.Tls, 586 | tlsCA: tlsCertificate 587 | }); 588 | 589 | client.log("Transport close test"); 590 | client.once("close", function () { 591 | client.log("Restart connection test"); 592 | awaitSyslogTlsMsg() 593 | .then(function (msg) { 594 | assert.match(msg, constructSyslogRegex(9, hostname, 595 | "Restart connection test")); 596 | client.close(); 597 | done(); 598 | }) 599 | }); 600 | 601 | awaitSyslogTlsMsg() 602 | .then(function (msg) { 603 | client.close(); 604 | }) 605 | }); 606 | it("should throw if a string isnt provided to .log()", function () { 607 | var hostname = "testhostname"; 608 | var client = new syslogClient.createClient("127.0.0.1", { 609 | port: syslogTcpPort, 610 | syslogHostname: hostname, 611 | transport: syslogClient.Transport.Tcp 612 | }); 613 | 614 | (function () { 615 | client.log(); 616 | }).should.throw(Error); 617 | 618 | (function () { 619 | client.log({}); 620 | }).should.throw(Error); 621 | 622 | (function () { 623 | client.log([]); 624 | }).should.throw(Error); 625 | 626 | (function () { 627 | client.log(undefined); 628 | }).should.throw(Error); 629 | 630 | (function () { 631 | client.log(null); 632 | }).should.throw(Error); 633 | }); 634 | it("should take a callback as the second argument to .log", function (done) { 635 | var hostname = "testhostname"; 636 | var client = new syslogClient.createClient("127.0.0.1", { 637 | port: syslogTcpPort, 638 | syslogHostname: hostname, 639 | transport: syslogClient.Transport.Tcp 640 | }); 641 | 642 | var count = 2, 643 | decFn = function () { 644 | count--; 645 | if (count === 0) { 646 | client.close(); 647 | done(); 648 | } 649 | }; 650 | 651 | client.log("anything", decFn); 652 | awaitSyslogTcpMsg().then(decFn) 653 | }); 654 | it("should take options as the second argument to .log", function (done) { 655 | var hostname = "testhostname"; 656 | var client = new syslogClient.createClient("127.0.0.1", { 657 | port: syslogTcpPort, 658 | syslogHostname: hostname, 659 | transport: syslogClient.Transport.Tcp 660 | }); 661 | 662 | var count = 2, 663 | decFn = function () { 664 | count--; 665 | if (count === 0) { 666 | client.close(); 667 | done(); 668 | } 669 | }; 670 | 671 | client.log("anything", { 672 | facility: syslogClient.Facility.System, 673 | severity: syslogClient.Severity.Notice 674 | }, decFn); 675 | awaitSyslogTcpMsg().then(function (msg) { 676 | assert.match(msg, constructSyslogRegex(29, hostname, 677 | "anything")); 678 | decFn(); 679 | }); 680 | }); 681 | it("should correctly calculate the PRI value", function (done) { 682 | var hostname = "testhostname"; 683 | var client = new syslogClient.createClient("127.0.0.1", { 684 | port: syslogTcpPort, 685 | syslogHostname: hostname, 686 | transport: syslogClient.Transport.Tcp 687 | }); 688 | 689 | var count = 2, 690 | decFn = function () { 691 | count--; 692 | if (count === 0) { 693 | client.close(); 694 | done(); 695 | } 696 | }; 697 | 698 | client.log("anything", { 699 | facility: syslogClient.Facility.Local0, 700 | severity: syslogClient.Severity.Emergency 701 | }, decFn); 702 | awaitSyslogTcpMsg().then(function (msg) { 703 | assert.match(msg, constructSyslogRegex(128, hostname, 704 | "anything")); 705 | decFn(); 706 | }); 707 | }) 708 | it("should call on error on connection error Tcp when invalid port", function (done) { 709 | var hostname = "testhostname"; 710 | var client = new syslogClient.createClient("127.0.0.1", { 711 | port: 502342323, // hopefully this isnt in use, TODO find free ports for testing 712 | tcpTimeout: 2000, 713 | syslogHostname: hostname, 714 | transport: syslogClient.Transport.Tcp 715 | }); 716 | 717 | var count = 2, 718 | decFn = function () { 719 | count--; 720 | if (count === 0) { 721 | client.close(); 722 | done(); 723 | } 724 | }; 725 | 726 | client.on("error", function (err) { 727 | err.should.be.instanceof(Error); 728 | decFn(); 729 | }); 730 | 731 | client.log("shouldn't work", function (err) { 732 | err.should.be.instanceof(Error); 733 | decFn(); 734 | }); 735 | }); 736 | it("should call on error on connection error TLS when invalid port", function (done) { 737 | var hostname = "testhostname"; 738 | var client = new syslogClient.createClient("localhost", { 739 | port: 512342317, // hopefully this isnt in use, TODO find free ports for testing 740 | tcpTimeout: 2000, 741 | syslogHostname: hostname, 742 | transport: syslogClient.Transport.Tls, 743 | tlsCA: tlsCertificate 744 | }); 745 | 746 | var count = 2, 747 | decFn = function () { 748 | count--; 749 | if (count === 0) 750 | done(); 751 | }; 752 | 753 | client.on("error", function (err) { 754 | err.should.be.instanceof(Error); 755 | decFn(); 756 | }); 757 | 758 | client.log("shouldn't work", function (err) { 759 | err.should.be.instanceof(Error); 760 | decFn(); 761 | }); 762 | }); 763 | it("should call on error on connection error Udp when invalid port", function (done) { 764 | var hostname = "testhostname"; 765 | var client = new syslogClient.createClient("127.0.0.1", { 766 | port: 12378726362, // hopefully this isnt in use, TODO find free ports for testing 767 | syslogHostname: hostname, 768 | transport: syslogClient.Transport.Udp 769 | }); 770 | 771 | var count = 2, 772 | decFn = function () { 773 | count--; 774 | if (count === 0) 775 | done(); 776 | }; 777 | 778 | client.on("error", function (err) { 779 | expect(err).to.be.instanceof(Error); 780 | decFn(); 781 | }); 782 | 783 | client.log("shouldn't work", function (err) { 784 | err.should.be.instanceof(Error); 785 | decFn(); 786 | }); 787 | }); 788 | it("should call on error with timeout on connection error Tcp", function (done) { 789 | var hostname = "testhostname"; 790 | var client = new syslogClient.createClient("203.0.113.1", { 791 | port: syslogTcpPort, // hopefully this isnt in use, TODO find free ports for testing 792 | tcpTimeout: 500, 793 | syslogHostname: hostname, 794 | transport: syslogClient.Transport.Tcp 795 | }); 796 | 797 | var count = 2, 798 | decFn = function () { 799 | count--; 800 | if (count === 0) 801 | done(); 802 | }; 803 | 804 | client.on("error", function (err) { 805 | err.should.be.instanceof(Error); 806 | decFn(); 807 | }); 808 | 809 | client.log("shouldn't work", function (err) { 810 | err.should.be.instanceof(Error); 811 | decFn(); 812 | }); 813 | }); 814 | it("should call on error with timeout on connection error TLS", function (done) { 815 | var hostname = "testhostname"; 816 | var client = new syslogClient.createClient("203.0.113.1", { 817 | port: syslogTlsPort, 818 | tcpTimeout: 500, 819 | syslogHostname: hostname, 820 | transport: syslogClient.Transport.Tls, 821 | tlsCA: tlsCertificate 822 | }); 823 | 824 | var count = 2, 825 | decFn = function () { 826 | count--; 827 | if (count === 0) 828 | done(); 829 | }; 830 | 831 | client.on("error", function (err) { 832 | err.should.be.instanceof(Error); 833 | decFn(); 834 | }); 835 | 836 | client.log("shouldn't work", function (err) { 837 | err.should.be.instanceof(Error); 838 | decFn(); 839 | }); 840 | }); 841 | it("should connect to UDP and send back-dated obsolete RFC 3164 log(s)", function () { 842 | var hostname = "testhostname"; 843 | var client = new syslogClient.createClient("127.0.0.1", { 844 | port: syslogUdpPort, 845 | syslogHostname: hostname, 846 | transport: syslogClient.Transport.Udp 847 | }); 848 | 849 | var backdate = new Date(2017, 2, 1); 850 | client.log("This is a test", { 851 | msgid: 98765, timestamp: backdate 852 | }); 853 | 854 | return awaitSyslogUdpMsg() 855 | .then(function (msg) { 856 | assert.match(msg, constructSyslogRegex(9, hostname, "This is a test", backdate)); 857 | client.log("This is a second test", { 858 | rfc3164: true, msgid: 102938 859 | }); 860 | return awaitSyslogUdpMsg(); 861 | }) 862 | .then(function (msg) { 863 | assert.match(msg, constructSyslogRegex(9, hostname, "This is a second test")); 864 | client.close(); 865 | }); 866 | }); 867 | it("should connect to UDP and send back-dated RFC 5424 log(s)", function () { 868 | var hostname = "testhostname"; 869 | var client = new syslogClient.createClient("127.0.0.1", { 870 | port: syslogUdpPort, 871 | syslogHostname: hostname, 872 | transport: syslogClient.Transport.Udp 873 | }); 874 | 875 | var backdate = new Date(2017, 2, 1); 876 | client.log("This is a test", { 877 | rfc3164: false, msgid: 98765, timestamp: backdate 878 | }); 879 | 880 | return awaitSyslogUdpMsg() 881 | .then(function (msg) { 882 | assert.match(msg, constructRfc5424Regex(9, hostname, "This is a test", 98765, backdate)); 883 | client.log("This is a second test", { 884 | rfc3164: false 885 | }); 886 | return awaitSyslogUdpMsg(); 887 | }) 888 | .then(function (msg) { 889 | assert.match(msg, constructRfc5424Regex(9, hostname, "This is a second test", "-")); 890 | client.close(); 891 | }); 892 | }); 893 | it("should refuse to connect to TLS with invalid certificate", function (done) { 894 | var hostname = "testhostname"; 895 | var client = new syslogClient.createClient("localhost", { 896 | port: syslogTlsPort, 897 | syslogHostname: hostname, 898 | transport: syslogClient.Transport.Tls, 899 | tlsCA: wrongCertificate 900 | }); 901 | 902 | var count = 2, 903 | decFn = function () { 904 | count--; 905 | if (count === 0) 906 | done(); 907 | }; 908 | 909 | client.on("error", function (err) { 910 | err.should.be.instanceof(Error); 911 | decFn(); 912 | }); 913 | 914 | client.log("shouldn't work", function (err) { 915 | err.should.be.instanceof(Error); 916 | decFn(); 917 | }); 918 | }); 919 | }); 920 | -------------------------------------------------------------------------------- /test/wrong.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBwjCCAWmgAwIBAgIJAN2lZjH1cDYDMAoGCCqGSM49BAMCMD4xCzAJBgNVBAYT 3 | AlVTMRswGQYDVQQLDBJub2RlLXN5c2xvZy1jbGllbnQxEjAQBgNVBAMMCWxvY2Fs 4 | aG9zdDAeFw0xNzA5MTcwMjA3NTJaFw0xOTA5MTcwMjA3NTJaMD4xCzAJBgNVBAYT 5 | AlVTMRswGQYDVQQLDBJub2RlLXN5c2xvZy1jbGllbnQxEjAQBgNVBAMMCWxvY2Fs 6 | aG9zdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCwvsqRr3Xn9PZe36Ir5Ej3r 7 | n0MJixsVgQCL/KsJK8M/yD6gd9BdUAHp5WYTqJGOy3opDRWsgjXR2hvgjj+Yk0yj 8 | UDBOMB0GA1UdDgQWBBSpQiIev1b7DQOuPcYwKbSE6g4HVTAfBgNVHSMEGDAWgBSp 9 | QiIev1b7DQOuPcYwKbSE6g4HVTAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0cA 10 | MEQCIGvK988mGTjL9LtOzH+5bjf6dWDeJmPF/IU4maHl1L5WAiBLWLqJeohOOfDh 11 | nCMsv6aWQVUQM0JJxLkuhSCeuQe26g== 12 | -----END CERTIFICATE----- 13 | --------------------------------------------------------------------------------