이전 포스팅에 이어서 syslog 파싱을 추가 해 보았습니다.
가볍게 시작했던 포스팅인데, RFC 보면서 하려니 이전 포스팅보다 시간이 걸려 하나 포스팅하는 데 오래 걸리네요.
- regex 정규식 참조 https://regex101.com/library/97phrb
- 차후 진행
위 정보를 보고 표준대로 해보았습니다.
하지만 현업에서는 네트워크 장비, 보안장비 또는 기타 디바이스들에서 보내는 syslog는 표준을 따르지 않는 경우가 있어 해당 예제로는 한계가 있습니다.
비표준 포맷을 맞추는 일도 고달픈 일입니다.
예제는 표준만 고려해서 RFC3164만 작성하였습니다.
package main
import (
"fmt"
"net"
"regexp"
"strconv"
"time"
)
type syslog struct {
Facility int
Datetime time.Time //hostname or IP address
Hostname string
Msg string
}
// RFC3164 https://www.rfc-editor.org/rfc/rfc3164.html
// * regex -> https://regex101.com/library/97phrb
// RFC5424 https://www.rfc-editor.org/rfc/rfc5424
var regRFC3164 *regexp.Regexp
var regRFC5424 *regexp.Regexp // is next time
var facilityMap = map[int]string{
0: "kernel messages",
1: "user-level messages",
2: "mail system",
3: "system daemons",
4: "security/authorization messages",
5: "messages generated internally by syslogd",
6: "line printer subsystem",
7: "network news subsystem",
8: "UUCP subsystem",
9: "clock daemon",
10: "security/authorization messages",
11: "FTP daemon",
12: "NTP subsystem",
13: "log audit",
14: "log alert",
15: "clock daemon (note 2)",
16: "local use 0 (local0)",
17: "local use 1 (local1)",
18: "local use 2 (local2)",
19: "local use 3 (local3)",
20: "local use 4 (local4)",
21: "local use 5 (local5)",
22: "local use 6 (local6)",
23: "local use 7 (local7)",
}
func syslogParser(r []byte) (syslog, error) {
var log syslog
var err error
rs := regRFC3164.FindSubmatch(r)
if len(rs) <= 1 {
return log, errors.New("not match")
}
log.Facility, err = strconv.Atoi(string(rs[1]))
if err != nil {
return log, err
}
t, err := time.Parse("Jan _2 15:04:05", string(rs[2]))
if err != nil {
return log, err
}
t = t.AddDate(time.Now().Year(), 0, 0) // 년 보정
log.Datetime = t
log.Hostname = string(rs[3])
log.Msg = string(rs[4])
return log, nil
}
func init() {
var err error
regRFC3164, err = regexp.Compile("<([0-9]{1,3})\\>([A-Za-z]{3} [0-9]{1,2} \\d{2}:\\d{2}:\\d{2}) ([\\S]+) ([\\S\\s]+)")
if err != nil {
fmt.Println(err.Error())
panic(err)
}
// RFC5424 is come in next time
}
func main() {
var ServerAddr *net.UDPAddr
var err error
ServerAddr, err = net.ResolveUDPAddr("udp", "0.0.0.0:514")
if err != nil {
fmt.Println(err.Error())
panic(err)
}
ServerConn, err := net.ListenUDP("udp", ServerAddr)
if err != nil {
fmt.Println(err.Error())
panic(err)
}
defer ServerConn.Close()
serverConn := ServerConn
buf := make([]byte, 65535)
for {
n, addr, _ := serverConn.ReadFromUDP(buf)
if n != 0 {
address := addr.IP.String()
log, err := syslogParser(buf[:n])
if err != nil {
fmt.Println(err.Error())
continue
}
fmt.Print(fmt.Sprintf(
"IP Address : %s\nFacility : %s\nDatetime : %s\nHostname : %s\nMessage : %s\n",
address,
facilityMap[log.Facility],
log.Datetime.String(),
log.Hostname,
log.Msg,
))
}
}
}
'Go언어 golang' 카테고리의 다른 글
golang REST API / go언어 REST API 서버. #2 docker mariadb 설치 및 접속 확인 (0) | 2023.03.16 |
---|---|
golang Syslog server / Go언어 Syslog collector - 파싱 추가 RFC5424 (0) | 2023.03.12 |
golang Syslog server / Go언어 Syslog collector #1 (0) | 2023.03.10 |
golang pretty progress bar (0) | 2023.03.09 |
고랭 엑셀 - golang excel #3 차트 삽입 (0) | 2023.03.08 |