Простая инструкция по установке Tinyproxy

Небольшое введение

Tinyproxy это такой маленький http/https прокси-сервер, на мой взгляд, очень простой в использовании и конфигурировании, вполне подходящий для несложных задач пропускания http(s) трафика. Например в офисе или дома. Лично я использую его, чтоб можно было посещать статистику и личный кабинет собственного провайдера в обход VPN.

Конфигурация network namespace.

Если у вас есть специальный network namespace для прокси, перед установкой сервера настраиваем его (добавляем нужные файлы hosts и resolv.conf, как это описано здесь Копия)

Рестартируем систему (или сетевой менеджер/демон, тут уж зависит от вашей ОС).

Устанавливаем tinyproxy

Для Sclackware можно скачать пакет с исходниками с помощью sbopkg, взять готовый и откомпилированный здесь (Для Slackware 12-14.2), или собрать из исходников на GitHub и готовый пакет установить с помощью installpkg.

Создаем пользователя и группу

1. Создаем группу для proxy-сервера, например proxy:

groupadd proxy

2. Создаем отдельного пользователя для запуска прокси-сервера:
Можно сделать это с помощью скрипта-обертки adduser над программой useradd.
— На первый вопрос вводим имя пользователя, например, provproxy.
— Далее пропускаем (нажимаем enter)
— В ответ на initial group, вводим имя ранее созданной группы для прокси-сервера, в данном случае proxy (в вашем — ту группу, которую создали вы).
— Далее, на вопрос о дополнительных группах, нельзя устанавливать что-либо, нажимаем Enter
— Home directory нужна, там будет лежать PID-файл, логи (если нужно) и конфигурационный файл. По умолчанию директория совпадает с именем пользователя и располагается в подкаталоге /home.
— Shell должна быть установлена строго в /bin/false, поскольку это не интерактивный пользователь. Если скрипт ответил вам: - Warning: /bin/false is not in /etc/shells (potential problem using FTP)
Do you wish to change the shell ? (Y/n)

То отвечаем n, а потом в /etc/shells добавляем строчку
/bin/false
— Expiry date пропускаем (Enter)
— Далее пропускаем всю User Information
— На вопрос о пароле придумываем что-нибудь чтоб прошло.
Далее правим /etc/shadow, находим строчку с именем пользователя и удаляем все, что между первым и вторым двоеточием. Было:
provproxy:$5$S8/tp/ap2wF/K$qaYnfHuR8opsWO0WwTaXCjiHjmge7mWuH5WwEd5Kn70:17888:0:99
Стало: provproxy::17888:0:99
Права на каталог надо установить в 700 (полный доступ для пользователя provproxy):
chmod 700 /home/provproxy

Можно не пользоваться интерактивным скриптом, а сделать все с помощью базовых команд:
1. Добавить пользователя
useradd -g proxy -d /home/provproxy -s /bin/false provproxy

где:
-g proxy группа пользователя (ранее созданная proxy)
-d /home/provproxy домашний каталог пользователя
-s /bin/false — оболочка для пользователя. Обычно здесь прописывается /bin/sh, /bin/bash для интерактивных пользователей, или /bin/false для неинтерактивных, что нам и надо в данном случае.
Строчка /bin/false должна быть в файле /etc/shells — если ее нет, дописать.

2. Создаем домашний каталог:
mkdir /home/provproxy
3. Меняем владельца каталога на пользователя provproxy
chown provproxy:proxy /home/provproxy
4. Меняем права доступа на каталог:
chmod 700 /home/provproxy

Инициализационный скрипт tinyproxy

Был подробно описан в этой заметке: Запускающий скрипт для tinyproxy Копия

Сам скрипт:
— На PasteBin
На GitHub
Скачать с Mega.nz

Поскольку сам инициализационный скрипт описан довольно полно, то я остановлюсь лишь на двух важных моментах.

PID-файл: в скрипте необходимо правильно указать путь к PID-файлу, но об этом поговорим ниже. У меня PID-файл создается в домашнем каталоге пользователя provproxy. Местоположение PID-файла задается в этой строке скрипта. Если надо, не забудьте исправить на свое значение:

