OpenVPN отклоняет первую строку? Вероятно, файл в UTF-16
Ошибка в первой строке со странными символами обычно означает, что профиль сохранён как UTF-16. Прочитайте первые байты и затем правильно преобразуйте файл.
Ошибка указывает на первую строку файла .ovpn и цитирует нечто похожее на перемешанные буквы там, где должно быть client. Файл нормально открывается в вашем редакторе, первая строка читается как client, а директива совершенно обычная. Оба наблюдения верны, потому что редактор декодирует байты, а клиент нет. То, что вы видите, почти всегда проблема кодировки, а не синтаксиса.
Миф: редактор показывает вам файл
Текстовый редактор декодирует байты в символы с помощью кодировки, которую он либо определяет, либо угадывает. Когда он угадывает UTF-16, файл выглядит на экране безупречно, хотя байты под ним — пары, после каждой латинской буквы идёт нулевой байт. OpenVPN читает эти байты как символы, и несоответствие проявляется на первой директиве, которую он пытается разобрать.
Итак, видимая строка и доставленная строка — две разные вещи. Удаление странных символов, которые вы видите, меняет отображение, а не кодировку, и следующий разбор терпит неудачу по той же причине с чуть иным сообщением. Поэтому погоня за токеном из ошибки всегда никуда не ведёт. Байты неверны в источнике, и каждый последующий читатель угадывает ту же испорченную последовательность.
Конкретную форму сбоя стоит узнавать, потому что она по-своему диагностична. Токен в самом начале файла, в профиле, который в остальном работал на других машинах, — это вопрос порядка байтов, а не словаря.
Что на самом деле говорят первые байты
Читайте байты, а не символы. Две небольшие команды решают вопрос за секунды, и ни одна не требует открывать файл в приложении, которое может его изменить:
file client.ovpn
head -c 24 client.ovpn | od -An -tx1
Шаблон, который вы ищете, — это пара начальных байтов, за которой идёт текст, где каждый второй байт нулевой. FF FE обозначает UTF-16 little-endian, FE FF — big-endian, а EF BB BF — UTF-8 с меткой порядка байтов. Обычный файл UTF-8 без метки начинается прямо с байта первой буквы.
Нулевые байты между буквами — главная примета. В UTF-16 little-endian слово client занимает двенадцать байтов вместо шести, потому что за каждым символом ASCII идёт ноль. Такую структуру экран редактора вам не покажет, и удаление двух байтов её не уберёт.
Здесь есть важный нюанс: читатель конфигурации OpenVPN действительно пропускает метку порядка байтов UTF-8 в начале файла, как показывает читатель конфигурации 2.6. Эта терпимость относится именно к этой метке и ничего не делает для файла UTF-16, буквы которого дополнены нулями. Считать обе метки одной проблемой — вторая половина мифа.
Преобразование — это «сохранить как», а не удаление
Прежде чем что-либо делать, сохраните нетронутую копию оригинала оператора и работайте с отдельным файлом. Профиль может содержать закрытый ключ или данные учётной записи, поэтому копия — и ваш откат, и ваш ориентир.
Затем выполните настоящее преобразование кодировки — либо через явное меню кодировки в редакторе, либо конвертером, который указывает входную и выходную кодировку:
iconv -f UTF-16 -t UTF-8 client.ovpn > client-utf8.ovpn
file client-utf8.ovpn
Проверьте результат, а не полагайтесь на код возврата команды. Преобразование должно сохранить каждую директиву и обязано сохранить любой встроенный блок сертификата или ключа байт в байт внутри его маркеров. Переупаковка данных PEM, изменение окончаний строк внутри блока или переформатирование профиля во время преобразования создаёт новую проблему, пока исправляется старая.
Направьте клиент или службу на преобразованный файл и посмотрите на первую ошибку, о которой он сообщит. Если перемешанный токен исчез, работа с кодировкой закончена, а всё, что не сработает после, — уже другой вопрос.
Чего исправленная кодировка не исправляет
Кодировка определяет, как читается текст; она ничего не говорит о том, допустимы ли параметры для клиента перед вами. Профиль, экспортированный для другой реализации, может разбираться чисто и всё равно быть отклонён из-за параметра, который работающая сборка не поддерживает, или из-за директивы, аргумент которой в этом клиенте значит другое.
Эти поздние ошибки заслуживают собственного расследования: точного написания, синтаксиса аргумента и версии, которая его принимает. Не считайте успешный разбор успешным профилем.
Держите расследование локальным, пока занимаетесь этим. Публичные онлайн-конвертеры и вставленные hex-дампы — плохое место для файла, который может содержать закрытый ключ, потому что проблему кодировки легко исправить, а утёкший ключ — нет.