áááşášáááŹá፠Habrusersá ááŽááąáˇááąáŹáˇ áááşá¸áá˛áˇáááŻááşáááŻááş NTP client ááᯠáááşáááŻááąá¸áááá˛áááŻáᏠááźáąáŹááźááťááşááŤáááşá áĄááźáąááśáĄáŹá¸ááźááˇáşá á
ááŹá¸áááŻááşá¸áááş áááşáááşááá˝á˛áˇá
ááşá¸ááŻáśáážááˇáş NTP ááŹááŹááž ááŻáśáˇááźááşáážáŻááᯠááŻááşááąáŹááşáááˇáşáááşá¸áááşá¸áááŻáˇ ááźáąáŹááşá¸áá˛áá˝áŹá¸áááşááźá
áşáááşá ááŻááşááᯠPython ááźááˇáş ááąá¸ááŹá¸ááááˇáşáááşá áĄááźáąáŹááşá¸áážáŹ áááŻáááŻáˇááąáŹ áĄááŹááťáŹá¸áĄáá˝ááş áááŻáááŻááąáŹááşá¸áá˝ááşááąáŹ ááŹááŹá
ááŹá¸ ááážááᯠáá°áááŤáááşá Connoisseurs ááťáŹá¸áááş ntplib ááŻááşáážááˇáş ááŻááşá áá°ááŽáážáŻááᯠáááááźáŻááááááˇáşáááş - áááşá¸ááźáąáŹááˇáş ááťá˝ááşáŻááşáááş âá
áááşáĄáŹá¸áááşáááşâ áá˛áˇáááşá
ááŤááᯠNTP áááŻááŹááŹáá˛á NTP áááş áĄááťáááşáĄáááĄááťááŹááŹááťáŹá¸áážááˇáş áĄááźááşáĄáážááşááŻáśáˇááźááşáááşáĄáá˝ááş ááááŻáááŻááąáŹáá
áşááŻááźá
áşáááşá á¤ááááŻáááŻááąáŹááᯠááąááşááŽá
ááşááťáŹá¸á
á˝áŹáá˝ááş áĄááŻáśá¸ááźáŻáááşá áĽáááŹáĄáŹá¸ááźááˇáşá windows áážá w32tm áááşááąáŹááşáážáŻá
NTP ááááŻáááŻááąáŹá ááŹá¸áážááşá¸ á áŻá áŻááąáŤááşá¸ á ááťááŻá¸áážááááşá áááááŹá¸áážááşá¸ 0 (1985, RFC958) ááᯠáááşáážááá˝ááş ááąááşáááŽááąáŹáˇáᯠáá°áááŹá¸áááşá áááşáážááá˝ááş ááŹá¸áážááşá¸áĄáá áşááťáŹá¸ááᯠáĄááŻáśá¸ááźáŻááąáááş- ááŹá¸áážááşá¸ 1 (1988, RFC1059)á ááŹá¸áážááşá¸ 2 (1989, RFC1119)á ááŹá¸áážááşá¸ 3 (1992, RFC1305) áážááˇáş ááŹá¸áážááşá¸ 4 (1996, RFC2030)á ááŹá¸áážááşá¸ 1-4 ááťáŹá¸áááş áá áşááŻáážááˇáşáá áşáᯠáá˝á˛áááşáĄááŻáśá¸ááźáŻáááŻááşáááşá áááşá¸áááŻáˇá áááşáááşáážáŻ áĄááşááááŻááŽáááşááťáŹá¸áá˝ááşáᏠáá˝á˛ááźáŹá¸áááşá ááŹááŹááťáŹá¸.
Package ááąáŹáşáááş

