Тут блог про starttls
Раптово виявилося, що майже всі протоколи Інтернету передають цінні дані відкритим текстом. І будь-який чувак, який зможе перехопити трафік, зможе витягти ці цінні дані. Звичайно, фоточки котиків і фільми відомого змісту - не дуже-то і цінні. Але ось логін-пароль для платного доступу до котиків, або ідентифікатор сесії, коли логін-пароль вже введений, - вже цінні.
Тому придумали SSL. З точки зору програми - майже такий же звичайний TCP сокет, ось тільки передані дані зашифровані. І ніякої чувак посередині ваших котиків більше не побачить. Якщо, звичайно, він не працює в правильних організаціях, чиїм обов'язком є пильнувати.
SSL / TLS - це гібридна криптосистема. У нас є клієнт, і є сервер. Клієнт завжди підключається до сервера. У сервера є приватний ключ, який завжди при ньому. І у сервера є публічний ключ, у вигляді сертифіката, підписаного якимось центром сертифікації. Ну або підписаний ключем самого сервера - самоподпісанний сертифікат. Сертифікат містить ім'я сервера, відомості про його власника та інше. Правильність цих відомостей підтверджується підписом. Центри сертифікації підписують сертифікати за гроші. Це організації, які дорожать своєю репутацією, а ми їм довіряємо. І на цій довірі все і тримається.
Клієнт, коли підключається до сервера, отримує його сертифікат. Він перевіряє: а чи дійсно це сертифікат того сервера, до якого ми підключаємося? А чи не минув термін дії сертифіката? А чи довіряємо ми тому центру сертифікації, що підписав цей сертифікат? Іноді сертифікат буває і у клієнта, і він пред'являє його серверу, а сервер виробляє подібні ж перевірки. Якщо все ок, то йдемо далі.
Використовуючи асиметричне шифрування. приватні ключі і публічні ключі з сертифікатів, клієнт і сервер домовляються про ключі сесії. Це ключ вже симетричного шифрування. І цим ключем будуть зашифровані наступні дані. Все секурно і красиво, якщо ви користуєтеся свіженькими реалізаціями TLS. Всі SSL, версії від 1.0 до 3.0, нині вважаються небезпечними. Безпечні - це TLS 1.1 або 1.2, і, може бути, TLS 1.0.
Добре, у нас є надійний спосіб шифрувати TCP з'єднання. Але у нас є і старі добрі, вже працюють протоколи. Як додати до них шифрування?
Спочатку вирішили: а давайте назвемо це новим протоколом і повісимо на окремий TCP порт. До імені протоколу як правило додають букву S - Secure. Так HTTP став HTTPS і переїхав з порту 80 на порт 443. FTP став FTPS. замість портів 21-20 став використовувати порти 990-989. Не плутати з SFTP. який використовує шифрування SSH, а не SSL. SMTP. протокол пересилання пошти, став SMTPS і переїхав з порту 25 на порт 465. У пошті взагалі багато протоколів: POP3 → POP3S - 110 → 995, IMAP → IMAPS - 143 → 993. Навіть в Jabber, він же XMPP. спочатку пішли цим шляхом, для клієнтських SSL підключень замість порту 5222 взяли порт 5223, для междусерверних підключень замість 5269 взяли порт 5270. О боже, навіть telnets придумали, на порту 992.
Цей підхід, коли для SSL шифрування виділяється окремий порт, сам вихідний протокол ніяк не змінюється, а просто загортається в SSL, називається SSL wrapping. Навіть була утилитка, яка так і називалася sslwrap. і дозволяла додати SSL до будь-якого протоколу.

