CS general Flashcards
Принципы кодировки
UTF-32 – это кодировка, которая переводит все символы в наборы из 32 бит. Это простой алгоритм, но изводящий много места впустую. UTF-16 и UTF-8 являются кодировками с переменной длиной кодирования. Если символ может быть закодирован одним байтом(потому что номер пункта символа очень маленький), UTF-8 закодирует его одним байтом. Если нужно 2 байта, то используется 2 байта. Кодировка сообщает старшими битами, сколькими битами кодируется текущий символ. Такой способ экономит место, но так же и тратит его в случае, если эти сигнальные биты часто используются. UTF-16 является компромиссом: все символы как минимум двухбайтные, но их размер может увеличиваться до 4 байт, если нужно.
Unicode – это огромная таблица соответствия символов и чисел, а различные UTF кодировки определяют, как эти числа переводятся в биты.
любой символ может быть закодирован множеством разных последовательностей бит, и любая последовательность бит может представлять разные символы, в зависимости от используемой кодировки. разные кодировки используют разное число бит на символ и разные значения для кодирования разных символов.
Гениальность UTF-8 в бинарной совместимости с ASCII, которая является де-факто основой для всех кодировок. Все символы ASCII занимают максимум байт в UTF-8 и используют те же биты, что и в ASCII. Иными словами, ASCII может быть отражено 1:1 в UTF-8. Любой символ не из ASCII занимает 2 или более байт в UTF-8. Большинство языков программирования, использующих ASCII в качестве кодировки исходного кода, позволяет включать текст в UTF-8 прямо в текст
Первый бит каждого байта кодирующего символ отвечает не за сам символ, а за определение байта. То есть например если ведущий (первый) бит нулевой, то это значит что для кодирования символа используется всего один байт. Что и обеспечивает совместимость с ASCII.
Для двухбайтовых символов первые три бита должны быть такие — 110
для трех-байтовых символов в первом байте ведущие биты — 1110
в кодировке UTF-16 любой символ юникода может быть закодирован либо двумя, либо четырьмя байтами.
Суррогатная пара — это две кодовые пары используемые для кодирования одного символа (итого 4 байта). Для таких суррогатных пар в таблице юникода отведен специальный диапазон от D800 до DFFF. Это значит, что при преобразовании кодовой пары из байтового вида в шестнадцатиричный вы получаете число из этого диапазона, то перед вами не самостоятельный символ, а суррогатная пара.
Что такое SSH
SSH (от англ. secure shell – безопасная оболочка) это набор программ, которые позволяют регистрироваться на компьютере по сети, удаленно выполнять на нем команды, а также копировать и перемещать файлы между компьютерами. SSH организует защищенное безопасное соединение поверх небезопасных каналов связи.
SSH предоставляет замены традиционным r-командам удаленного доступа с тем отличием, что они обладают повышенной безопасностью. Они выполняются поверх защищенных зашифрованных соединений, которые не позволяет прослушивать или подменять трафик. Кроме того, SSH может обеспечивать безопасное соединение для передачи любого другого трафика: например, почтовых сообщений или файлов.
Основные функции SSH
Протокол SSH возник как попытка обезопасить открытые незащищенные соединения. Впоследствии его функции были значительно расширены. Наиболее важными из них являются:
Безопасные команды доступа к хосту. SSH дает возможность выполнять безопасные команды доступа к хосту, такие как ssh (удаленная оболочка), slogin (удаленный вход в систему), scp (удаленное копирование);
X11 Forwarding. SSH предоставляет встроенный механизм для выполнения удаленных клиентов X Window.
Port forwarding. SSH может выполнять переадресацию портов, передавая трафик c одного порта одной машины на другой порт другой машины. При этом передаваемый трафик шифруется;
Обеспечение безопасности SSH
Безопасность протокола достигается использованием нескольких решений, которые сводят к минимуму риск использования соединения:
- Шифрование соединение, которое может выполняться одним из методов, выбранных в процессе переговоров. Шифрованное соединение не позволяет просто перехватить и использовать трафик. Выбор алгоритма шифрования делает систему более гибкой, позволяя не использовать алгоритмы, в которых обнаружены слабые места или которые не может поддерживать одна из сторон;
- Аутентификация сервера выполняется при любом соединении. Это не позволяет выполнить подмену сервера или подмену трафика;
- Аутентификация клиента может выполняться одним из нескольких доступных способов. Это с одной стороны может повысить надежность аутентификации, с другой – делает систему более гибкой и упрощает ее использование;
- Проверка целостности пакетов позволяет отследить любые незаконные изменения в трафике соединения. При обнаружении таких изменений, соединение немедленно разрывается;
- Временные параметры аутентификации не позволяют воспользоваться данными соединения в том, случае, если спустя некоторое время после перехвата оно все-таки было расшифровано. Устаревание обычно происходит через час;
Аутентификация сервера (SSH)
Аутентификация сервера производится при помощи инфраструктуры открытых ключей. Клиент, который хочет установить соединение с сервером шифрует данные известным ему открытым ключом сервера и отправляет их серверу. Сервер должен расшифровать их при помощи известного только ему секретного ключа, и отправить их назад. Так клиент может быть уверен в том, является ли хост тем, за кого себя выдает.
Аутентификация сервера по протоколу SSH выполняется при помощи инфраструктуры открытых ключей. Открытый ключ сервера клиент получает при первом соединении с ним.
Аутентификация сервера дает возможность не полагаться на службу имен и маршрутизацию пакетов. В том случае, если нарушителю удалось подменить запись в DNS или перенаправить IP-пакеты на свой хост, аутентификация не пройдет, поскольку хост не обладает необходимыми секретными ключами.
ssh защищает от
Подмены IP-адресов (IP-spoofing), когда удаленный хост посылает пакеты от имени другого хоста;
Подмены DNS-записей (DNS-spoofing), когда изменяется запись на сервере DNS и в результате соединение устанавливается не с желаемым хостом, а с тем, на который указывает новая запись;
Перехвата открытых паролей и прочих данных, которые передаются в открытом виде и любой, кто имеет физический доступ к каналу, может их узнать.
Аутентификация клиента SSH
Методы аутентификации клиентов, которые использует SSH:
Host-based аутентификация Аутентификация с помощью открытых ключей Kerberos-аутентификация Парольная аутентификация. По хостам. Метод аналогичный используемому в r-командах. В том случае, если соединение устанавливается с привилегированного порта, и файл .rhosts позволяет вход в систему, он разрешается. Этот метод является потенциально небезопасным, рекомендуется не использовать его. Для повышения уровня своей безопасности метод может быть дополнен RSA-аутентификацией клиентского хоста.
Открытый ключ. Клиент отправляет серверу открытый ключ. Если сервер знает его, он просит клиента доказать, что тот знает и секретный ключ тоже. Если клиент может это доказать, значит аутентификация считается успешной.
Керберос. Аутентификация проводится по схеме v5 Kerberos.
Пароль. В самом крайнем случае, если не удалось провести аутентификацию не одним из перечисленных способов, используется традиционная аутентификация при помощи пароля. Принцип аутентификации аналогичен тому, какой, например, используется в Telnet с той разницей, что пароль передается по зашифрованному каналу.
Сервер sshd
Как и в любом сетевом взаимодействии, в SSH-соединении участвуют две стороны: клиент и сервер. Сервер SSH реализован в виде программы sshd.
Сервер sshd является независимой программой, поэтому его запуск нужно производить во время загрузки компьютера стартовыми скриптами. То есть, вызов sshd либо должен осуществляться явно одним из rc-скриптов, либо ссылки на скрипт запуска следует включить в иерархию /etc/rc?.d/.
Для того чтобы сервер sshd автоматически стартовал при запуске компьютера, необходимо добавить его вызов в скрипты загрузки.
Будучи запущенным, демон работает в фоновом режиме и обрабатывает все входящие запросы по порту 22. Для каждого соединения создается новая копия демона, который занимается только его обслуживанием.
Настройка сервера sshd
Конфигурация демона определяется файлом /etc/ssh/sshd_config. Он представляет собой набор действующих строк, пустых строк и строк-комментариев. Действующие строки файла содержат название параметра и его значение.
В конфигурационном файле указывается большое количество параметров, которые можно отнести к нескольким категориям:
Адреса. Интерфейс и порт, к которым привязан демон;
Журнализация. Опции, определяющие то, какая именно информация о работе демона должна регистрироваться и заноситься в журналы системы;
Управление ключами. Информация о том, в каких файлах находятся ключи, участвующие в аутентификации.
Аутентификация. Допустимые схемы аутентификации.
Дополнительные параметры. Опции, управляющие дополнительными функциями SSH, такими как переадресация портов, переадресация X11 и другие
Некоторые конфигурационные параметры могут быть переопределены опциями командной строки при вызове sshd.
Клиент ssh
Программа ssh предназначена для регистрации на удаленном хосте с использование протокола ssh и удаленного выполнения команд. Кроме того ssh позволяет выполнять туннелирование любых TCP-соединений внутри ssh-канала (port forwarding).
Синтаксис программы ssh:
ssh опции хост пользователь@хост команда
ssh подключается к удаленному хосту, используя для этого текущее имя пользователя или, если указано явно, имя пользователь. После этого происходит двусторонняя аутентификация, т.е. удаленный хост доказывает, что он именно тот, за кого себя выдает, а регистрирующийся пользователь в свою очередь доказывает это удаленному хосту.
После этого удаленный хост, выполняет заданную команду, либо если команда отсутствует, запускает командный интерпретатор и предоставляет к нему доступ. После того, как команда выполнена, либо оболочка командного интерпретатора завершила свою работу, соединение завершается.
Программа ssh имеет свой собственный конфигурационный файл, точно такого же формата, как и конфигурационный файл сервера sshd, только в котором используются другие директивы.
Некоторые опции командной строки программы ssh
- v – Выводить отладочную информацию о ходе процесса установки соединения. Настоятельно рекомендуется использовать ключ во время настройки службы.
- f – Перейти в фоновый режим, сразу же после того, как пройден этап регистрации
- l пользователь – Регистрироваться на удаленной системе как пользователь. Вместо ключа -l имяможно указывать перед именем хоста в форме пользователь@хост
- p порт – Порт удаленного хоста, на котором доступен сервис SSH. По умолчанию используется порт 22.
- L порт:хост:хостпорт – Перенаправить порт локального хоста на хостпорт удаленного хоста.
- R порт:хост:хостпорт – Перенаправить порт удаленного локального хоста на хостпорт локального хоста.
- o опции – Явно указать опции, которые перекрывают опции, заданные в конфигурационных файлах ssh.
Создание и установка асимметричных ключей SSH
Аутентификация с использованием открытых ключей проходит следующим образом. Хост, на котором выполняется удаленная регистрация предлагает пользователю аутентифицировать себя. Для этого он пересылает сообщение, зашифрованное известным ему открытым ключом пользователя. Если пользователь расшифрует сообщение, значит он знает секретный ключ, следовательно, является тем за кого себя выдает.
Секретные ключи хранятся в файлах identity, id_dsa и id_rsa в локальном каталоге ~/.ssh (разные файлы для разных алгоритмов шифрования). Открытые ключи должны быть в файлах authorized_keys и authorized_keys2 в каталоге ~/.ssh на удаленном компьютере, на котором производится регистрация. В качестве домашнего рассматривается каталог пользователя, под именем которого выполняется регистрация. Файл authorized_keys используется для хранения открытых ключей для SSH1, а в authorized_keys2 — для SSH2.
ssh дает возможность использования одного из трех различных алгоритмов асимметричного шифрования RSA или DSA.
Типы ключей
rsa1 – Тип ключа RSA1, используемый в SSH версии 1
rsa – Тип ключа RSA, используемый в SSH версии 2
dsa – Тип ключа DSA, используемый в SSH версии 2
Для создания, преобразования и управления ключами аутентификации используется утилита ssh-keygen. Синтаксис программы:
ssh-keygen опции
Программа генерирует пару открытый ключ - секретный ключ. При этом она спрашивает, в какие файлы нужно записать ключи. По умолчанию секретный ключ записывается в ~/.ssh/identity (или ~/.ssh/id_rsa, ~/.ssh/id_dsa), а открытый в ~/.ssh/identity.pub.
Сгенерированный секретный ключ защищается при помощи парольной фразы (passphrase), которую нужно обязательно знать, для того чтобы воспользоваться ключом. Секретная фраза вводится в момент генерирования ключей. Она может быть затем изменена, без повторного копирования ключей.
Можно сгенерировать секретные ключи, в которых парольная фраза будет отсутствовать. Хотя это и упрощает использование ключей, делать этого не рекомендуется, поскольку в этом случае файл с секретным ключом автоматически влечет за собой полный беспрепятственный доступ ко всем системам, где установлена его открытая пара.
Полученный открытый ключ нужно добавить в файлы authorized_keys удаленных хостов, к которым будет производится доступ.
После того, как аутентификация с использование открытых ключей настроена, доступ к удаленному компьютеру можно получить без пароля. Однако для того чтобы воспользоваться локальным секретным ключом нужно ввести парольную фразу.
Некоторые опции командной строки программы ssh-keygen
-t тип – Тип генерируемого ключа. Допустимые типы: rsa, rsa1 и dsa.
-p – Изменить парольную фразу
-l – Показать отпечаток (fingerprint) секретного ключа
[править]Опции ключа в ~/.ssh/authorized_keys
Для каждого открытого ключа в файлах ~/.ssh/authorized_keys можно выставить опции, ограничивающие возможности клиента, аутентифицировавшегося по данному ключу. Опции находятся перед ключем,
from=”список-шаблонов-через-запятую” - разрешает принимать соединения только с хостов, удовлетворяющих одному из шаблонов. В качестве шаблонов поддерживаются символы - ?, * и !
command=”команда” - при аутентификации по данному ключу разрешается запускать только указанную команду, а не то что указано пользователем - например, “echo this key disabled” или “dump -params” и обязательно использовать опцию no-pty для бинарной передачи данных
no-port-forwarding - запретить port-forwarding
no-X11-forwarding - запретить X11
no-user-rc - Запрещает выполнение файла ~/.ssh/rc после аутентификации (в RHEL не работает)
environment=”NAME=VALUE” - Принудительная установка переменных среды окружения. (в RHEL не работает)
no-agent-forwarding - запретить использование agent-forwarding
no-pty - запретить интерактивную оболочку
permitopen=”host:port” - (ограничить переназначение локального порта: ssh -L)
scp
Набор программ SSH позволяют не только выполнять удаленную регистрацию на компьютере для доступа к удаленной строке. Программа scp копирует файлы между хостами, полагаясь при этом на протоколы SSH и используя те же методы аутентификации, что и ssh.
Синтаксис программы scp:
scp опции пользователь@хост1:файл1… пользователь@хост2:файл2
Команда устанавливает защищенное соединение между хостом1 и хостом2 и копирует файл1 хоста1 в файл2 хоста2. Любой из хостов может быть локальным. Если имя хоста не указано, подразумевается локальный хост.
Синтаксис использования команды scp напоминает синтаксис cp. Она так же обрабатывает большое количество аргументов, использует аналогичные ключи для рекурсивного копирования, для копирования атрибутов и т.д.
Опции программы scp
- r – Выполнить рекурсивное копирование каталогов
- p – Сохранить по возможности атрибуты файлов (права доступа, время модификации, время доступа) при копировании
- C – Выполнять сжатие файлов при передаче
- P порт – Соединяться с удаленным компьютером по порту порт
- v – Сообщать отладочную информацию о ходе SSH-соединения
- q – Не выдавать индикатор прогресса
SFTP
SFTP (SSH File Transfer Protocol) — SSH-протокол для передачи файлов. Он предназначен для копирования и выполнения других операций с файлами поверх надёжного и безопасного соединения. Как правило, в качестве базового протокола, обеспечивающего соединение, и используется протокол SSH2, но это не обязательно.
SFTP-сервер встроен в OpenSSH. Он реализуется с помощью программы sftp-server. SFTP-клиент sftp встроен в пакет OpenSSH. В качестве SFTP-клиента для Windows может использоваться WinSCP или PSFTP из пакета PuTTY.
Перенаправление TCP-портов (port forwarding) - SSH
У SSH есть возможность, известная как перенаправление портов (port forwarding), которая позволяет передавать по SSH-соединению данные других протоколов. Перенаправление портов позволяет передать подключение, сделанное на одном конце SSH-соединения передать на другой конец и продолжить сеанс связи оттуда.
Другими словами, перенаправление портов SSH можно рассматривать как особую форму туннелирования TCP-соединений, когда SSH-клиент (или сервер; в зависимости от направления туннелирования; об этом ниже) прослушивает на одном хосте порт, и полученные на него соединения передаёт на вторую сторону, SSH-серверу (или клиенту, соответственно) внутри установленного SSH-соединения; вторая сторона инициирует соединение к серверу назначения уже от своего имени, и передаёт в нём полученные по туннелю данные.
Типичная задача, которая может решаться с помощью перенаправление TCP, это доступ к внутреннему серверу сети снаружи, через шлюз. Представьте, что у вас есть сеть, которая находится за UNIX-шлюзом, смотрящим в Интернет. У вас есть доступ к этому шлюзу по SSH. Вы находитесь в Интернете и хотите попасть на один из внутренних серверов сети, не имеет значения по какому протоколу, но пусть, например, по протоколу RDP. Возможности открыть порт при помощи трансляции адресов у вас на сервере нет (например, потому что у вас там нет прав root’а, а есть только доступ к оболочке).
Для решения такой задачи прекрасно подойдёт перенаправление TCP-порта с помощью SSH. Вы создаёте SSH-соединение на шлюз, внутри которого будет передавать трафик будущего соединения. Вы просите ssh выполнить перенаправление портов, в результате чего он открывает на прослушивание какой-либо локальный порт, обращение на который передаётся SSH-серверу на шлюз, который в свою очередь передаёт его серверу-получателю, то есть на RDP-сервер (причём делает это от своего имени; обратный адрес IP-пакетов будет адресом сервера).
Трафик внутри SSH-туннеля шифруется, поэтому перенапраление портов может быть очень полезным для шифрования данных незащищённых протоколов, например, POP3, или создания небольших виртуальных сетей. С другой стороны, нужно иметь в виду, что с помощью перенаправления портов легко организовать доступ изнутри сети наружу или наоборот, и не забывать об этом особенно при выделении учётных записей с доступом к облочке (по-русски говоря, шелла) на шлюзе (по сути, это равносильно предоставлению доступа ко внутренней сети снаружи).
Перенаправление портов может быть отключено либо в конфигурационном файле программ ssh и sshd, либо на стадии их компиляции. Тем не менее пользователь может иметь собственные программы переадресации, на которые конфигурация ssh и sshd не будет оказывать никакого влияния.
Различают два вида перенаправления портов:
Локальное. Клиент принимает подключение и посылает запрос на инициирование соединения SSH-серверу, который в свою очередь устанавливает незащищённое соединение с адресатом;
Удаленное. Сервер принимает подключение и посылает запрос на инициирование соединения SSH-клиенту.
Фактически два этих режима отличаются только тем, с какой стороны будет инициироваться соединение: со стороны клиента или со стороны сервера.
Главным опциями, переводящими ssh в режим перенаправления портов являются -L (локальное перенаправление) и -R (удаленное перенаправление). Кроме того могут быть дополнительно полезны некоторые другие ключи.
Ключи ssh полезные при перенаправлении портов.
- L порт:хост:хостпорт — Выполнить локальное перенаправление портов. При обращении на порт локальной машины будет создан туннель на порт хостпорт указанного хоста.
- R порт:хост:хостпорт — Выполнить удалённое перенаправление. При обращении на порт удаленной машины будет создан SSH-туннель и соединение будет переадресовано на хостпорт указанного хоста.
- N — Не выполнять команду удалённо. Используется только при перенаправлении портов.
- f — Перейти в фоновый режим работы, сразу же после регистрации на удалённой системе.
SSH через HTTP-прокси
Для этого необходимо чтобы на прокси-сервере был разрешён метод CONNECT. Обычно он разрешён как минимум на 443 порт. Если SSH-сервер с той стороны прокси работает на 443 порту, то обратиться на него через SSH не составит никакого труда. Существует несколько программ для этого, самая популярная — corkskrew.
После того как программа установлена, можно добавить в ~/.ssh/config такие строки:
Host *
ProxyCommand corkscrew http-proxy.example.com 8080 %h %p
Обращения на все хосты будут выполняться теперь через прокси http-proxy.example.com (порт 8080).
Протокол HTTP
HTTP — широко распространённый протокол передачи данных, изначально предназначенный для передачи гипертекстовых документов (то есть документов, которые могут содержать ссылки, позволяющие организовать переход к другим документам).
Протокол HTTP предполагает использование клиент-серверной структуры передачи данных. Клиентское приложение формирует запрос и отправляет его на сервер, после чего серверное программное обеспечение обрабатывает данный запрос, формирует ответ и передаёт его обратно клиенту. После этого клиентское приложение может продолжить отправлять другие запросы, которые будут обработаны аналогичным образом.
Задача, которая традиционно решается с помощью протокола HTTP — обмен данными между пользовательским приложением, осуществляющим доступ к веб-ресурсам (обычно это веб-браузер) и веб-сервером. На данный момент именно благодаря протоколу HTTP обеспечивается работа Всемирной паутины.
Также HTTP часто используется как протокол передачи информации для других протоколов прикладного уровня, таких как SOAP, XML-RPC и WebDAV. В таком случае говорят, что протокол HTTP используется как «транспорт».
API многих программных продуктов также подразумевает использование HTTP для передачи данных — сами данные при этом могут иметь любой формат, например, XML или JSON.
Как правило, передача данных по протоколу HTTP осуществляется через TCP/IP-соединения. Серверное программное обеспечение при этом обычно использует TCP-порт 80 (и, если порт не указан явно, то обычно клиентское программное обеспечение по умолчанию использует именно 80-й порт для открываемых HTTP-соединений), хотя может использовать и любой другой.
Стартовая (начальная) строка запроса для HTTP 1.1 составляется по следующей схеме:
Метод URI HTTP/Версия
Например (такая стартовая строка может указывать на то, что запрашивается главная страница сайта):
GET / HTTP/1.1
URI (Uniform Resource Identifier, унифицированный идентификатор ресурса) — путь до конкретного ресурса (например, документа), над которым необходимо осуществить операцию (например, в случае использования метода GET подразумевается получение ресурса). Некоторые запросы могут не относиться к какому-либо ресурсу, в этом случае вместо URI в стартовую строку может быть добавлена звёздочка (астериск, символ «*»). Например, это может быть запрос, который относится к самому веб-серверу, а не какому-либо конкретному ресурсу. В этом случае стартовая строка может выглядеть так:
OPTIONS * HTTP/1.1
Стартовая строка ответа имеет следующую структуру:
HTTP/Версия Код состояния Пояснение
Версия протокола здесь задаётся так же, как в запросе.
Код состояния (Status Code) — три цифры (первая из которых указывает на класс состояния), которые определяют результат совершения запроса. Например, в случае, если был использован метод GET, и сервер предоставляет ресурс с указанным идентификатором, то такое состояние задаётся с помощью кода 200. Если сервер сообщает о том, что такого ресурса не существует — 404. Если сервер сообщает о том, что не может предоставить доступ к данному ресурсу по причине отсутствия необходимых привилегий у клиента, то используется код 403. Спецификация HTTP 1.1 определяет 40 различных кодов HTTP, а также допускается расширение протокола и использование дополнительных кодов состояний.
Пояснение к коду состояния (Reason Phrase) — текстовое (но не включающее символы CR и LF) пояснение к коду ответа, предназначено для упрощения чтения ответа человеком. Пояснение может не учитываться клиентским программным обеспечением, а также может отличаться от стандартного в некоторых реализациях серверного ПО.
Сам по себе протокол HTTP не предполагает использование шифрования для передачи информации. Тем не менее, для HTTP есть распространённое расширение, которое реализует упаковку передаваемых данных в криптографический протокол SSL или TLS.
Название этого расширения — HTTPS (HyperText Transfer Protocol Secure). Для HTTPS-соединений обычно используется TCP-порт 443. HTTPS широко используется для защиты информации от перехвата, а также, как правило, обеспечивает защиту от атак вида man-in-the-middle — в том случае, если сертификат проверяется на клиенте, и при этом приватный ключ сертификата не был скомпрометирован, пользователь не подтверждал использование неподписанного сертификата, и на компьютере пользователя не были внедрены сертификаты центра сертификации злоумышленника.
Протокол HTTP предполагает достаточно большое количество возможностей для расширения. В частности, спецификация HTTP 1.1 предполагает возможность использования заголовка Upgrade для переключения на обмен данными по другому протоколу. Запрос с таким заголовком отправляется клиентом. Если серверу требуется произвести переход на обмен данными по другому протоколу, то он может вернуть клиенту ответ со статусом «426 Upgrade Required», и в этом случае клиент может отправить новый запрос, уже с заголовком Upgrade.
Такая возможность используется, в частности, для организации обмена данными по протоколу WebSocket (протокол, описанный в спецификации RFC 6455, позволяющий обеим сторонам передавать данные в нужный момент, без отправки дополнительных HTTP-запросов): стандартное «рукопожатие» (handshake) сводится к отправке HTTP-запроса с заголовком Upgrade, имеющим значение «websocket», на который сервер возвращает ответ с состоянием «101 Switching Protocols», и далее любая сторона может начать передавать данные уже по протоколу WebSocket.
принципы IP
IP implements packet-switched networking. It has a concept of hosts, which are machines. The IP protocol specifies how datagrams (packets) are sent between these hosts.
A packet is a chunk of binary data that has a source host and a destination host. An IP network will then simply transmit the packet from the source to the destination. One important aspect of IP is that packets are delivered using best effort. A packet may be lost along the way and never reach the destination. Or it may get duplicated and arrive multiple times at the destination.
Each host in an IP network has an address – the so-called IP address. Each packet contains the source and destination hosts’ addresses. The IP is responsible for routing datagrams – as the IP packet travels through the network, each node (host) that it travels through looks at the destination address in the packet to figure out in which direction the packet should be forwarded.
Today, most packages are still IPv4 (Internet Protocol version 4), where each IPv4 address is 32 bits long. They’re most often written in dotted-decimal notation, like so: 198.51.100.42
The newer IPv6 standard is slowly gaining traction. It has a larger address space: its addresses are 128 bits long. This allows for easier routing as the packets travel through the network. And since there are more available addresses, tricks such as network address translation are no longer necessary. IPv6 addresses are represented in the hexadecimal system and divided into eight groups separated by colons, e.g. 2001:0db8:85a3:0042:1000:8a2e:0370:7334.
IPv4 Header
The header is 20 bytes long (without options, which are rarely used).
The most interesting parts of the header are the source and destination IP addresses. Aside from that, the version field will be set to 4 – it’s IPv4. And the protocol field specifies which protocol the payload is using. TCP’s protocol number is 6. The total length field specified is the length of the entire packet – header plus payload.
IPv6 Header
IPv6 uses addresses that are 128 bits long.
The IPv6 header has a fixed length of 40 bytes.
The source and destination addresses are again the most interesting fields. In IPv6, the next header field specifies what data follows the header. IPv6 allows chaining of headers inside the packet. Each subsequent IPv6 header will also have a next header field until the actual payload is reached. When the next header field, for example, is 6 (TCP’s protocol number), the rest of the packet will be TCP data.
IP fragmentation
In IPv4, packets (datagrams) can get fragmented. The underlying transport layer will have an upper limit to the length of packet it can support. In IPv4, a router may fragment a packet if it gets routed onto an underlying data link for which the packet would otherwise be too big. These packets will then get reassembled at the destination host. The sender can decide to disallow routers to fragment packets, in which case they’ll send a Packet Too Big ICMP back to the sender.
In IPv6, a router will always drop the packet and send back a Packet Too Big ICMP6 message to the sender. The end points use this to do a path MTU discovery to figure out what the optimal so-called maximum transfer unit (MTU) along the path between the two hosts is. Only when the upper layer has a minimum payload size that is too big for this MTU will IPv6 use fragmentation. With TCP over IPv6, this is not the case.
TCP
TCP is built on top of IP. The Transmission Control Protocol provides reliable, ordered, error-checked delivery of a stream of data between programs. With TCP, an application running on one device can send data to an application on another device and be sure that the data arrives there in the same way that it was sent.
With TCP, applications establish connections between each other. A TCP connection is duplex and allows data to flow in both directions. The applications on either end do not have to worry about the data being split up into packets, or the fact that the packet transport is best effort. TCP guarantees that the data will arrive at the other end in pristine condition.
A typical use case of TCP is HTTP. Our web browser (application 1) connects to a web server (application 2). Once the connection is made, the browser can send a request through the connection, and the web server can send a response back through the same connection.
Multiple applications on the same host can use TCP simultaneously. To uniquely identify an application, TCP has a concept of ports. A connection between two applications has a source IP address and a source port on one end, and a destination IP address and a destination port at the other end. This pair of addresses, plus a port for either end, uniquely identifies the connection.
A web server using HTTPS will listen on port 443. The browser will use a so-called ephemeral port as the source port and then use TCP to establish a connection between the two address-port pairs.
TCP runs unmodified on top of both IPv4 and IPv6. The Protocol (IPv4) or Next Header (IPv6) field will be set to 6, which is the protocol number for TCP.
TCP Segments
The data stream that flows between hosts is cut up into chunks, which are turned into TCP segments. The TCP segment then becomes the payload of an IP packet.
Each TCP segment has a header and a payload. The payload is the actual data chunk to be transmitted. The TCP segment header first and foremost contains the source and destination port number – the source and destination addresses are already present in the IP header.
The header also contains sequence and acknowledgement numbers and quite a few other fields which are all used by TCP to manage the connection.
TCP Connections
In TCP, a connection is always established from one host to another. Hence, there are two different roles in connection setup: one end (e.g. the web server) is listening for connections, while the other end (e.g. our app) connects to the listening application (e.g. the web server). The server performs a so-called passive open – it starts listening. The client performs a so-called active open toward the server.
Connection setup happens through a three-way handshake. It works like this:
The client sends a SYN to the server with a random sequence number, A
The server replies with a SYN-ACK with an acknowledgment number of A+1 and a random sequence number, B
The client sends an ACK to the server with an acknowledgement number of B+1 and a sequence number of A+1
SYN is short for synchronize sequence numbers. Once data flows between both ends, each TCP segment has a sequence number. This is how TCP makes sure that all parts arrive at the other end, and that they’re put together in the right order. Before communication can start, both ends need to synchronize the sequence number of the first segments.
ACK is short for acknowledgment. When a segment arrives at one of the ends, that end will acknowledge the receipt of that segment by sending an acknowledgment for the sequence number of the received segment.
When the connection is created, both ends can send data to the other end. Each segment that is sent has a sequence number corresponding to the number of bytes sent so far. The receiving end will acknowledge packets as they are received by sending back segments with the corresponding ACK in the header.
Flow control is about making sure that the sending side doesn’t send data faster than the receiver (at either end) can process it. The receiver sends a so-called receive window, which tells the sender how much more data the receiver can buffer.
The basic idea is that the sender side looks at the acknowledgments it gets back. This is a very tricky business and there are various tradeoffs to be made. Remember that the underlying IP packets can arrive out of order, not at all, or twice. The sender needs to estimate what the round-trip time is and use that to figure out if it should have received an acknowledgement already. Retransmitting packets is obviously costly, but not retransmitting causes the connection to stall for a while, and the load on the network is likely to be very dynamic. The TCP algorithms need to constantly adapt to the current situation.
The important thing to note is that a TCP connection is a very lively and flexible thing. Aside from the actual data flow, both ends constantly send hints and updates back and forth to continuously fine-tune the connection.
Because of this tuning, TCP connections that are short-lived can be very inefficient. When a connection is first created, the TCP algorithms still don’t know what the conditions of the network are. And toward the end of the connection lifetime, there’s less information flowing back to the sender, which therefore has a harder time estimating how things are moving along.
XML
С физической точки зрения документ состоит из сущностей (англ. entities), из которых каждая может отсылать на другую сущность. Единственный корневой элемент — документная сущность. Содержание сущностей — символы.
С логической точки зрения документ состоит из комментариев (англ. comments), объявлений (англ. declarations), элементов (англ. elements), ссылок на сущности (англ. character references) и инструкций обработки (англ. processing instructions). Всё это в документе структуризуется разметкой (англ. markup).
Документ состоит из сущностей, содержание которых — символы. Все они разделены на два типа: символьные данные (англ. character data) и разметки. К разметке принадлежат: теги (англ. tags), обозначающие границы элементов, объявления и инструкции обработки, включая их атрибуты (англ. attributes), ссылки на сущности, комментарии, а также последовательности символов, обрамляющие секции «CDATA». Часть документа, не принадлежащая разметке, составляет символьные данные документа.
Все составляющие части документа обобщаются в пролог и корневой элемент. Корневой элемент — обязательная часть документа, составляющая всю его суть (пролог, вообще говоря, может отсутствовать). Может включать (а может не включать) вложенные в него элементы и символьные данные, а также комментарии. Вложенные в корневой элемент элементы, в свою очередь, могут включать вложенные в них элементы, символьные данные и комментарии, и так далее. Пролог может включать объявления, инструкции обработки, комментарии. Его следует начинать с объявления XML, хотя в определённой ситуации допускается отсутствие этого объявления.
Элементы документа должны быть правильно вложены: любой элемент, начинающийся внутри другого элемента (то есть любой элемент документа, кроме корневого), должен заканчиваться внутри элемента, в котором он начался. Символьные данные могут встречаться внутри элементов как непосредственно так и в специальных секциях «CDATA». Объявления, инструкции обработки и элементы могут иметь связанные с ними атрибуты. Атрибуты используются для связывания с логической единицей текста пар имя-значение.
Объявление XML указывает версию языка, на которой написан документ. Поскольку интерпретация содержимого документа зависит от версии языка, то Спецификация предписывает начинать документ с объявления XML. В первой (1.0) версии языка использование объявления не было обязательным, в последующих версиях оно обязательно. Таким образом, версия языка определяется из объявления, и если объявление отсутствует, то принимается версия 1.0.
Кроме версии XML,объявление может также содержать информацию о кодировке документа
Для объявления типа документа существует специальная инструкция !DOCTYPE. Она позволяет задать при помощи языка DTD, какие в документ входят элементы, каковы их атрибуты, какие сущности могут использоваться и кое-что ещё.
После XML-объявления могут следовать комментарии, инструкции обработки или же пустые пространства[11], но затем идёт Объявления типа документа, где «Name» — имя корневого тега, «ExternalID» — внешний идентификатор, а «intSubset» — объявление разметки или же ссылка на сущность. Как гласит спецификация, если внешний идентификатор объявляется вместе с внутренним объявлением, то последнее идёт перед первым
Элемент (англ. element) является понятием логической структуры документа. Каждый документ содержит один или несколько элементов. Границы элементов представлены начальным и конечным тегами. Имя элемента в начальном и конечном тегах элемента должно совпадать. Элемент может быть также представлен тегом пустого, то есть не включающего в себя другие элементы и символьные данные, элемента.
Для решения задачи преобразования документа XML в другую схему или другой формат предназначен язык XSLT.
Для форматированного документа (документа, подготовленного к визуализации) предназначен формат XSL-FO.
XPath — синтаксис для адресации содержимого документа, представленного в форме дерева. Выражения XPath используются в языке XQuery. Выражения XPath, вообще говоря, могут использоваться в любом контексте, где уместно использовать формальные ссылки на элементы дерева, в частности, в качестве параметров для методов интерфейсов доступа к документу.
XQuery — язык программирования, ориентированный на работу с документами.
Для чтения XML есть три варианта API[13].
Событийный API (event-driven API, push-style API) — XML-процессор читает XML; при определённом событии (появлении открывающего или закрывающего тега, текстовой строки, атрибута) вызывается callback-функция.
+ Расходует мало памяти[13].
+ При обработке огромного XML есть стандартная точка, позволяющая мгновенно остановить обработчик[13].
− Крайне сложен для прикладного программиста: приходится держать в памяти информацию, в каком месте документа мы находимся.
+ Библиотека проста в программировании.
− Затруднена поддержка перекрёстных ссылок: надо организовать временное хранение строковых ссылок, а когда документ будет считан — преобразовать идентификаторы в указатели.
− При ошибке в XML в памяти остаётся полусозданная структура предметной отрасли; программист должен своими руками корректно уничтожить её.
− API только для чтения, для записи потребуется другой API.
± Естественный выбор, когда из огромного XML надо извлечь немного данных[13].
± Естественный выбор, когда XML надо преобразовать в структуру предметной отрасли[13].
Примеры библиотек: SAX, Expat
Потоковый API (также pull-style API) — устроен на манер потоков ввода-вывода.
+ Расходует мало памяти.
± Информация, в каком месте документа мы находимся, неявно задаётся местом в потоке выполнения. Это серьёзно упрощает работу прикладного программиста. На продуманных API объём кода приближается к таковому для DOM.
− Библиотека сложна в программировании.
− Сложно сделать, чтобы «почти верные» XML с перепутанным порядком тегов работали правильно.
− Затруднена поддержка перекрёстных ссылок.
− При ошибке в XML в памяти остаётся полусозданная структура предметной отрасли; программист должен своими руками корректно уничтожить её.
− API только для чтения, для записи потребуется другой API.
Примеры библиотек: StAX
Объектный API (Document Object Model, DOM, «объектная модель документа») — считывает XML и воссоздаёт его в памяти в виде объектной структуры.
− Расходует много памяти — намного больше, чем сам XML занимает на диске. На pugixml расход памяти втрое и более превышает длину XML.
+ Прост для прикладного программиста.
+ Библиотека проста в программировании.
+ Зачастую удаётся распознать «почти верные» XML с перепутанным порядком тегов.
+ Позволяет произвольный доступ к XML[13]. Это, например, упрощает работу с перекрёстными ссылками.
+ При ошибке в XML в памяти остаётся полусозданная структура XML, которая будет автоматически уничтожена самой библиотекой.
+ Общий API для чтения и записи.
± Естественный выбор, когда объектом предметной области является сам XML: например, в веб-браузере[13], XML-редакторе, в импортёре к программе-локализатору, который извлекает строки из XML произвольной структуры.
± Естественный выбор, когда нужно загрузить XML, слегка переработать и сохранить[13]. Те части, которые трогать не нужно, не требуют никакого кода.
Примеры библиотек: JDOM, TinyXML, pugixml
API прямой записи записывает XML тег за тегом, атрибут за атрибутом.
+ Быстр, нет промежуточных объектов.
− Примитивная библиотека может делать неоптимальный XML (например, вместо ). Работающая оптимально намного сложнее в программировании.
− Непригоден для отдельных специфических задач.
− Если структуры предметной области работают ненадёжно, без специальных мер (записать в память или в другой файл, потом переименовать) можно остаться с «упавшей» программой и потерянным файлом.
− При ошибке программиста может получиться синтаксически некорректный XML.
− API только для записи, для чтения потребуется другой API.
Объектный API, он же Document Object Model.
− Создаёт объектную структуру для XML, что может отнять памяти больше, чем структура предметной отрасли.
± Универсален (впрочем, в большинстве задач преимущества над хорошо проработанным API прямой записи нет — в отличие от чтения).
+ Даже если структуры предметной области работают ненадёжно, а программист не предусмотрел никакой «защиты», единственный сценарий, когда файл перезаписывается на неполный — нехватка места на диске.
+ Общий API для записи и чтения.
Примеры библиотек: те же, что и для чтения XML методом DOM.
XML — язык разметки, другими словами, средство описания документа. Именно в нише документов, текстов, где доля разнотипных символьных данных велика, а доля разметки мала — XML успешен. С другой стороны, обмен данными в открытых системах не сводится к обмену документами. Избыточность разметки XML (а в целях разработки языка прямо указано, что лаконичность не является приоритетом проекта) сказывается в ситуациях, когда данные не вписываются в традиционную модель документа.
HTML
Язык HTML интерпретируется браузерами; полученный в результате интерпретации форматированный текст отображается на экране монитора компьютера или мобильного устройства.
Язык HTML до 5-й версии определялся как приложение SGML (стандартного обобщённого языка разметки по стандарту ISO 8879). Спецификации HTML5 формулируются в терминах DOM (объектной модели документа).
Язык XHTML является более строгим вариантом HTML, он следует синтаксису XML и является приложением языка XML в области разметки гипертекста.
Во всемирной паутине HTML-страницы, как правило, передаются браузерам от сервера по протоколам HTTP или HTTPS, в виде простого текста или с использованием шифрования.
Любой документ на языке HTML представляет собой набор элементов, причём начало и конец каждого элемента обозначается специальными пометками — тегами. Элементы могут быть пустыми, то есть не содержащими никакого текста и других данных. В этом случае обычно не указывается закрывающий тег (например, тег переноса строки <br></br> — одиночный и закрывать его не нужно) . Кроме того, элементы могут иметь атрибуты, определяющие какие-либо их свойства (например, атрибут href=” у ссылки). Атрибуты указываются в открывающем теге.
Кроме элементов, в HTML-документах есть и сущности (англ. entities) — «специальные символы». Сущности начинаются с символа амперсанда и имеют вид &имя; или NNNN;, где NNNN — код символа в Юникоде в десятичной системе счисления.
Каждый HTML-документ, отвечающий спецификации HTML какой-либо версии, должен начинаться со строки объявления версии HTML >
Далее обозначается начало и конец документа тегами и соответственно. Внутри этих тегов должны находиться теги заголовка () и тела () документа.
Язык разметки HTML включает поддержку клиентских скриптов (сценариев), которые могут быть выполнены во время загрузки документа или позже. Скрипты могут быть как внешними (js-файлы), так и внутренними (элемент или атрибуты обработчиков событий в самих элементах).
Элемент
может располагаться либо в <head>, либо в <body>-элементе (перед закрывающим </body>).
Скрипты используются, например, для обработки событий от клавиатуры, мыши, событий от форм, общего состояния документа.
Форма задаётся с помощью элемента <form>, внутри которого и располагаются элементы управления. Кроме общих для HTML атрибутов, в <form> могут присутствовать следующие:
action (действие) — обязательный атрибут (в HTML5 — нет), содержащий URI обработчика формы;
method (метод отправки формы) — атрибут, принимающий значения GET (по умолчанию) или POST;
enctype (тип кодирования для содержимого) — по умолчанию application/x-www-form-urlencoded (всегда для метода GET), но обычно употребляется multipart/form-data;
accept — список MIME-типов для загрузки файлов;
name — имя формы;
onsubmit — обработчик события «форма отправлена» (для скриптов);
onreset — обработчик события: «форма очищена» (тоже для скриптов);
accept-charset список поддерживаемых наборов символов.