ローカルマシン時間を調整せずにLXCでntpdのみをサーバーとして実行する方法

ローカルマシン時間を調整せずにLXCでntpdのみをサーバーとして実行する方法

デバイスの時計をLXC内で実行されているCentOS-7サーバーと同期させる必要があります。サーバーはパッケージntpdで使用しようとしますが、他の製品では開いています。ntpこの質問は、ntpdサーバーまたはそれに対応する設定に関するものです。

これまで私はこれを試しました/etc/ntp.conf

driftfile /var/lib/ntp/drift
restrict default nomodify notrap nopeer noquery

restrict 127.0.0.1
restrict ::1

server 127.127.1.1 iburst
fudge  127.127.1.1 stratum 8

disable monitor

これには2つの問題があります。

  1. ntpd録音後終了cap_set_proc() failed to drop root privileges: Operation not permitted
  2. ntpd現地時間を調整しようとしています。失敗しましたが試しました。これが唯一の問題であり、ログにエラーメッセージがある場合は問題ありません。

/var/log/messagesntpdを起動しようとした結果の全体出力:

systemd: Starting Network Time Service...
ntpd[20154]: ntpd [email protected] Wed Apr 12 21:24:06 UTC 2017 (1)
ntpd[20155]: proto: precision = 0.120 usec
ntpd[20155]: ntp_adjtime() failed: Operation not permitted
systemd: Started Network Time Service.
ntpd[20155]: 0.0.0.0 c01d 0d kern kernel time sync enabled
ntpd[20155]: Listen and drop on 0 v4wildcard 0.0.0.0 UDP 123
ntpd[20155]: Listen and drop on 1 v6wildcard :: UDP 123
ntpd[20155]: Listen normally on 2 lo 127.0.0.1 UDP 123
ntpd[20155]: Listen normally on 3 eth0 hidden:A.B.C.D UDP 123
ntpd[20155]: Listen normally on 4 tun0 hidden:E.F.G.H UDP 123
ntpd[20155]: Listening on routing socket on fd #21 for interface updates
ntpd[20155]: 0.0.0.0 c016 06 restart
ntpd[20155]: ntp_adjtime() failed: Operation not permitted
ntpd[20155]: 0.0.0.0 c012 02 freq_set kernel 0.000 PPM
ntpd[20155]: 0.0.0.0 c011 01 freq_not_set
ntpd[20155]: cap_set_proc() failed to drop root privileges: Operation not permitted
systemd: ntpd.service: main process exited, code=exited, status=255/n/a
systemd: Unit ntpd.service entered failed state.
systemd: ntpd.service failed.

答え1

コメントで説明したように、慢性病患者-x最近、システムクロックを変更しようとしない新しいオプションが追加され、特にコンテナ操作に適しています。残念ながら、このオプションを受け取った最初のバージョン(3.2)は徹底的ではなく、まだLinux機能を要求したため、まだ失敗しました。

ギブスCentOS7 LXCコンテナ(CentOS以外のホストを含​​む)のchronydパッケージchronyバージョン3.2-2.el7にはオプションが含まれていますが、-x実際にはバグ修正はここにありません。

# strace /usr/sbin/chronyd -x -d

[...]

[pid   571] capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
[pid   571] capset({_LINUX_CAPABILITY_VERSION_3, 0}, {1<<CAP_NET_BIND_SERVICE|1<<CAP_SYS_TIME, 1<<CAP_NET_BIND_SERVICE|1<<CAP_SYS_TIME, 0}) = -1 EPERM (Operation not permitted)

したがって、修正できないバイナリクロニドが禁止機能を要求するのを防ぐことができればうまくいくでしょう(3.3バグ修正はまさにこれでした)。良いニュースです。LD_PRELOAD/を使用できます。dlsym()包装紙。

他のLinuxシステムでコンパイル(実際にはDebian 9ホストでコンパイルされており、CentOS7コンテナで問題なく実行されています)このコードはと呼ばれ、capsetwrapper.c構造定義が見つかりました。そこたとえば(カーネル3.10でも変更されていません)。

#define _GNU_SOURCE 1
#include <dlfcn.h>

#include <sys/capability.h>

int capset(cap_user_header_t hdrp, const cap_user_data_t datap) {
    int (*orig_capset)(cap_user_header_t,const cap_user_data_t)=dlsym(RTLD_NEXT,"capset");
    datap->effective &= ~ (1<<CAP_SYS_TIME);
    datap->permitted &= ~ (1<<CAP_SYS_TIME);
    return orig_capset(hdrp, datap);
}

次の特定の方法を使用してください(ライブラリをLD_PRELOAD使用するのに適しているため):

gcc -shared -fPIC -o libcapsetwrapper.so capsetwrapper.c -ldl

仕組みは次のとおりです。

[root@centos7-amd64bis ~]# LD_PRELOAD=/root/libcapsetwrapper.so /usr/sbin/chronyd -x -d
2019-03-24T10:09:58Z chronyd version 3.2 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SECHASH +SIGND +ASYNCDNS +IPV6 +DEBUG)
2019-03-24T10:09:58Z Disabled control of system clock
2019-03-24T10:09:58Z Frequency 0.000 +/- 1000000.000 ppm read from /var/lib/chrony/drift