PIDFILE="/home/provproxy/tinyproxy.pid"

Команда запуска прокси-сервера:
По умолчанию там просто указан путь к исполняемому файлу tinyproxy:

TINYPROXYCMD="/usr/sbin/tinyproxy"

Но я хочу эту команду немного подправить.

Запуск сервера при старте системы.

При старте системы все обычно запускается от root‘а, а нам не надо совершенно, чтоб под root‘ом крутились всякие там сервера. Не зря же мы отдельного пользователя делали. Дополняем команду:

TINYPROXYCMD="sudo -u provproxy /usr/sbin/tinyproxy"

В таком виде, скрипт, запускаемый при старте из-под root‘а вызовет tinyproxy от имени нужного нам пользователя. Справедливости ради, надо заметить, что tinyproxy, как любой уважающий себя сервер, умеет сам себе понижать права до определенного пользователя, указанного в файле конфигурации. Но на этом остановимся ниже. На мой взгляд, одно другому не мешает, зато так виднее и жестко задано, от какого пользователя стартовать.

Альтернативный файл конфигурации.

По умолчанию tinyproxy ищет свой файл конфигурации в /etc/tinyproxy.conf, но можно задать альтернативный, в домашнем каталоге пользователя. Делается это путем добавления ключа и пути к файлу. Объединю этот вариант с предыдущим:

TINYPROXYCMD="sudo -u provproxy /usr/sbin/tinyproxy -c /home/provproxy/tinyproxy.conf"

Альтернативный конфигурационный файл в домашнем каталоге.

Раз уж началось с альтернативного файла конфигурации, так давайте его сделаем (от root). Копируем файл /etc/tinyproxy.conf в /home/provproxy/tinyproxy.conf

cp /etc/tinyproxy.conf /home/provproxy/tinyproxy.conf

Далее устанавливаем ему владельца (можно перейти в директорию /home/provproxy перед этим, я перешел — пути будут неполные):

chown provproxy:proxy tinyproxy.conf

И права — пользователю provproxy на tinyproxy.conf нужны права только на чтение, ничего он не пишет в конфигурационный файл, и тем более не пытается исполнить.

chmod 400 tinyproxy.conf

Конфигурирование.

Открываем файл от root‘а и настраиваем параметры прокси-сервера.

Подробно описывается конфингурационный файл

Проверка

Прописываем нужный адрес прокси в браузере:

Проверяем соединение:

Вот тут не показывается, что используется прокси, потому что прокси настроен верно — с отключением via и других заголовков, передающих IP-адрес.

Источники

Tinyproxy, краткая инструкция

Скрипт для автоматического обновления паролей с vpnbook.com не работает.

Старый скрипт для автоматического обновления паролей с бесплатного VPN-сервиса vpnbook.com более не работает. Они весь сайт таки зажабаскриптили и пароль теперь отображается в виде картинки. Но поскольку пока у меня есть хорошие анархисты, милые, предоставляющие доступ к своему сервису нахаляву, я перестал пользоваться vpnbook, и расковыривать этот пиздец мне влом. Расковыряю, конечно, но потом, не сейчас.
И я даже знаю, как это сделать.

Отложенная автозагрузка.

Или автозагрузка нужных программ с подключаемых дисков, внешних носителей и сетевых шар.

Возникла тут производственная задача. Некоторые программы, необходимые для работы, находятся на сетевых шарах (либо подключаемых/шифрованных контейнерах), однако, после загрузки рабочей ОС, они должны автоматически запускаться у пользователя. Для примера, на работе это была программа управления станком.

Решая задачу, перелопатил гору литературы, но ничего готового не нашел. В результате написал свой «Менеджер отложенной автозагрузки».

Принцип работы простой, пользователь в этом самом «Менеджере» указывает путь до нужной программы, лежащей, например, на сетевом диске. «Менеджер» установлен на разделе с ОС, и запускается при ее загрузке. При запуске он проверяет через заданный интервал времени, появился ли нужный «экзешник». Если появился — запускает.

