Хотел бы поделиться ещё тем, как сделать так, чтобы соединение от VPS до сайтов ходило через сторонний VPN.
Hidden text
Таким образом иногда удаётся обходить ограничения самих сайтов, которые понимают, что ваш VPS из компании нежелательной страны, хоть и физически находится в другой стране. Например, у меня при прочих равных через VPS напрямую тикток показывает замороженный русский вариант, а через такую схему — рабочий западный.
Т.е. общая схема будет такая:
От вас в стране с цензурой до заграничного VPS будет продолжать работать XRay с XTLS-Reality (или другой XRay вариант), чтобы скрывать сам факт обхода блокировок.
От вашего заграничного VPS трафик будет идти к оплаченному серверу VPN какой-нибудь компании, предоставляющей такие услуги. Он будет идти через обычный OpenVPN шифруясь, но не маскируясь (считаем, что на той территории факт наличия VPN не пытаются вычислять и срубать), таким образом, мы скрываем статичный IP уже нашего VPS, плюс получаем возможность ходить через разные страны. Наш VPS относительно именно VPN будет выступать просто клиентом.
Я буду считать, что у вас настроен VPS по этой статье, но, в принципе, сойдёт любой работающий XRay-конфиг.
Идём на сайт вашего VPN провайдера, логинимся, получаем от них ovpn-файл. Обычно такие файлики дают скачивать, если мы выберем опцию в стиле, что хотим настроить VPN-клиент на роутере, либо на линуксе. Вот, чисто как пример.
Нам потребуется один файлик с одной локацией, через которую будем выходить. Логично взять ту же страну/город, в которой находится ваш VPS, чтобы меньше терять на пинге. Потом можно будет заморочиться с переключением на другие страны, если захотите. Скачиваем нужный ovpn-файл. Если скачали на свою машину, на VPS можно перекинуть по SSH (с винды см. Передача файлов с Windows на Linux Ubuntu по SSH).
Далее все инструкции на VPS. Ставим OpenVPN:
apt update
apt install openvpn -y
Переименовываем ovpn-файл в client.conf и переносим его в папку /etc/openvpn/ Открываем полученный файл на редактирование:
nano /etc/openvpn/client.conf
Находим там строчку
auth-user-pass
и меняем её на
auth-user-pass /etc/openvpn/pass
Создаём файл
nano /etc/openvpn/pass
В нём записываем две строчки:
логин
пароль
Это те логин и пароль, с которыми вы подсоединяетесь к VPN. Защитим их уровнем доступа:
chmod 400 /etc/openvpn/pass
Дальше снова открываем на редактирование файл
nano /etc/openvpn/client.conf
и дописываем в нём в конце файла такие строчки:
# Писать максимум 50 повторяющихся сообщений в логи (чтобы их не засорять)
mute 50
# Не рулить маршрутизацией. ВПН захочет развернуться для всех соединений,
# но это совсем не то, что нам нужно, маршрутизацией мы будем рулить сами.
route-nopull
# Сохранять соединение и переподключаться, если оно прерывается
keepalive 10 60
# Скрипт, который будет выполняться для установленного соединения
# Там мы будем рулить маршрутизацией
up /etc/openvpn/custom.sh
Создаём теперь вышеупомянутый скрипт
nano /etc/openvpn/custom.sh
В нём:
#!/bin/sh
# Таблица 200 пойдёт через tun0 (т.е. через впн)
ip route add default dev tun0 table 200
# Удаляем и добавляем правило, что пакеты, маркированные
# числом 2, будут отброшены
ip rule delete fwmark 2 blackhole
ip rule add fwmark 2 blackhole
# Удаляем и добавляем правило, что пакеты, маркированные
# числом 2, будут отправлены в таблицу 200 (и пойдут через впн).
ip rule delete fwmark 2 table 200
ip rule add fwmark 2 table 200
# Применяем правила
ip route flush cache
Мы получим два правила, которые касаются пакетов, маркированных двойкой, при этом их порядок будет такой, что сначала пакет полетит на впн, а если не получится (впн будет выключен), то пакет не пойдёт никуда. Если отбрасывание не написать, то мы при отсутствии впн будем ходить напрямую с VPS.
Т.е. все исходящие из xray пакеты, которые летят напрямую к сайтам (freedom), будут средствами XRay помечаться как 2, роутингом все пакеты с меткой 2 будут заворачиваться в таблицу 200, а она будет лететь через VPN.
Теперь осталось только запустить клиент OpenVPN как демона:
nano /etc/default/openvpn
Раскаменчиваем # у строчки
AUTOSTART="all"
Дальше регаем демона:
systemctl enable openvpn@client.service
Перегружаем демоны:
systemctl daemon-reload
Стартуем OpenVPN:
service openvpn@client start
И перегружаем xray:
systemctl restart xray
Разумеется, XRay можно настроить и получше, создав себе несколько пользователей, часть из которых будет ходить через VPN (помечая пакеты), а часть напрямую с VPS.
Сам я не настоящий линукс-пользователь, если кто предложит, как это сделать получше, буду только рад.
Ориентировался на эти инструкции:
Как настроить OpenVPN Client на Ubuntu. С этой статьи можно начать, чтобы проверить, что ваше клиентское OpenVPN-соединение вообще ходит нормально (до демонизации, роутинга и связи с XRay).
Я согласен с посылом статьи, что типы-обёртки — это классно. Но про VerifiedEmailAddress, который наследует EmailAddress, я вообще не понял. Какого типа будет поле email у класса User-то?
Если VerifiedEmailAddress, то что если он ещё не Verified?
Если EmailAddress, то при использовании всё равно нужно
if( email is VerifiedEmailAddress )
что по сути то же самое, что и
if( email.IsVerified() )
Если два поля, то это вообще жесть, да и всё равно вылезает что-то типа
Отныне флешка навсегда будет установлена в свободном USB порту вашего компьютера, до тех пор, пока вы обновите старое железо!
Я ведь правильно понимаю, что эта флешка нужна будет только в момент загрузки? Ну т.е. после загрузки ОС её можно будет спокойно вытащить (до следующей перезагрузки)? Или же к ней в момент работы ОС будут происходить обращения?
Исключение нужно для исключительной ситуации. ИМХО исключительные ситуации имеет смысл оптимизировать тогда, когда оптимизированы все штатные.
Судя по всему, предложенное решение сочетает в себе минусы и от retval в стиле Си, и от плюсовых исключений: и (сравнительно) медленное, и может легко быть проигнорировано. Опять же, если исключение должно лететь уровней на пять вверх, весь код там превратится в лапшу из if'ов и переупаковывания Expected'ов.
С чего бы вдруг я захочу/меня заставят делать х2, если х2 платить мне не будут? Вот если будут, тогда ещё можно подумать.
Другой вариант – внешний по отношению к работе стимул. Мой любимый – ипотека [...]
Оба варианта – внешние. Ты их не выбирал, ожидания изменились сами, а развиваться пришлось тебе, причём – очень быстро.
А как я могу не выбрать ипотеку сам, но при этом её получить?
«Это была все вина Джерри, он был ответственен за большую часть проекта»
Эти интервьюеры натренированы и заточены на то, чтобы идентифицировать дрянных людей и уделяют этому особое внимание.
А если так оно и было? Может коллега Джерри реально косячил со своей частью кода. Или это был Джерри из бизнеса, который развернул требования на 180 градусов незадолго до концов срока. ИМХО ничем не лучше как брать всю вину на себя и рассказывать на собеседовании, как здорово ты всё портил, так и рассказывать, что всё было идеально и ни с какими проблемами не сталкивался.
Про представление перечислимого множества в виде полинома можно почитать Ю. В. Матиясевич, «Диофантовы множества». Там автор приводит конструктивное доказательство, алгоритм, как из математического выражения, описывающего перечислимое множество (язык Я5 в терминологии автора), можно получить полином, его описывающий (язык Я0). Я лично целиком весь этот путь не проделывал, но автор пишет
Такой „перевод" с Я5 на Я0 требует чисто механической, нетворческой работы и в принципе может быть поручен вычислительной машине.
И с виду написано оно очень понятно и здорово, не нужно быть на 100% в теме всех тонкостей.
Во всём этом для меня лично особенно круто то, что для доказательства неразрешимости 10 проблемы Гильберта был проложен мост из математики в информатику, чтобы свести проблему в итоге к проблеме остановки. А ещё, имхо, нам очень повезло, что автор разговаривает на одном с нами языке, т.к. мы можем свободно послушать его лекции об этом всём на ютубе в оригинале.
«Незашифрованный контент при передаче возможно подменить исполняемым файлом, при открытии которого может быть выполнена вредоносная программа. Таким образом, что мало вероятно, но тем не менее возможно, при желании и определенных навыках злоумышленник может получить контроль над устройством. Более того, отсутствие шифрования делает устройство уязвимым для атак»
Не, ну это бред. Для этого должна быть определённая уязвимость нефильтрации входных данных, чтобы можно было выполнить произвольный код, да плюс ещё опционально уязвимость повышения прав в системе, чтобы «покинуть пределы приложения». А то эдак мы все уязвимы потому и только потому что браузер может в http-протокол.
Проблема отсутствия шифрования в том, что передаваемые данные могут быть кем-угодно прочитаны и переписаны. Т.е. если реквизиты банковской карты передаются, можно украсть деньги с этой карты, а если местоположение, то можно перенаправить такси на другой конец города. Но «овладевание» устройством — это вообще не про то.
Тут есть три варианта. HR (да и любой другой собеседующий) может:
Намеренно искать «косяк», чтобы сбить ЗП.
Просто не шарить/заблуждаться в критериях.
Может быть прав в своих критериях.
В именно такой ситуации, как была описана, можно просто соврать, что на предыдущей работе у вас были один/несколько из проектов на шарпе, и опыт есть. Хуже от этого никому не станет:
В случае 1 найдутся ещё какие-то косяки, по которым вам нужно платить на 50к меньше, и результат будет тот же.
В случае 2, если программист реально шарит (хотя и промышленного опыта реально не было), то он и пройдёт тех.собес, и работать будет отлично.
В случае 3, если вы переоценили свои силы, то вы просто не пройдёте тех.собес.
Это в статье вообще некорректный пример, и фиг знает, почему он вообще там есть, и есть именно там (в мощностях). Он больше запутывает.
Дело в том, что конкретный элемент может иметь только одно из двух отношений к конкретному множеству: либо присутствовать в нём, либо нет. Соответственно, либо в этом множестве есть пятёрка, либо пятёрки нет. Нескольких «одинаковых» элементов не бывает.
Формулирую задачу — сколько различных номеров длиной К, заканчивающихся на заданной кнопке р, можно набрать на клавиатуре телефона (тастатуре), если мы должны перемещаться по кнопкам ходом шахматного коня.
Такая задача, возможно, вызовет интерес у любителей задачек изначально. Может быть она чуть-чуть заинтересует тех, кто любит шахматы или просто имеет иррациональную страсть к закономерностям на кнопочных телефонах.
Но сторонников «математика не нужна» она лишний раз убедит, что математики варятся в своих абстрактных задачах ради самих задач, в абсолютном отрыве от реальности. И что все эти вектора и матрицы нужны для обсчёта бесконечных ходов сферических коней по шахматным телефонам, а не для «настоящих» задач.
ИМХО чтобы человек заинтересовался математикой, нужно показать, как математика поможет решить лично его проблему. Например, для меня (учился в классе 7 в это время) это была проблема такого плана: как заставить в моём прототипе недоигры на VBA бегать объект по окружности. Тригонометрические функции тогда стали для меня «магией», которая позволила «открыть глаза» и отбросить стереотипы о «ненужных знаниях после арифметики». И чем дальше, тем больше задач, о которые я безуспешно бился лбом, внезапно оказывались решены в сильно более общем случае три века назад именно в математике.
Собственно, «отбитость» моей задачи беганья по кругу для других людей может быть такого же уровня, как и задача из поста. Чтобы привлечь человека математикой, нужно показать ему решение той задачи, которая интересует лично его.
Ага. А ещё может быть так: что предки видели как линейную зависимость, а мы видим как экспоненту, потомки увидят как примерную синусоиду. моё_хобби_экстраполировать.жпг
не является бесполезным/вредным? Скотт Майерс в «Эффективный и современный С++. 42 рекомендации по использованию C++11 и C++14» писал, что в лучшем случае компилятор поймёт нас, хотя не обязан, а в худшем мы сломаем RVO/NRVO. Или в 17 стандарте что-то с тех пор кардинально поменялось?
Натыкался на одного человека, у него был блог: там было много политики, мата и всего этого. Понятно, что человек, так скажем, эмоциональный. Соответственно, это нужно учитывать: если у тебя в команде трое спокойные, а кто-то новый на дейликах будет все время поднимать бучу, это скажется на команде.
А может так человек пар выпускает в интернете, после чего как раз ему неинтересно нести эти темы в рабочий коллектив. ИМХО вообще не показатель.
Можно выработать привычку ставить будильник не на пробуждение, а на засыпание. Например, сигнал в 23:30 напомнит, что в 12 уже надо быть в кроватке и начать засыпать. Это совет, кстати, Мэтью Уолкер считает самым важным среди всех, касающихся гигиены сна.
Такой режим для меня — это прямо насилие над собой. Если я не хочу спать в определённое время, то я, скорее всего, и не усну. Буду ворочаться, перекладывать нагретую подушку, крутить в голове какие-то тупые мысли. Бесполезная и неприятная трата времени. Лучше уж поделать что-нибудь, а лечь тогда, когда организм решит, что ему это нужно. Конечно, таким образом можно просидеть всю ночь, а утром на работу — но это ничего. Это значит, что организм получит свой недосып, а на следующий день уже сам скорректирует своё хотение спать.
Но, конечно, оно у всех по-своему.
Я, конечно, понимаю, что прошло 10 лет, но, может быть, эта мечта всё ещё актуальна.
Когда-то задался для себя этой целью и нашёл программу HIDMacros. Она как раз отлично справлялась с двумя клавами: на одной можно было поставить шорткаты на клавиши так, что те теряли изначальное предназначение, при этом на другой у клавиш оставался прежний смысл. Даже пользовался какое-то время так двумя клавиатурами, но потом надоело.
Есть, правда, ложка дёгтя: программа больше не развивается автором, а на новых осях уже не работает (личный опыт: на WinXP x86 работала, на Win7 x64 уже нет). Хотя вместо неё автор мутит LuaMacros. Но ей лично я не пользовался, поэтому ничего уже сказать не могу.
В заключение ещё раз напомню, что все вышеописанные термины относятся к синтаксически валидному коду, который будет успешно скомпилирован. Код, невалидный с точки зрения Стандарта, называется ill-formed program.
Вот хотел ещё уточнить, может быть кто-нибудь из присутствующих подскажет. Я так понимаю, что если код не компилируется, то это значит, что он является ill-formed. Однако обратное неверно: код может скомпилироваться, но всё равно являться ill-formed, например, если в коде нарушено ODR. Так ли это? Нет ли ещё каких-нибудь вариантов компилирующегося кода, который при этом будет ill-formed?
И ещё такой вопрос по поводу успешности компиляции: а не может ли UB всё-таки вызвать ошибку компиляции (просто как возможность, не обязательно даже стабильное повторение)? Оно же всё-таки U. Может при развёртывании каких-нибудь шаблонов или макросов, например?
Хочется для себя по полочкам разложить, как эти все круги диаграммы Венна пересекаются, и что есть их пересечения: Implementation-defined behavior, Unspecified behavior, Undefined behavior, ill-formed, некомпилирующийся код.
Классно! Года четыре назад задумывался о чём-то таком, но руки не дошли (да и не возникло прям огромной необходимости). Грустно только, что приходится вот так вот извращаться для того, чтобы получить мидишку, которая в принципе для мелодии есть, но не у тебя.
Автор, огромное спасибо за цикл статей!
Хотел бы поделиться ещё тем, как сделать так, чтобы соединение от VPS до сайтов ходило через сторонний VPN.
Hidden text
Таким образом иногда удаётся обходить ограничения самих сайтов, которые понимают, что ваш VPS из компании нежелательной страны, хоть и физически находится в другой стране. Например, у меня при прочих равных через VPS напрямую тикток показывает замороженный русский вариант, а через такую схему — рабочий западный.
Т.е. общая схема будет такая:
От вас в стране с цензурой до заграничного VPS будет продолжать работать XRay с XTLS-Reality (или другой XRay вариант), чтобы скрывать сам факт обхода блокировок.
От вашего заграничного VPS трафик будет идти к оплаченному серверу VPN какой-нибудь компании, предоставляющей такие услуги. Он будет идти через обычный OpenVPN шифруясь, но не маскируясь (считаем, что на той территории факт наличия VPN не пытаются вычислять и срубать), таким образом, мы скрываем статичный IP уже нашего VPS, плюс получаем возможность ходить через разные страны. Наш VPS относительно именно VPN будет выступать просто клиентом.
Я буду считать, что у вас настроен VPS по этой статье, но, в принципе, сойдёт любой работающий XRay-конфиг.
Идём на сайт вашего VPN провайдера, логинимся, получаем от них ovpn-файл. Обычно такие файлики дают скачивать, если мы выберем опцию в стиле, что хотим настроить VPN-клиент на роутере, либо на линуксе. Вот, чисто как пример.
Нам потребуется один файлик с одной локацией, через которую будем выходить. Логично взять ту же страну/город, в которой находится ваш VPS, чтобы меньше терять на пинге. Потом можно будет заморочиться с переключением на другие страны, если захотите. Скачиваем нужный ovpn-файл. Если скачали на свою машину, на VPS можно перекинуть по SSH (с винды см. Передача файлов с Windows на Linux Ubuntu по SSH).
Далее все инструкции на VPS.
Ставим OpenVPN:
Переименовываем ovpn-файл в client.conf и переносим его в папку /etc/openvpn/
Открываем полученный файл на редактирование:
Находим там строчку
и меняем её на
Создаём файл
В нём записываем две строчки:
Это те логин и пароль, с которыми вы подсоединяетесь к VPN. Защитим их уровнем доступа:
Дальше снова открываем на редактирование файл
и дописываем в нём в конце файла такие строчки:
Создаём теперь вышеупомянутый скрипт
В нём:
Мы получим два правила, которые касаются пакетов, маркированных двойкой, при этом их порядок будет такой, что сначала пакет полетит на впн, а если не получится (впн будет выключен), то пакет не пойдёт никуда. Если отбрасывание не написать, то мы при отсутствии впн будем ходить напрямую с VPS.
Даём скрипту права на выполнение:
Теперь залезаем в конфиг xray:
И у
outbounds
меняемfreedom
с такого:на такой:
Т.е. все исходящие из xray пакеты, которые летят напрямую к сайтам (freedom), будут средствами XRay помечаться как 2, роутингом все пакеты с меткой 2 будут заворачиваться в таблицу 200, а она будет лететь через VPN.
Теперь осталось только запустить клиент OpenVPN как демона:
Раскаменчиваем # у строчки
Дальше регаем демона:
Перегружаем демоны:
Стартуем OpenVPN:
И перегружаем xray:
Разумеется, XRay можно настроить и получше, создав себе несколько пользователей, часть из которых будет ходить через VPN (помечая пакеты), а часть напрямую с VPS.
Сам я не настоящий линукс-пользователь, если кто предложит, как это сделать получше, буду только рад.
Ориентировался на эти инструкции:
Как настроить OpenVPN Client на Ubuntu. С этой статьи можно начать, чтобы проверить, что ваше клиентское OpenVPN-соединение вообще ходит нормально (до демонизации, роутинга и связи с XRay).
OpenVPN на роутере для перенаправления только определённых соединений.
Autostart OpenVPN in systemd (Ubuntu).
XRay StreamSettingsObject
Я согласен с посылом статьи, что типы-обёртки — это классно. Но про
VerifiedEmailAddress
, который наследуетEmailAddress
, я вообще не понял. Какого типа будет полеemail
у классаUser
-то?Если
VerifiedEmailAddress
, то что если он ещё неVerified
?Если
EmailAddress
, то при использовании всё равно нужночто по сути то же самое, что и
Если два поля, то это вообще жесть, да и всё равно вылезает что-то типа
И у демона (в xray.service) ещё нужно выставить в блоке
[Service]
для уровня warning, например. Иначе каждое соединение будет в логе.
Судя по всему, предложенное решение сочетает в себе минусы и от retval в стиле Си, и от плюсовых исключений: и (сравнительно) медленное, и может легко быть проигнорировано. Опять же, если исключение должно лететь уровней на пять вверх, весь код там превратится в лапшу из if'ов и переупаковывания Expected'ов.
А как я могу не выбрать ипотеку сам, но при этом её получить?
А если так оно и было? Может коллега Джерри реально косячил со своей частью кода. Или это был Джерри из бизнеса, который развернул требования на 180 градусов незадолго до концов срока. ИМХО ничем не лучше как брать всю вину на себя и рассказывать на собеседовании, как здорово ты всё портил, так и рассказывать, что всё было идеально и ни с какими проблемами не сталкивался.
И с виду написано оно очень понятно и здорово, не нужно быть на 100% в теме всех тонкостей.
Во всём этом для меня лично особенно круто то, что для доказательства неразрешимости 10 проблемы Гильберта был проложен мост из математики в информатику, чтобы свести проблему в итоге к проблеме остановки. А ещё, имхо, нам очень повезло, что автор разговаривает на одном с нами языке, т.к. мы можем свободно послушать его лекции об этом всём на ютубе в оригинале.
Не, ну это бред. Для этого должна быть определённая уязвимость нефильтрации входных данных, чтобы можно было выполнить произвольный код, да плюс ещё опционально уязвимость повышения прав в системе, чтобы «покинуть пределы приложения». А то эдак мы все уязвимы потому и только потому что браузер может в http-протокол.
Проблема отсутствия шифрования в том, что передаваемые данные могут быть кем-угодно прочитаны и переписаны. Т.е. если реквизиты банковской карты передаются, можно украсть деньги с этой карты, а если местоположение, то можно перенаправить такси на другой конец города. Но «овладевание» устройством — это вообще не про то.
В именно такой ситуации, как была описана, можно просто соврать, что на предыдущей работе у вас были один/несколько из проектов на шарпе, и опыт есть. Хуже от этого никому не станет:
Дело в том, что конкретный элемент может иметь только одно из двух отношений к конкретному множеству: либо присутствовать в нём, либо нет. Соответственно, либо в этом множестве есть пятёрка, либо пятёрки нет. Нескольких «одинаковых» элементов не бывает.
Такая задача, возможно, вызовет интерес у любителей задачек изначально. Может быть она чуть-чуть заинтересует тех, кто любит шахматы или просто имеет иррациональную страсть к закономерностям на кнопочных телефонах.
Но сторонников «математика не нужна» она лишний раз убедит, что математики варятся в своих абстрактных задачах ради самих задач, в абсолютном отрыве от реальности. И что все эти вектора и матрицы нужны для обсчёта бесконечных ходов сферических коней по шахматным телефонам, а не для «настоящих» задач.
ИМХО чтобы человек заинтересовался математикой, нужно показать, как математика поможет решить лично его проблему. Например, для меня (учился в классе 7 в это время) это была проблема такого плана: как заставить в моём прототипе недоигры на VBA бегать объект по окружности. Тригонометрические функции тогда стали для меня «магией», которая позволила «открыть глаза» и отбросить стереотипы о «ненужных знаниях после арифметики». И чем дальше, тем больше задач, о которые я безуспешно бился лбом, внезапно оказывались решены в сильно более общем случае три века назад именно в математике.
Собственно, «отбитость» моей задачи беганья по кругу для других людей может быть такого же уровня, как и задача из поста. Чтобы привлечь человека математикой, нужно показать ему решение той задачи, которая интересует лично его.
моё_хобби_экстраполировать.жпг
не является бесполезным/вредным? Скотт Майерс в «Эффективный и современный С++. 42 рекомендации по использованию C++11 и C++14» писал, что в лучшем случае компилятор поймёт нас, хотя не обязан, а в худшем мы сломаем RVO/NRVO. Или в 17 стандарте что-то с тех пор кардинально поменялось?
А может так человек пар выпускает в интернете, после чего как раз ему неинтересно нести эти темы в рабочий коллектив. ИМХО вообще не показатель.
Такой режим для меня — это прямо насилие над собой. Если я не хочу спать в определённое время, то я, скорее всего, и не усну. Буду ворочаться, перекладывать нагретую подушку, крутить в голове какие-то тупые мысли. Бесполезная и неприятная трата времени. Лучше уж поделать что-нибудь, а лечь тогда, когда организм решит, что ему это нужно. Конечно, таким образом можно просидеть всю ночь, а утром на работу — но это ничего. Это значит, что организм получит свой недосып, а на следующий день уже сам скорректирует своё хотение спать.
Но, конечно, оно у всех по-своему.
Интересно, насколько сильно машинное обучение в этом случае справится лучше, чем цепи Маркова, например.
Когда-то задался для себя этой целью и нашёл программу HIDMacros. Она как раз отлично справлялась с двумя клавами: на одной можно было поставить шорткаты на клавиши так, что те теряли изначальное предназначение, при этом на другой у клавиш оставался прежний смысл. Даже пользовался какое-то время так двумя клавиатурами, но потом надоело.
Есть, правда, ложка дёгтя: программа больше не развивается автором, а на новых осях уже не работает (личный опыт: на WinXP x86 работала, на Win7 x64 уже нет). Хотя вместо неё автор мутит LuaMacros. Но ей лично я не пользовался, поэтому ничего уже сказать не могу.
Вот хотел ещё уточнить, может быть кто-нибудь из присутствующих подскажет. Я так понимаю, что если код не компилируется, то это значит, что он является ill-formed. Однако обратное неверно: код может скомпилироваться, но всё равно являться ill-formed, например, если в коде нарушено ODR. Так ли это? Нет ли ещё каких-нибудь вариантов компилирующегося кода, который при этом будет ill-formed?
И ещё такой вопрос по поводу успешности компиляции: а не может ли UB всё-таки вызвать ошибку компиляции (просто как возможность, не обязательно даже стабильное повторение)? Оно же всё-таки U. Может при развёртывании каких-нибудь шаблонов или макросов, например?
Хочется для себя по полочкам разложить, как эти все круги диаграммы Венна пересекаются, и что есть их пересечения: Implementation-defined behavior, Unspecified behavior, Undefined behavior, ill-formed, некомпилирующийся код.