実行時に機能を確認してください。

# egrep '^Cap(Prm|Eff)' /proc/$(pidof chronyd)/status
CapPrm: 0000000000000400
CapEff: 0000000000000400

上記の残りの0x400を表示します1<<CAP_NET_BIND_SERVICE

システムに統合するには:

  • 包装紙を次のようlibcapsetwrapper.soに配置します。/usr/local/lib/libcapsetwrapper.so

  • systemctl edit chronydオーバーライドチェックを使用すると、CAP_SYS_TIME実行可能ファイルは次のように起動されます。

    [Unit]
    ConditionCapability=
    
    [Service]
    ExecStart=
    ExecStart=/bin/sh -c 'export LD_PRELOAD=/usr/local/lib/libcapsetwrapper.so; exec /usr/sbin/chronyd -x'
    

    申し訳ありません。パラメータを再利用できません$OPTIONS(空であるため、-xオプションをからロードする必要があります/etc/sysconfig/chronyd)。しかし、より体系化された知識があれば可能です。

作業結果:

# systemctl status chronyd
● chronyd.service - NTP client/server
   Loaded: loaded (/usr/lib/systemd/system/chronyd.service; enabled; vendor preset: enabled)
  Drop-In: /etc/systemd/system/chronyd.service.d
           `-override.conf
   Active: active (running) since Sun 2019-03-24 10:24:26 UTC; 13min ago
     Docs: man:chronyd(8)
           man:chrony.conf(5)
  Process: 843 ExecStartPost=/usr/libexec/chrony-helper update-daemon (code=exited, status=0/SUCCESS)
  Process: 839 ExecStart=/bin/sh -c export LD_PRELOAD=/usr/local/lib/libcapsetwrapper.so; exec /usr/sbin/chronyd -x (code=exited, status=0/SUCCESS)
 Main PID: 841 (chronyd)
   CGroup: /system.slice/chronyd.service
           `-841 /usr/sbin/chronyd -x

テストされていないのは、デフォルトのSELinux環境(ここでは使用できません)がプリロード操作を許可するのか、それ以上の作業を実行するのか/usr/local/lib/libcapsetwrapper.so(必ず使用restorecon)です。

答え2

バージョン以降1908年7月7日CentOSにはchronyバージョンがあります3.4このフラグは正しくサポートされており、-xわずかな設定調整でLXCで実行できます。

  • デフォルトでは、/usr/lib/systemd/system/chronyd.serviceLXCでConditionCapability=CAP_SYS_TIME実行する必要はありませんので、-xこの削除エントリをファイルに追加して削除してください。/etc/systemd/system/chronyd.service.d/lxc.conf
    [Unit]
    # Default service has:
    # ConditionCapability=CAP_SYS_TIME
    # which does not work under LXC and causes service to refuse to start
    # Clear it.
    ConditionCapability=
  • 編集/etc/sysconfig/chronydして最後-xに追加OPTIONSOPTIONS="-x"

  • /etc/chrony.confNTPサーバーと同期せずに、代わりにローカルクロックの時間を提供するように変更します。他のすべてのserverアイテムを削除/無効にして、次の項目を追加します。

    # Comment out default/other server entries
    #server 0.centos.pool.ntp.org iburst
    #server 1.centos.pool.ntp.org iburst
    #server 2.centos.pool.ntp.org iburst
    #server 3.centos.pool.ntp.org iburst
    #
    # Add these as per https://www.thegeekdiary.com/centos-rhel-7-chrony-how-to-sync-to-local-clock/
    server 127.127.1.0
    local stratum 10
    allow all

例の内容はあなたに合わないかもしれませんので、allowあなたのニーズに合わせて指示を確認してください。allow all

  • サービスを再ロードして再起動してください。
    systemctl daemon-reload
    systemctl restart chronyd

そうする必要があります。

答え3

私はうまくいく方法を見つけましたが、私の解決策は満足できないので、まだ良い答えを探しています。

ntpdパート1:root権限を放棄しようとすることをブロックしました。

デフォルト値は次/usr/lib/systemd/system/ntpd.serviceのとおりです。

[Service]
EnvironmentFile=-/etc/sysconfig/ntpd
ExecStart=/usr/sbin/ntpd -u ntp:ntp $OPTIONS

-u ntp:ntpだから配置して「削除」します。/etc/systemd/system/ntpd.service.d/local.conf

[Service]
ExecStart=
ExecStart=/usr/sbin/ntpd $OPTIONS

これによりntpdroot として実行できます。うまくいきますが、このアプローチは満足できません。

パート2。現地時間部分を更新しない

/etc/ntp.confこの行を追加すると、サービスの開始時にエラーを設定せずに3回記録するのではなく、1回のエラーのみを記録しますdisable kernel。時計を変更できないため、これは許可されます。理想的には、時計を変更しようとしません。ntpdntp_adjtime() failed: Operation not permitted

関連情報