По умолчанию программа работает в портативном режиме (т.е. все настройки и список запускаемых программ, хранятся в директории с программой). Запуск без параметров открывает окно настройки, где можно добавить нужные для запуска задачи, а также в отдельном меню установить время проверки доступности задач, прочие параметры и добавить сам менеджер в автозагрузку ОС. Понятно, что менеджер должен находиться на разделе жесткого диска, который доступен ОС сразу после загрузки.

В качестве запускаемой задачи можно указать не исполняемый файл (exe, com, bat, cmd), но и документ, тогда он откроется в ассоциированной с ним программе.

Для исполнения задач, необходимо запустить менеджер с параметром командной строки /run

Скриншоты


Основное окно настроек

Опции «Менеджера отложенной автозагрузки»

Окно добавления/редактирования задачи

Cправка по параметрам командной строки

StartupDelayed /help
StartupDelayed [/run] [/d|confdir <путь>]
/help
— эта справка
/run — выполнение задач
/d — запускать в «не-портативном режиме» (конфигурационные файлы в директории %LocalApplicationsData%\StartupDelayed)
/confdir <путь> — указать путь к директории с файлами конфигурации

По умолчанию программа будет запущена в режиме конфигурации, и будет искать конфигурационные файлы в директории со своим исполняемым файлом.

Скачать

Инсталлятор (не портативная версия)
Портативная версия
Исходники на GitHub

DetecTOR v 0.3.0b.

Обновлена утилита DetecTOR, которая определяла, присутствует ли определенный IP в сети Tor.

По многочисленным просьбам зрителей добавлен:

— модуль SxGeoSharp, теперь, даже если IP отсутствует в сети Tor, программа возьмет информацию из базы SxGeo (если вы ее скачаете и подгрузите, она бесплатная), и выдаст вам страну (+город и регион, если есть) для конкретного IP-адреса.
— по умолчанию включен портабельный режим, все настройки программы хранятся в подкаталогах с исполняемым файлом.
— режим пакетной обработки. Если у вас есть огромный лог или просто список IPv4 адресов, (тестировалось на 1000 IP-адресов в специально нагенерированном текстовом файле, где IP были расположены в случайном порядке), то программа найдет все адреса, проверит их по БД SxGeo и БД адресов Tor и выдаст результат в виде файла CSV. Можно включить или отключить выдачу в отчет дополнительных данных Tor.
— добавлены дополнительные аргументы командной строки (см. readme.txt).
— проверено замечание пользователя [info]paperdaemon@ljr. Данная ошибка при работе в Windows 7 и более ранних версиях так и не была выявлена.

readme.txt

Основная статья о DetecTOR Копия
Скачать (портативная версия)
Исходники

C#, DataSet, пользовательские типы данных, и хинтик при использовании Dataset Designer.

Известно, что DataSet может хранить пользовательские типы данных в таблицах. Для нетипизированного DataSet, т.е. экземпляра класса DataSet, достаточно, чтобы нужные типы данных были видны из того места кода, в котором будем проводить операции с DataSet. Например, сделаем тестовый enum:

public enum testenum
{
     val0=0,
     val1=1
}

и подключим какое-нибудь дополнительное пространство имен, например:

using System.Diagnostics;

Теперь, в таблицу DataSet можно добавить поля типов testenum и, например, ProcessWindowStyle (из System.Diagnostics)

//...
DataSet dsTest = new DataSet();
//...
dsTest.Tables.Add("Test");
dsTest.Tables["Test"].Columns.Add("Text", typeof(string));
dsTest.Tables["Test"].Columns.Add("Enum", typeof(testenum));
dsTest.Tables["Test"].Columns.Add("Enum2", typeof(ProcessWindowStyle));

Код на PasteBin

Если же делать типизированный DataSet, т.е. добавить в проект DataSet, как отдельный класс (наследник обычного DataSet), и создать нужные таблицы в конструкторе (Dataset Designer), то при попытке просто прописать пользовательский тип DataType в конструкторе, получится ошибка:

