audit 5: the supervisor socket the panel's alone, OpenDKIM logs and oversigns From
test / test (push) Canceled after 0s

M17: the supervisord control socket is root:supervisor 0770, a group whose
one member is the panel; OpenDKIM and Postfix keep `selfpost` for the files
under /data and no longer reach the socket.

L30, read in OpenDKIM 2.11.0~beta2's source first: it logs through
syslog(3) only and has no Logfile option, and nothing in the container
served /dev/log. internal/syslogrelay (the panel binary with
-syslog-relay=/run/syslog/log, program syslog-relay before OpenDKIM,
/dev/log a link to its socket) passes the datagrams to stdout, error and
worse marked. opendkim.conf: Syslog yes, Canonicalization relaxed/simple,
OversignHeaders From (RFC 6376 § 3.4, § 8.15). e2e: OpenDKIM's start line
reaches the container log; every program RUNNING; DKIM verifies.

Tested on the test server: go vet + go test of 26 packages, make e2e (all
pass, 626 s) on this tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-15 13:07:28 +03:00
co-authored by Claude Opus 5.5
parent d6ed6bcb30
commit dab7715e80
11 changed files with 258 additions and 15 deletions
+87
View File
@@ -0,0 +1,87 @@
// Package syslogrelay passes what programs in the container send to syslog(3)
// on to standard output, where supervisord takes it into the container's log.
//
// OpenDKIM logs through syslog(3) and nothing else (OpenDKIM 2.11.0~beta2,
// opendkim/opendkim.conf.5.in: Syslog, SyslogFacility and SyslogName are the
// only logging options; opendkim/opendkim.c calls openlog() and syslog()).
// syslog(3) sends each message as a datagram to /dev/log, and in the container
// nothing listened there: OpenDKIM's errors - a key it cannot read, a table it
// cannot open - went nowhere (audit 2026-10-12, L30). Postfix is not among the
// senders: it logs through its own postlogd (build/postfix-config.sh).
package syslogrelay
import (
"bytes"
"fmt"
"io"
"net"
"os"
"regexp"
)
// stamp is the BSD syslog timestamp that follows the priority, "Oct 15
// 09:00:00 " (RFC 3164 § 4.1.2: "Mmm dd hh:mm:ss", the day padded with a
// space). The container's log has times of its own.
var stamp = regexp.MustCompile(`^[A-Z][a-z]{2} [ 0-9][0-9] [0-9]{2}:[0-9]{2}:[0-9]{2} `)
// Line turns one datagram into the line written out: the priority and the
// timestamp taken off, trailing newlines too; what remains is "ident[pid]:
// message". A severity of error or worse (RFC 3164 § 4.1.1: the priority is
// facility*8 + severity, and 0-3 are emergency to error) is said in front.
func Line(datagram []byte) string {
b := bytes.TrimRight(datagram, "\r\n\x00")
severity := -1
if len(b) > 2 && b[0] == '<' {
if end := bytes.IndexByte(b, '>'); end > 1 && end <= 4 {
pri := 0
ok := true
for _, c := range b[1:end] {
if c < '0' || c > '9' {
ok = false
break
}
pri = pri*10 + int(c-'0')
}
if ok {
severity = pri % 8
b = b[end+1:]
}
}
}
if loc := stamp.FindIndex(b); loc != nil {
b = b[loc[1]:]
}
line := string(b)
if severity >= 0 && severity <= 3 {
line = "error: " + line
}
return line
}
// Run listens on a datagram socket at path, which anyone in the container may
// write to, and writes each message to w as a line until the socket fails.
// /dev/log is a link to path (build/entrypoint.sh).
func Run(path string, w io.Writer) error {
_ = os.Remove(path)
conn, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Name: path, Net: "unixgram"})
if err != nil {
return fmt.Errorf("syslog relay: listen on %s: %w", path, err)
}
defer conn.Close()
// OpenDKIM runs as its own user; the socket is the container's local log,
// as /dev/log is on a host.
if err := os.Chmod(path, 0o666); err != nil {
return fmt.Errorf("syslog relay: %w", err)
}
buf := make([]byte, 64<<10)
for {
n, _, err := conn.ReadFromUnix(buf)
if err != nil {
return fmt.Errorf("syslog relay: read: %w", err)
}
if n == 0 {
continue
}
fmt.Fprintln(w, Line(buf[:n]))
}
}