为什么docker容器中的shell会显示主机中的dmesg内容?

WoJ*_*WoJ 5 privileges containers elevated-privileges docker

我有一个在Ubuntu yakkety上运行Debian jessie的docker容器。

在docker内部(ssh例如,通过docker连接)时,我与主机隔离(这是预期的)。但是,dmesg我意识到这向我显示了主机而不是容器的消息。它如何访问其主机的信息?

docker容器的配置不是特殊的(除了它使用的是不同于的特定桥docker0),尤其是它不会在任何特权模式下运行("Privileged": false如下所示):

root@srv ~# docker inspect minecraft-1-8
[
    {
        "Id": "748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e",
        "Created": "2016-12-01T15:35:05.287672787Z",
        "Path": "/usr/bin/supervisord",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 28650,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2016-12-15T18:37:08.409564695Z",
            "FinishedAt": "2016-12-15T18:37:07.457274028Z"
        },
        "Image": "sha256:78a2f88d47e29523503c2196ed2faaa3d1039d948d73987edc03b2abd338595d",
        "ResolvConfPath": "/var/lib/docker/containers/748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e/hostname",
        "HostsPath": "/var/lib/docker/containers/748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e/hosts",
        "LogPath": "/var/lib/docker/containers/748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e/748cfdfbf3fb5526cb7151cbc0857117af3c7bd8ab9e086c4f2efb897290d66e-json.log",
        "Name": "/minecraft-1-8",
        "RestartCount": 0,
        "Driver": "overlay",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "docker",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": null,
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DiskQuota": 0,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": -1,
            "OomKillDisable": false,
            "PidsLimit": 0,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0
        },
        "GraphDriver": {
            "Name": "overlay",
            "Data": {
                "LowerDir": "/var/lib/docker/overlay/e78ce9dbcedd6974429a4aada8f38913b7d35da41f586f203dd99a568f38b6c3/root",
                "MergedDir": "/var/lib/docker/overlay/e8422e4707d95db8ea747af2367626cc8bf16e95f8eb05dfad9a63461c9ade86/merged",
                "UpperDir": "/var/lib/docker/overlay/e8422e4707d95db8ea747af2367626cc8bf16e95f8eb05dfad9a63461c9ade86/upper",
                "WorkDir": "/var/lib/docker/overlay/e8422e4707d95db8ea747af2367626cc8bf16e95f8eb05dfad9a63461c9ade86/work"
            }
        },
        "Mounts": [],
        "Config": {
            "Hostname": "minecraft-1-8",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": true,
            "AttachStderr": true,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/usr/bin/supervisord"
            ],
            "Image": "minecraft",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "cf411634babad31138ab4572b9cd7306f74a54dd1baf4cd8d7706d7e7020c594",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/cf411634baba",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "",
            "Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "",
            "IPPrefixLen": 0,
            "IPv6Gateway": "",
            "MacAddress": "",
            "Networks": {
                "docker": {
                    "IPAMConfig": {
                        "IPv4Address": "10.200.0.100"
                    },
                    "Links": null,
                    "Aliases": [
                        "748cfdfbf3fb"
                    ],
                    "NetworkID": "7b20560b36032d36ffe6c0ebece6b4408355d207f4e203a2957b0434ee0afdc1",
                    "EndpointID": "9fa4fc914dfe76022ce0db02e48a7e7c85c57bc2a15b0b3e5d81b1f24d95f376",
                    "Gateway": "10.200.0.1",
                    "IPAddress": "10.200.0.100",
                    "IPPrefixLen": 24,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:0a:c8:00:64"
                }
            }
        }
    }
]
Run Code Online (Sandbox Code Playgroud)

Mat*_*att 6

在大多数发行版中,dmesg它不是特权命令。任何用户都可以使用klogctl接口读取内核环形缓冲区。

$ id
uid=1001(matt) gid=1001(matt) groups=1001(matt)
$ dmesg | head -1
[    0.000000] Initializing cgroup subsys cpuset
Run Code Online (Sandbox Code Playgroud)

但是除了读什么也做不了

$ dmesg -C
dmesg: klogctl failed: Operation not permitted
Run Code Online (Sandbox Code Playgroud)

扩展到Docker

$ sudo docker run debian dmesg | head -1
[    0.000000] Initializing cgroup subsys cpuset
$ sudo docker run debian dmesg -C
dmesg: klogctl failed: Operation not permitted
Run Code Online (Sandbox Code Playgroud)

限制访问

您可以限制读取访问到root用户和那些与CAP_SYSLOG或CAP_SYS_ADMIN 能力通过/proc/sys/kernel/dmesg_restrict

$ echo 1 > /proc/sys/kernel/dmesg_restrict
Run Code Online (Sandbox Code Playgroud)

然后,您将收到一条拒绝权限消息:

$ docker run ubuntu:yakkety dmesg
dmesg: read kernel buffer failed: Operation not permitted
Run Code Online (Sandbox Code Playgroud)

然后以特权模式运行容器将重新获得对主机内核环形缓冲区的访问权限

$ docker run --privileged ubuntu:yakkety dmesg
[146902.131915] br-fa26f1dc96a1: port 3(veth80d3d5d) entered disabled state
...
Run Code Online (Sandbox Code Playgroud)

使用sysctl来配置kernel.dmesg_restrict=1是否永久需要它。

命名空间

至于为什么内核日志没有其他内核区域那样的名称间隔,我认为答案是“很难”。在此2012年版中,您可能不知道要了解的更多细节。逐步接近实用容器:“ syslog”名称空间LWN发布。除了所建议的修补程序之外,我看不到对其的任何参考:https : //lwn.net/Articles/562389/ https://lwn.net/Articles/561271/。如您在最近的netfilter补丁中所看到的,它们可以解决,以允许容器名称空间中的规则使用全局日志。