На самом деле, имена типов данных нужно вводить полностью, вместе с их пространствами имен. Т.е., при условии, что пространство имен программы, например tmpDataSet, то тип testenum нужно указывать как tmpDataSet.testenum (а тип ProcessWindowStyle, соответственно, как System.Diagnostics.ProcessWindowStyle)


Вещь, вроде бы довольно очевидная, если приглядеться (стандартные типы из списка прописываются точно также):

Но почему-то прямо нигде не озвученная, что странно.

C#, Регулярное выражение для IP-адреса (v4)

Искать айпишники, например, в логах.
Для десятичной (полной) записи:

(25[0-5]|2[0-4]\d|[01]?\d\d?)(\.(25[0-5]|2[0-4]\d|[01]?\d\d?)){3}

Второе, должно поддерживать восьмеричную, шестнадцатеричную, десятичную и смешанную запись:

(0[0-7]{10,11}|0(x|X)[0-9a-fA-F]{8}|(\b4\d{8}[0-5]\b|\b[1-3]?\d{8}\d?\b)|((2[0-5][0-5]|1\d{2}|[1-9]\d?)|(0(x|X)[0-9a-fA-F]{2})|(0[0-7]{3}))(\.((2[0-5][0-5]|1\d{2}|\d\d?)|(0(x|X)[0-9a-fA-F]{2})|(0[0-7]{3}))){3})

Второй мопед не мой, оставляю на всякий случай, чтоб два раза не вставать.

Протестировать можно здесь
Ну и тесты на C# (от Лехи)

Element PNK-000 Конь-пилятор с бензопилой


Автор [info]rex_weblen@ljr

Он, кстати, еще переводит милый комикс Forest Hill, единственный, кстати, в рунете переводит, и поэтому не пропиарить просто не могу. А мне вот такого элемента (см. «Межлокальную контрабанду») сделал, по моему межлокальному эсхатологическому мутанту. За что ему почет и уважение. И знал бы он какую бурю породил в местном сообществе… Теперь у меня стадо коней-пиляторов, только отсканировать всех надо, рано или поздно покажу.

C#, Об анализе exceptions при вызове внешнего процесса.

Или отлавливаем нажатие клавиши «Отмена» в окне запроса UAC.

Вот однажды я писал небольшую утилиту, которая запускает любое приложение или командный файл (bat/cmd) от имени администратора. И мне в комментариях правильно намекнули, что я слишком грубо обрабатываю exceptions, которые могут случиться во время запуска внешнего процесса. Но вообще это хороший пример не только для конкретного случая, но и для подхода к обработке ошибок вообще. Кратко говоря — если вы предполагаете, что где-то может возникнуть ошибка, то есть два метода:
1. Предотвратить и обезвредить. К таким ошибкам, например, относится возможная недоступность файла для чтения/записи, или вообще его отсутствие, когда он нужен. Тогда лучше проверить, например, наличие файла, с помощью File.Exist() перед операцией с файлом.
2. Отловить на этапе времени выполнения. Для этого в C# существуют try/catch.

Нам нужен именно способ #2, поскольку мы не знаем и проверить заранее никак не можем, нажмет пользователь «Отмену» в окне запроса, или нет.

Изначально было сделано так, т.е. тут мы полагались на какой-то внутренний флаг, и от его состояния принимали решение, реагировать на ошибку или нет.

3. Но на самом деле нам нужно отследить конкретную ошибку, для соответствующей нашему случаю реакции на нее, а изначально, мы этого не сделали, полагаясь на авось (внутренний флаг).

Немного теории об exceptions при запуске внешних процессов.

Как известно, в .NET ошибки времени выполнения распределены по классам. Есть общий класс — Exception, в который попадают все ошибки времени выполнения, и есть конкретные классы для обработки определенных ошибок. Иерархия обработки следующая: «от конкретных к общему». Т.е. сначала (если мы хотим их обработать), указываются конкретные ошибки, а потом можно, но не обязательно указать общий обработчик.
Конкретно при запуске внешних процессов могут возникнуть следующие виды ошибок:
ArgumentNullException
ObjectDisposedException
FileNotFoundException
(на самом деле в зависимости от OS но может не сработать, сработает следующий)
Win32Exception
он нам и нужен
PlatformNotSupportedException