У такого обертання є свої недоліки. У нас додається цілий новий порт. По-хорошому, його треба реєструвати в IANA. Його треба відкривати в брандмауера. Цей порт повинен хтось слухати, а значить, у нас буде в два рази більше демонів: на старому незашифрованому порту, і на новому SSL порту. Нарешті, так як обмін сертифікатами і домовленість про параметри шифрування відбуваються ще до початку роботи нашого прикладного протоколу, деякі можливості цього протоколу перестають працювати.
Хороший приклад: віртуальний хостинг в HTTP, він перестав працювати в HTTPS. У нас є один HTTP сервер, а обслуговує він кілька сайтів, з різними доменними іменами. У HTTP / 1.1 клієнт в кожному запиті вказати назву Host. куди поміщає відповідну частину URL. Сервер дивиться на цей заголовок, і вибирає, до якого він обслуговує сайту відноситься запит. Все просто. Але у випадку з SSL клієнт запитує і перевіряє сертифікат сервера ще до передачі будь-яких заголовків. І в сертифікаті міститься доменне ім'я сервера. І клієнт засвідчується що це саме те ім'я, до якого він звертається. По-хорошому, у кожного сайту повинен бути свій сертифікат. А тут виходить, що на одному 443 порту може бути тільки один сертифікат, який не може відповідати всім сайтам відразу. Ось і не працює.
У спробі обійти ці труднощі вирішили піти іншим шляхом. Розширити протоколи, щоб можна було почати сеанс зв'язку без шифрування, а потім переключитися на шифрування, якщо і клієнт, і сервер його підтримують. Це красиво називається Opportunistic TLS. А команда, що включає шифрування, називається STARTTLS.
Спочатку клієнт підключається до сервера як зазвичай, без шифрування. В ході початку переговорів, за правилами даного протоколу, клієнт і сервер з'ясовують свої можливості. Якщо і клієнт, і сервер можуть і хочуть шифруватися, клієнт посилає команду STARTTLS. Після цього починається звичайна для TLS процедура обміну сертифікатами і узгодження ключів. Якщо вона завершується успішно, наступні команди в сеансі між клієнтом і сервером вже йдуть по зашифрованому каналу.
У разі SMTP це виглядає приблизно так. Можна перевірити звичайним telnet.
Клієнт запитує у сервера, які фичи він підтримує: командою EHLO. Сервер каже, що, серед іншого, він вміє STARTTLS: 250-STARTTLS. Клієнт говорить STARTTLS. Сервер каже: я готовий, починай. Після цього і треба починати TLS, тільки telnet цього не вміє.

У XMPP, так як це протокол на основі XML. STARTTLS виглядає як XML тег.
В OpenSSL є вбудований клієнт, який вміє робити STARTTLS. Наприклад для SMTP.
Клієнт досить убогий, але воно й зрозуміло, бо тільки для тестів. Він дуже забавно сприймає деякі символи, тому команди SMTP краще набирати маленькими буквами: rcpt to. тому що велика R змушує цей клієнт робити реконнект. Проте, він вміє робити STARTTLS для smtp, pop3, imap і ftp (параметр -starttls).
Використовувати один і той же порт для незашифрованих і для шифрованих з'єднань виявилося так зручно, що окремі порти для SSL швиденько оголосили застарілими. Так що тепер стандартний і кошерний спосіб робити TLS - це STARTTLS.
Може здатися, що це небезпечно, адже ми починаємо сесію без шифрування. Але шифрування включається відразу ж, як обидві сторони вирішать, що воно їм потрібно. Відкритим текстом видно тільки загальні підтримувані можливості клієнта і сервера. І клієнт, і сервер можна налаштувати так, щоб вони вимагали використання команди STARTTLS. В цьому випадку потрібно, щоб STARTTLS був однією з перших команд в сесії, до передачі важливих даних. Інакше подальша робота блокується згідно з протоколом.
А ось з HTTPS якось не склалося. Можливо, тому, що в HTTP не передбачено тривалих сесій між клієнтом і сервером, STARTTLS просто нікуди встромляти. Втім, подібна спроба робилася в RFC 2817. але не прижилася. Там пропонувалося робити Upgrade протоколу до TLS, приблизно як зараз робиться для WebSocket або для одночасної підтримки HTTP і HTTP / 2.
OpenSSLний клієнт можна і для SSL wrapper використовувати. (Тема Host для запиту в HTTP / 1.1 є обов'язковим)
Але зараз віртуальні хостинги цілком живуть під HTTPS, викручуються. Можна взяти wildcard сертифікат. на домен * .myhost.example. і все піддомени зможуть прикриватися цим сертифікатом. Можна включити в один сертифікат кілька доменних імен, найчастіше за допомогою розширення для сертифікатів під назвою subjectAltName. Ми просто вказуємо в одному сертифікаті доменні імена всіх сайтів на нашому сервері. Ось тільки для додавання ще одного сайту сертифікат доведеться перевипускати.

У HTTP / 2 все залишається без істотних змін. Специфікація не вимагає обов'язкового TLS, існують URL зі схемою http і https. Але існуючі реалізації працюють тільки з TLS. При цьому потрібно TLS 1.2 або вище і підтримка Server Name Indication.
Проте, для HTTP / 2 є забавний чернетку Opportunistic Security for HTTP. Щоб для http URL працював TLS, якщо клієнт з сервером домовляться. Замість однієї команди STARTTLS в цьому чернетці передбачається обмін JSONамі.