ááŻááşááźáááŻááş (ááźááşáááşáážáŻáá˝ážááşááźááťááş) - áážááážááŻááşá¸ááŻááááĄááźáąáŹááşá¸áááááąá¸áá˝ážááşááźááąáŹááśááŤááşáá
áşááŻá áĄáááášááŤááş-
- 0 - ááźáŻááźááşáážáŻááážáááŤá
- 1 - áá áşááąáˇááŹáááąáŹááşááŻáśá¸áááá áşáá˝ááş 61 á áášáááˇáşááŤáááşáááşá
- 2 - áá áşááąáˇááŹáááąáŹááşááŻáśá¸áááá áşáá˝ááş 59 á áášáááˇáşááŤáááşáááşá
- 3 â ááŹááŹááťá˝ááşáá˝ááşá¸áážáŻ (áĄááťáááşááᯠáááşáá°ááźáŻáááááŤ)
ááŹá¸áážááşá¸ááśááŤááş (ááŹá¸áážááşá¸ááśááŤááş) â NTP ááááŻáááŻááąáŹ ááŹá¸áážááşá¸ááśááŤááş (á-á)á
ááŻáś (ááŻááş) â ááŻááşáááŻá¸ááąá¸áááŻáˇáá°á áááşáááşáážáŻááŻááşá 0 ááž 7 áĄááá áĄááŻáśá¸áĄááťáŹá¸ááŻáśá¸áááşáááŻá¸-
- 3 - ááąáŹááşáááş
- 4 â ááŹááŹ
- 5 â ááŻááşáá˝ážááˇáşáážáŻááŻááş
áĄáá˝ážáŹ (áĄáá˝ážáŹáĄáááˇáş) â ááŹááŹáážááˇáş áááşáá˝ážááşá¸ááŹááŽááźáŹá¸áážá áĄáááşáĄáááşáĄáá˝ážáŹáĄááąáĄáá˝ááş (1 â ááŹááŹáááş áááşáá˝ážááşá¸ááŹááŽááž ááąááŹááᯠáááŻááşáááŻááşáá°áááşá 2 â ááŹááŹáááş áĄáá˝ážáŹ 1 ááŤáááˇáş ááŹááŹáá
áşááŻááž ááąááŹááᯠáá°áááş)á
ááąáá°á¸áááş áááşáááŻááşáááşááąáˇááťáşááťáŹá¸ááźáŹá¸ áĄááźááˇáşááŻáśá¸ááźáŹá¸ááŹáááᯠáááŻááşá
áŹá¸ááźáŻáááˇáş ááááşá¸ááźááˇáşáá
áşááŻááźá
áşáááşá NTP client áááş ááŹááŹááᯠá
á
áşáááşá¸ááąáŹááşáá°áááş ááťážáąáŹáşáááˇáşááŹá¸áááˇáş ááźáŹá¸ááŹáááᯠá¤ááąááŹáá˝ááş áááşáážááşááąá¸ááźáŽá¸ NTP ááŹááŹááž ááąáŹááşáá°áááş ááťážáąáŹáşáááˇáşááŹá¸áááˇáş ááźáŹá¸ááŹáááᯠáááşáážááşááąá¸ááŤáááşá áááşáááŻá¸áááş á
áášáááˇáşá binary logarithm áážááˇáş ááŽááťážáááşá
á
áąáˇá
ááşááąááťáŹááźááşá¸ (accuracy) áááş á
áá
áşááŹááŽá ááááťáážáŻááᯠáááŻááşá
áŹá¸ááźáŻáááˇáş ááááşá¸ááźááˇáşááźá
áşáááşá áááşáááŻá¸áááş á
áášáááˇáşá binary logarithm áážááˇáş ááŽááťážáááşá
Root áážáąáŹááˇáşáážáąá¸ááźááşá¸á (ááŹááŹáážáąáŹááˇáşáážáąá¸áážáŻ) â áááşáážááşááŹá¸ááąáŹ áĄáážááşáĄááąáĄáá˝ááşáĄááźá
áş á
áášáááˇáşáĄáááŻááş NTP ááŹááŹáááŻáˇááąáŹááşáážááááş ááŹááŽáááşáážáŻááźááşá¸áĄáá˝ááş áááŻáĄááşááąáŹáĄááťáááşá
áĄááźá
áşááźááˇáşáážáśáˇááźááşá¸á (ááŹááŹááźááˇáşááźááşáážáŻ) - ááŻáśááąáĄáážááşááźááˇáş á
áášáááˇáşáĄááąáĄáá˝ááşáĄááźá
áş NTP ááŹááŹááŹááŽáááşááźááşá¸áááťáśáˇáážáśáˇáážáŻá
Ref id (áĄáááşá¸áĄááźá
áş identifier) âââ ááŹáᎠIDá ááŹááŹáá˝ááş stratum 1 áážáááŤáá ref id áááş áĄááşáááşááŹáᎠ(4 ASCII á
áŹááŻáśá¸) á áĄáááşááźá
áşáááşá áĄáááşá ááŹááŹáááş áĄááźáŹá¸ááŹááŹáááŻáĄááŻáśá¸ááźáŻááŤáá áááŻá¸ááŹá¸ááťááş ID áá˝ááş á¤ááŹááŹáááááşá
áŹááŤáážááááşá
ááąáŹááşááŻáśá¸ áĄáá˝ááş 4 ááŻáááş áĄááťáááş - 32 bits - ááááşá¸ááźááˇáşáĄáááŻááşá¸á 32 bits - áĄáááŻááşá¸ááááşá¸áĄáááŻááşá¸ááᯠáááŻááşá
áŹá¸ááźáŻáááşá
áĄáá˝ážááşá¸ - ááŹááŹááąáŤáşáážá ááąáŹááşááŻáśá¸ááąáŤáş ááŹááŽááťáŹá¸ááᯠáááşááźááşá¸á
áĄá
ááźáŻ - áááşáááşááᯠáááŻáˇáááŻááşáááˇáşáĄááťáááş (ááŹááŹááž ááźááˇáşáá˝ááşá¸áááş - á¤áĄááŹáĄááąáŤáş ááąáŹááşáááş)á
ááśáá° - ááŹááŹááž packet áááŻáááşááśááážááááˇáşáĄááťáááşá
áááŻáˇááąá¸ - ááŹááŹááž ááááŻááşá¸áááˇáşááśáááŻáˇ áááşáááşááᯠááąá¸áááŻáˇáááˇáşáĄááťáááş (Client ááž ááźááˇáşáá˝ááşá¸ááŹá¸ááąáŹá á¤áĄááŹáĄááąáŤáş ááąáŹááşáááş)á
ááťá˝ááşáŻááşáááŻáˇáááş ááąáŹááşááŻáśá¸áááşáááşáážá áşááŻááᯠáááˇáşáá˝ááşá¸á ááşá¸á áŹá¸áááşáááŻááşááŤá
ááťá˝ááşáŻááşáááŻáˇá package áááŻááąá¸ááźááŤá ááŻáˇá
áĄááŻááşááŻááş
class NTPPacket:
_FORMAT = "!B B b b 11I"
def __init__(self, version_number=2, mode=3, transmit=0):
# Necessary of enter leap second (2 bits)
self.leap_indicator = 0
# Version of protocol (3 bits)
self.version_number = version_number
# Mode of sender (3 bits)
self.mode = mode
# The level of "layering" reading time (1 byte)
self.stratum = 0
# Interval between requests (1 byte)
self.pool = 0
# Precision (log2) (1 byte)
self.precision = 0
# Interval for the clock reach NTP server (4 bytes)
self.root_delay = 0
# Scatter the clock NTP-server (4 bytes)
self.root_dispersion = 0
# Indicator of clocks (4 bytes)
self.ref_id = 0
# Last update time on server (8 bytes)
self.reference = 0
# Time of sending packet from local machine (8 bytes)
self.originate = 0
# Time of receipt on server (8 bytes)
self.receive = 0
# Time of sending answer from server (8 bytes)
self.transmit = transmit
ááŹááŹáááŻáˇ áááşáááşáá
áşáᯠááąá¸áááŻáˇááźááşá¸ (áááşááśááźááşá¸) ááźáŻááŻááşáááşá áááşá¸ááᯠbyte áááşá¸ááťááşá¸áá
áşááŻáĄááźá
áş ááźáąáŹááşá¸áá˛áááŻááşáááŤáááşá
ᤠ(áážááˇáş ááźáąáŹááşá¸ááźááş) ááŻááşááąáŹááşááťááşáĄáá˝ááşá ááťá˝ááşáŻááşáááŻáˇáááş ááŻááşááąáŹááşááťááş áážá
áşááŻááᯠááąá¸ááŹá¸ááŤáááş - pack() áážááˇáş unpack():
pack ááŻááşááąáŹááşááťááş
def pack(self):
return struct.pack(NTPPacket._FORMAT,
(self.leap_indicator << 6) +
(self.version_number << 3) + self.mode,
self.stratum,
self.pool,
self.precision,
int(self.root_delay) + get_fraction(self.root_delay, 16),
int(self.root_dispersion) +
get_fraction(self.root_dispersion, 16),
self.ref_id,
int(self.reference),
get_fraction(self.reference, 32),
int(self.originate),
get_fraction(self.originate, 32),
int(self.receive),
get_fraction(self.receive, 32),
int(self.transmit),
get_fraction(self.transmit, 32))
unpack function áááŻ
def unpack(self, data: bytes):
unpacked_data = struct.unpack(NTPPacket._FORMAT, data)
self.leap_indicator = unpacked_data[0] >> 6 # 2 bits
self.version_number = unpacked_data[0] >> 3 & 0b111 # 3 bits
self.mode = unpacked_data[0] & 0b111 # 3 bits
self.stratum = unpacked_data[1] # 1 byte
self.pool = unpacked_data[2] # 1 byte
self.precision = unpacked_data[3] # 1 byte
# 2 bytes | 2 bytes
self.root_delay = (unpacked_data[4] >> 16) +
(unpacked_data[4] & 0xFFFF) / 2 ** 16
# 2 bytes | 2 bytes
self.root_dispersion = (unpacked_data[5] >> 16) +
(unpacked_data[5] & 0xFFFF) / 2 ** 16
# 4 bytes
self.ref_id = str((unpacked_data[6] >> 24) & 0xFF) + " " +
str((unpacked_data[6] >> 16) & 0xFF) + " " +
str((unpacked_data[6] >> 8) & 0xFF) + " " +
str(unpacked_data[6] & 0xFF)
self.reference = unpacked_data[7] + unpacked_data[8] / 2 ** 32 # 8 bytes
self.originate = unpacked_data[9] + unpacked_data[10] / 2 ** 32 # 8 bytes
self.receive = unpacked_data[11] + unpacked_data[12] / 2 ** 32 # 8 bytes
self.transmit = unpacked_data[13] + unpacked_data[14] / 2 ** 32 # 8 bytes
return self
ááťááşá¸áá°ááťáŹá¸áĄáá˝ááş áĄáááŽááąá¸áážááşá¸áá áşááŻáĄááąááźááˇáş áááşááąáˇááşáťááᯠáážáááąáŹá áŹááźáąáŹááşá¸áĄááźá áş ááźáąáŹááşá¸áá˛ááąá¸áááˇáşááŻááş
def to_display(self):
return "Leap indicator: {0.leap_indicator}n"
"Version number: {0.version_number}n"
"Mode: {0.mode}n"
"Stratum: {0.stratum}n"
"Pool: {0.pool}n"
"Precision: {0.precision}n"
"Root delay: {0.root_delay}n"
"Root dispersion: {0.root_dispersion}n"
"Ref id: {0.ref_id}n"
"Reference: {0.reference}n"
"Originate: {0.originate}n"
"Receive: {0.receive}n"
"Transmit: {0.transmit}"
.format(self)
ááŹááŹáááŻáˇ áááşááąáˇááşáťáá áşáᯠáááŻáˇááźááşá¸á
ááźááˇáşááŹá¸ááąáŹ áĄáá˝ááşááťáŹá¸ááŤáážáááąáŹ áááşáááşááᯠááŹááŹáááŻáˇ ááąá¸áááŻáˇáááŤáááşá ááŹá¸áážááşá¸, ááŻáś и áááŻáˇááąá¸á áĄáááŻá፠áááŻáˇááąá¸ á ááşáá˝ááşá¸á ááşáá˝ááş áááşáážááĄááťáááş (áááşáááŤáᎠ1á 1900 ááááşá¸á)á ááŹá¸áážááşá¸ - 1-4á ááŻááş - 3 (ááąáŹááşáááşááŻááş) áá˝ááş áááşáááşáážááşáááŤáááşá
ááąáŹááşá¸áááŻááťááşáááŻáááşááśááźáŽá¸ááąáŹááş ááŹááŹáááş NTP áááşáááşáážá áá˝ááşáááşáĄáŹá¸ááŻáśá¸ááᯠááźááˇáşá á˝ááşáᏠáĄáá˝ááşáá˛áááŻáˇ áá°á¸áá°ááźááşá¸ áĄá ááźáŻ ááśáážáááşáááŻá¸ áááŻáˇááąá¸ááąáŹááşá¸áááŻááťááşáá˛áá˝ááş ááŤááŹáááşá ááąáŹááşáááşáááş áááşáá˝ááşá¸áážá áá°ááĄááťáááşáááşáááŻá¸ááᯠááťááşááťááşá¸áááźááˇáşáááŻááşáááźááşá¸áážáŹ ááťá˝ááşáŻááşáĄáá˝ááş áááşá¸ááźááşááŤáááşá áĄá ááźáŻ. ááááşáĄááąááźááˇáş packet ááźááşááŹááąáŹáĄááŤá client áá˝ááş áĄááťáááşáááşáááŻá¸ 4 ááŻáážááááş - ááąáŹááşá¸áááŻááťááşááąá¸áááŻáˇáááˇáşáĄááťáááş (áĄá ááźáŻ) ááŹááŹáááş ááąáŹááşá¸áááŻááťááşááᯠáááşááśááážááááˇáşáĄááťáááş (ááśáá°) ááŹááŹááž ááŻáśáˇááźááşáážáŻááąá¸áááŻáˇáááˇáşáĄááťáááş (áááŻáˇááąá¸) áážááˇáş client ááž ááŻáśáˇááźááşáážáŻááᯠáááşááśááážááááˇáşáĄááťáááş- ááąáŹááşáᏠ(áĄááŻááşáá˛áá˝ááşáááŤááŤ)á á¤áááşáááŻá¸ááťáŹá¸áááŻáĄááŻáśá¸ááźáŻááźááşá¸ááźááˇáş ááťá˝ááşáŻááşáááŻáˇáááş áážááşáááşááąáŹáĄááťáááşááᯠáááşáážááşáááŻááşáááşá
áĄááŻááşáááŻáˇááźááşá¸áážááˇáşáááşááśááźááşá¸ááŻááş
# Time difference between 1970 and 1900, seconds
FORMAT_DIFF = (datetime.date(1970, 1, 1) - datetime.date(1900, 1, 1)).days * 24 * 3600
# Waiting time for recv (seconds)
WAITING_TIME = 5
server = "pool.ntp.org"
port = 123
packet = NTPPacket(version_number=2, mode=3, transmit=time.time() + FORMAT_DIFF)
answer = NTPPacket()
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.settimeout(WAITING_TIME)
s.sendto(packet.pack(), (server, port))
data = s.recv(48)
arrive_time = time.time() + FORMAT_DIFF
answer.unpack(data)
ááŹááŹááž ááąááŹááᯠááŻááşááąáŹááşááąáááşá
ááŹááŹááž ááąááŹááťáŹá¸ááᯠááŻááşáá°ááźááşá¸áááş Raymond M. Smullyan (1978) á ááźáżááŹááąáŹááşá¸ááž áĄááşášáááááşáá°ááźáŽá¸áááşá¸á ááŻááşááąáŹááşááťááşáážááˇáş áááşáá°áááş- "áá°áá áşáŚá¸áá˝ááş áááşáááşááŹááŽáá áşááŻáśá¸ááž ááážáááąáŹáşáááşá¸ áĄáááşáá˝ááş áá áşááŤáá áşááś áá°ááąáˇááąááąáŹ ááááťááąáŹ áááŻááşáááşááŹááŽáá áşááŻáśá¸áážááááşá ááąáááŻááşáááşá áá áşááąáˇáá˝ááş ááŹááŽááᯠááąáŹááşáá áşááźáááş ááąáááŻááşáááş ááąáˇáá˝áŹá¸áááźááˇáş áá°áˇáá°áááşááťááşá¸ááś áá˝áŹá¸áááşáᏠáááąáááşá¸áá˝ááş áĄáá°ááąáᏠáĄáááşááźááşááąáŹááşááąáŹáĄá፠ááŹááŽááᯠáážááşáááşá á˝áŹ áááşáážááşáááŻááşáá˛áˇáááşá áááŽá¸áá˝áŹá¸ááťáááşááᯠááźááŻááááááş áá°áááşáááŻááŻááşáááá˛á áĄááźáąáááąáŹáˇ âáĄáááşááá˝ááşáá˝áŹá¸áá˛áˇáĄá፠áá°áá áşááąáŹááşá ááŹááŽááᯠááąáááŻááşááźáŽá¸ áááşáá˛áážáŹáážááá˛áˇ áĄááąáĄááŹá¸ááᯠáážááşáááááşá áá°áááşááťááşá¸áá áşááąáŹááşááŽááŹááźáŽá¸ á§ááˇáşáááşáá˝áąááᯠááŹá¸áá˛áˇááźáŽá¸ áá°ááąáŹááşáážáááťáááşáá˛áˇ áá˝ááşáá˝áŹááťáááşááᯠáážááşááŹá¸ááŹá¸áá˛áˇááŤáááşá á¤áĄááŹá áá°ááŹááąáŹááşáááşáááşáá˛áˇáááşááᯠáááážááááŻááşáááşááźá áşáááşá áĄáááşááźááşááąáŹááşááźáŽá¸ ááŹááŽáááŻááźááˇáşáááŻááşááąáŹáˇ áá°áá áşááąáŹááşá áá°ááážáááąáŹáˇáá˛áˇ áĄááťáááşááᯠáĄááŻáśá¸áĄááźááşááąá¸ááŤáááşá áá°áááşáááşáá˛áˇáá˛áˇáĄááťáááşááᯠááŻááşáááŻááşááźááşá¸áĄáŹá¸ááźááˇáş áĄá˛ááŽááąááŹáá˛áˇ áĄááźááşáááŽá¸ááᯠááźááşáááşá¸áá˛áˇááá˛áˇ áĄááťáááşááᯠáá°áá áşááąáŹááşá áááááşá á§ááˇáşáááşááťáŹá¸ áá˝ááşáá˝áŹááťáááşáĄáá áááşá¸ááąáŤáşáá˝ááş ááŻááşááŻáśá¸áá˛áˇááąáŹ áĄááťáááşáá áşáááşááᯠááąáŤááşá¸áááˇáşááźááşá¸ááźááˇáş áĄáááşáááŻáˇááąáŹááşáážááááˇáşáĄááťáááşááᯠáááážááááŻááşááźáŽá¸ ááŹááŽáááşááśááťáŹá¸ááᯠááťáááşáážááááş áĄáá˝ááˇáşáĄááąá¸ááážááááşááźá áşáááşáâ
ááąáŹááşá¸áááŻááťááşáá áşááŻáĄáá˝ááş ááŹááŹááŻááşááąáŹááşááąáááˇáşáĄááťáááşááᯠáážáŹááŤ-
- client ááž ááŹááŹáááŻáˇ packet á áááŽá¸áá˝áŹá¸ááťáááşááᯠáážáŹááŤ- ((ááąáŹááşáážá â áá°ááĄá ) â (áááŻáˇ â áááşááś)) / á
- client áážááˇáş server time áĄááźáŹá¸ ááźáŹá¸ááŹá¸ááťááşááᯠáážáŹááŤ
áááşááś - Originate - ((Arrive - Originate) - (Transmit - Receive)) / 2 =
2 * áááşááś â 2 * áá°á â ááąáŹááşáážáááŹáááş + áá°á + ááąá¸áááŻáˇááźááşá¸ â áááşááś =
áááşááś â áá°áááşá¸ â ááąáŹááşáááş + áááŻáˇááŤá
ááťá˝ááşáŻááşáááŻáˇáááş ááąáá áśááąáŹáşááťáááşá ááááşáááşáááŻá¸ááᯠááąáŤááşá¸áááˇáşáᏠááááᯠááťáąáŹáşáá˝ážááşá á˝áŹááźááşáááşá¸ááŤá
ááááşáá˝ááş
time_different = answer.get_time_different(arrive_time)
result = "Time difference: {}nServer time: {}n{}".format(
time_different,
datetime.datetime.fromtimestamp(time.time() + time_different).strftime("%c"),
answer.to_display())
print(result)
áĄááŻáśá¸áááşáááşá .
source: www.habr.com