На самом деле, практически всегда срабатывает класс ошибок Win32Exception, остальные или очень редки, или их можно охарактеризовать одним словом — случился ой, дальше работать не будем.

Анализ Win32Exception

Для начала подключим нужный namespace:
using System.ComponentModel;

А теперь примемся за анализ. На самом деле, у каждой Win32-ошибки имеется внутренний код. В C#-exceptions он сохраняется в переменной NativeErrorCode. Т.е для решения нашей задачи, нам в конструкции try/catch достаточно отловить конкретный код ошибки. Для нажатия клавиши «Отмена» в окне UAC, это будет код 1223, «Операция отменена пользователем».

Исправление.

1. Сначала надо отловить ошибку типа Win32Exception и проанализировать значение NativeErrorCode.
2. Если NativeErrorCode == 1223, то не предпринимаем никаких действий.
3. Если NativeErrorCode другой, оповещаем пользователя об ошибке.
4. Если сработало исключение другого типа (не Win32Exception), то аналогично предыдущему пункту — оповещаем пользователя об ошибке.

//...

try
{
    Process.Start(psi);
}
catch (Win32Exception wex)
{
    if (wex.NativeErrorCode == 1223) //нажали "Отмену" в окне UAC
    {
        return true;
    }
    else //какой-то другой Win32 Error
    {
        ErrorMessage = wex.NativeErrorCode.ToString() + " " + wex.Message;
        return false;
    }
}
catch (Exception ex) //какой-то другой Exception
{
    ErrorMessage = ex.Message;
    return false;
}

//...

Код полностью здесь

Источники

1. Коды ошибок Win32 (Краткое пояснение и полный список кодов, англ., MSDN)
2. Нужный код ошибки (Отменено пользователем)

Утилита wsudo

1. Репозиторий на GitHub
2. Скачать
3. Заметка об утилите Копия

Про недавно разразившийся блокадосрач.

У меня отношение к истории примерно такое же, как у Невзорова, то есть, как к историям — в смысле баек и прочей литературщины. Меня тогда не было, сам не видел, так что именно байки, крипотные или прикольные, это уж в зависимости от содержания баек. Но про блокаду поведаю семейную историю. Какие-то родственники в блокаду попали, не буду говорить какие, да это не особо интересно, как мне, так и читателям.
Но прабабушке от них дошло последнее письмо. Понятно, что письмо наверняка было больше, и мне все это попало через перезказ, но одна фраза из рассказа, до сих пор не отпускает.
«Съели мы своего рыжего поросеночка».
У оставшихся в Ленинграде родственников был рыжий кот.

Пробрало хуже всякой крипоты.

На фильм я, естественно, не пойду (и даже в пиратке смотреть не буду), но другим никогда не буду запрещать . Запрещать запрещено. Если не будет запрещено запрещать, то «смогут повторить», а котов мне жалко.

Завелись попы.

Приснился забавный сон, будто в моей квартире завелись попы, маленькие такие, не больше спички ростом. Ходят крестными ходами (или чем там они должны ходить), реально, организованными кучками. Был даже патриарх, отличался от остальных попов, этой белой своей шапочкой-колпачком с миниатюрным крестиком сверху, как в телевизоре показывают. Ходил, естественно, впереди всех. Попы пели что-то свое церковное, и при этом издавали колокольный звон, причем, колокольни я не видел, то ли они издавали звон сверхъестественными способом, то ли колокольня была где-то заныкана, под тумбочку, например, или в стенной шкаф. Меня почему-то это умиляло, особенно звон и песнопения, да и просто было забавно. Я еще думал, что вот, травил клопов, а вместо клопов завелись попы.
Потом пришел участковый, стал ругаться, мол жалобы от соседей поступают на шум.
Я ему показал попов, сказал, что-то типа «Ну вот, завелись, сам не знаю что делать». Участковый как-то завис, причем завис именно как видео при плохой связи, судорожно подергиваясь и заикаясь, вроде даже квадратиками пошел.
А потом был уже другой сон, но не интересный, вроде про каких-то шпионов.

Психоделические графики (DOS, Turbo Pascal)

Наконец нашел дико красивые графики, которые наш товарищ рисовал в Turbo Pascal под DOS. Ни я, ни товарищ алгоритма не помним, помним только то, что в качестве входных данных была матрица 3×3. Писалось это в качестве какого-то зачета. Но товарищ, тот еще креатвищик, усовершенствовал формулу и задание, в результате программа рисовала четырехмерные графики. Поскольку четырехмерного монитора у нас не было (хотя была мысль собрать, но что б мы делали со своими трехмерными глазами), четвертое измерение отображалось цветом.
С этими графиками связана забавная история, которая, минимум до 2010 г. будоражила универ. Дело в том, что условное задание «нарисовать в паскале графики», давалось всем. Но по внутриуневеровской сети до сих пор ходит, или ходил, легендарный исходник моего товарища. И его периодически некоторые долбозавры брали, и пытались сдать преподу Б. А препод Б. спрашивал, «объясните, как написали, и что оно делает». И это был провал. Сдающего.

Вообще хочу это соптимизировать и сделать из оригинала заставку, на Юнити, например.

https://youtu.be/qutWWmHYjYc

В оригинале звука не было, и работало оно гораздо медленнее, но может в этом виноват эмулятор DOS, я ускорил видео в 20 раз примерно.

Один из исходников, вроде последняя версия, на PasteBin и пример файла данных к нему
Весь архив с проектом

C#, программное создание ярлыка (shortcut) Windows

И случайно, самое полное описание WshShortcut.

Преамбула

Почему-то, уж не знаю почему, в .NET Framework (во всяком случае до 4 версии, в 4 вроде появился) не было стандартного способа создать ярлык (файл .LNK) программно. Но способы все-таки есть. Расскажу о них, в порядке уменьшения геморройности.

I. Создать ярлык вручную

Самый геморройный способ, для любителей ассемблера и прочего байтокопательства. Файл ярлыка (*.lnk), это обычный бинарный файл. Почему-то в сети бытует мнение, что формат LNK-файлов закрыт, и чуть ли не засекречен. Однако это не так, спецификация формата вполне себе открыта и лежит на официальном сайте Microsoft. Так что остается осилить 48 страничную спецификацию, и можно приступать. 🙂 Но мы этого делать не будем. Замечу лишь, что в формате файла есть несколько странных моментов. Например, зачем хранить в файле ярлыка серийный номер тома и тип диска (HDD, CD, Floppy) и NetBIOS имя компьютера, я совершенно не понимаю.

II. Обратиться к Windows Script Host через COM-интерфейс

Способ, наиболее часто встречающийся в сети, но почему-то, весьма поверхностно описанный. Windows Script Host — компонент Microsoft Windows, предназначенный для запуска сценариев на скриптовых языках JScript и VBScript, а также и на других дополнительно устанавливаемых языках (например, Perl).

Остановлюсь поподробнее на некоторых моментах. Сначала самое основное.
В References проекта надо добавить соответствующий компонент (щелкнуть по References правой кнопкой мыши, выбрать Add Reference…) В появившемся окне выбираем вкладку COM и находим компонент Windows Script Host Object Model.

Из-за того, что мы используем COM-интерфейс, с нашей программой придется таскать библиотеку для взаимодействия с ним Interop.IWshRuntimeLibrary.dll (ее нам без нашего участия сделает компилятор .NET).
Теперь указываем соответствующую директиву using:

using IWshRuntimeLibrary;

Создаем объект WSH Shell:

WshShell wshShell = new WshShell(); //создаем объект wsh shell
На самом деле у объекта WshShell довольно много интересных возможностей, например выполнять VBS или JS сценарии прямо из кода C#, со всеми возможностями Windows Scripting Host, естественно. Но это так, к слову. Мы же создадим объект для управления ярлыком:

IWshShortcut Shortcut = (IWshShortcut)wshShell.
CreateShortcut(ShortcutPath);

где ShortcutPath — строковая переменная, в которую записан путь к файлу создаваемого ярлыка.

В самом простейшем случае, надо задать имя файла для которого создается ярлык:

Shortcut.TargetPath = @"C:\Windows\notepad.exe"; //путь к целевому файлу

Если дополнительные параметры не заданы, то:
— в качестве иконки ярлыка будет установлена иконка по умолчанию (для EXE — его иконка, для остальных — стандартные системные иконки)
— в качестве рабочего каталога — каталог, в котором расположен целевой файл (тут C:\Windows\).
— размер окна — нормальный.

Теперь нужно сохранить ярлык:
Shortcut.Save();

Пример кода целиком на PasteBin

Теперь о дополнительных параметрах, которым особо никто внимания не уделяет, а там скрыто несколько мелких гадостей и глюков.

Пример кода функции, задающей дополнительные параметры ярлыка на PasteBin

Остальные параметры под катом

Горячая клавиша:
Задается параметром string Shortcut.Hotkey
Внимание! Если переменной попытаться установить значение null, произойдет ошибка нехватки памяти (OutOfMemoryException). Любая строка не подпадающая под формат, вызывает ArgumentException "Значение не попадает в ожидаемый диапазон."

Строка должна быть следующего вида: "Ctrl+Alt+N", т.е. содержать названия клавиш-модификаторов, символьную или функциональную клавишу, названия должны быть разделены знаком + без пробелов. Названия регистронезависимы.
Чтобы хоткей сработал, ярлык надо создавать или в меню Пуск, или на Рабочем столе. Почему-то если создать ярлык где-то еще, а потом скопировать в Пуск или на Рабочий стол, хоткей не работает (хотя, если менять горячую клавишу у уже созданного ярлыка, через свойства ярлыка, то все работает). Установленный хоткей становится глобальным для всей системы, т.е. если "Ctrl+Alt+N" обрабатывается в какой-то программе, то после создания ярлыка, сочетание клавиш будет перехвачено Windows, и запустится то, на что указывает ярлык.
Список возможных клавиш:
Модификаторы: CTRL+ ALT+ SHIFT+ (и еще какой-то EXT+ встречается в [1])
Алфавитно-цифровые, функциональные и прочие:
F1-F12, 0-9, A-Z
ESC, ENTER, TAB, SPACE, PRINT SCREEN
(указывается как SNAPSHOT), BACKSPACE [1] (причем обычным способом через проводник установить их нельзя, и нет, Ctrl+Alt+Del так не перехватить, хотя создать такой хоткей можно).
Полный список клавиш можно посмотреть в WINUSER.H или в [2], имена берутся без VK_, и не получится в качестве третьей клавиши использовать имена модификаторов и мышиных кнопок, ярлык создастся без ошибок, а вот работать не будет.

Забавный баг

Через свойства ярлыка нельзя задать горячую клавишу БЕЗ модификаторов. Windows заботливо будет нам подставлять CTRL+ALT+, а вот с помощью WshShortcut — можно, т.е. если значение Hotkey установить, например в «F1" и создать ярлык на Рабочем столе, то по нажатию F1 будет вызываться, например, Блокнот. На практике это использовать, конечно, никак нельзя, разве что над кем-нибудь подшутить.

Демо и класс-обертка над IWshShortcut на GitHub

III. Создание ярлыка через Windows API.

Вообще, этот способ по геморройности надо было бы ставить на второе место, чего одна статья [3], описывающая все API, стоит. Но авторы статьи, крутые акулы программирования, для нас постарались и таки сделали классы для работы с ярлыками, причем сделали великолепно! С помощью их класса ShellLink можно не только создавать новые ярлыки, но и читать/редактировать существующие.
ShellLink вместе с демо можно скачать с mega.nz или с моего репозитория на GitHub, не знаю, будут ли проблемы с лицензией, но на vbaccelerator.com вроде Creative Commons.
С официального сайта почему-то сей полезный горшочек пропал, хотя статья осталась. Видать авторы забили на проект и что-то протухло.
Повторюсь, класс написан хорошо, ничего не падает и с ошибками не вылетает. Единственное, что криво, это установка хоткея. Ну да и черт с ним, мне особо не нужно было, так что ковыряться и исправлять не стал.
Написано сие дело аж в 2003 г., но прекрасно работает до сих пор, на Windows 7 в т.ч.

Для подключения к своему проекту из оригинального архива понадобятся два класса (файлы ShellLink.cs и FileIcon.cs), далее подключаем соответствующий namespace (using vbAccelerator.Components.Shell;) и можно использовать. Пример кода:

ShellLink shortcut = new ShellLink();
shortcut.ShortCutFile = @"C:\Temp\shortcut\test.lnk";
shortcut.Target = @"C:\Windows\notepad.exe";
shortcut.WorkingDirectory = @"C:\";
shortcut.IconPath = @"C:\Windows\System32\shell32.dll";
shortcut.IconIndex=111;
shortcut.Description = "Тестовый ярлык";
shortcut.Arguments = "file.txt";
shortcut.DisplayMode = ShellLink.LinkDisplayMode.edmMaximized;
shortcut.Save();

Источники

1. WshShortcut.Hotkey Копия
2. Virtual-Key Codes Копия
3. Creating and Modifying Shortcuts (ShellLink, WebArchive) Копия
4. Создание ярлыков с помощью Windows Script Host
5. Спецификация формата файлов LNK Копия

Исходный код

1. ShellLink от vbaccelerator. Скачать с Mega.NZ. На GitHub
2. Демо и класс-обертка над IWshShortcut на GitHub

Сетевые namespace’ы Linux, отдельные конфигурации для каждого namespace.

Это заметка от моего собственного склероза, потому что мелочи иногда забываю.
Для общей информации, что такое этот самый сетевой неймспейс. Это такая хитрая фиговина в ядре Linux, которая позволяет на одной машине с одной сетевой картой соединяться с сетью, будто у вас вагон и маленькая тележка этих сетевых карт (соответственно, куча локальных IP), можно, например, на одном неймспейсе поднять VPN до одного провайдера, на втором — до второго, на третьем — коннектиться к основному, и т.д.

Network namespace — это логически отделенный от других стек сетевых протоколов в Linux. Такая себе контейнерная виртуализация для сетевых интервейсов, когда chroot LXC и нужна виртуализация только сетевых интерфейсов. Эмулируется полностью сетевой стек: сетевые интерфейсы, таблица маршрутизации, файрволл и т.д. Так, как это работает на уровне ядра и для определенных процессов, то вполне можно получить рабочую конфигурации, когда на одной машине есть несколько сетевых интерфейсов с одинаковыми IP-адресами и ничто не конфликтует.
Хочу по этим штуковинам написать большой материал, как мы их у себя сконфигурировали и развели с одного сервера целый пул доступа к разным VPN-провайдерам, но руки не доходят. Поэтому да, заметка от склероза.

Каждому из нэймспейсов можно подсунуть свою конфигурацию сети, свои конфигурационные файлы (resolv.conf, hosts)

Для этого достаточно положить соответствующие файлы в директорию /etc/netns/имя_namespace, например, для гипотетического namespace с именем riseupvpnns это будет каталог /etc/netns/riseupvpnns, туда можно положить, например, resolv.conf, прописать необходимые DNS, и эта конфигурация будет влиять только на данный namespace, в независимости, что там в основной системе прописано.

C# Получение пути к папке ОС Windows

Оказывается, вплоть до версии .NET 4 в перечислении Environment.SpecialFolder нет пути к папке, куда установлена Windows (обычно C:\Windows). Эту досадную оплошность можно обойти двумя способами:
1. Посмотреть в переменную окружения SystemRoot или windir:
string windir=Environment.GetEnvironmentVariable("SystemRoot");
string windir=Environment.GetEnvironmentVariable("windir");

2. ВНЕЗАПНО, бывают хитрые самосборные или специальные дистрибутивы, где данных переменных окружения нет. Тогда:
— надо взять путь к директории system, (обычно это C:\Windows\System32), который есть в Environment.SpecialFolder во всех версиях .NET: Environment.SpecialFolder.System
— получить директорию выше уровнем:

string windir = System.IO.Directory.GetParent(
        Environment.GetFolderPath(Environment.SpecialFolder.System));