• Как сохранить IP-адрес клиента при подключении по OpenVPN?

    @WhiteNinja Автор вопроса
    Спасибо!

    Я на сервере убрал вот эту настройку

    push "redirect-gateway def1 bypass-dhcp"

    И вроде всё заработало. IP-адрес на клиенте так и остался как был до соединения.
    Написано
  • Как правильно открыть доступ к ресурсам в локальной сети пользователям через VPN?

    @WhiteNinja Автор вопроса
    Valentin Barbolin,
    К сожалению у меня так и не получилось с командой route XXX.XXX.XXX.XXX 255.255.255.255 vpn_gateway.

    Возможно это связано с тем, что важен порядок и я не в то место вставляю эту строку (хотя я пробовал по разному), вот такой конфиг server.conf получается:

    port 1194
    proto udp
    dev tun
    user nobody
    group nogroup
    persist-key
    persist-tun
    keepalive 10 120
    topology subnet
    server 10.8.0.0 255.255.255.0
    ifconfig-pool-persist ipp.txt
    push "dhcp-option DNS 8.8.8.8"
    push "dhcp-option DNS 8.8.4.4"
    push "redirect-gateway def1 bypass-dhcp"
    push "route XXX.XXX.XXX.XXX 255.255.255.0 vpn_gateway"
    dh none
    ...


    Где XXX.XXX.XXX.XXX = публичный IP-адрес сервера, где стоит VPN-server и GitLab.

    Пока я в DNS в A записи в качестве IP указал локальный 10.8.0.1 и тогда конечно всё заработало.
    Насколько считается antibest practice использование приватных адресов в публичных DNS -серверах?
    Написано
  • Как правильно открыть доступ к ресурсам в локальной сети пользователям через VPN?

    @WhiteNinja Автор вопроса
    AlexVWill,
    Спасибо!

    1-ый пункт я так и сделал, а вот 2-ой нет. Попробую настроить доступ к интрасети не через Apache, а через Nginx! Огромное спасибо за ссылку!!
    Написано
  • Как правильно открыть доступ к ресурсам в локальной сети пользователям через VPN?

    @WhiteNinja Автор вопроса
    Valentin Barbolin,

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


    Понял, спасибо!

    Ты хочешь заходить на сервер по DNS имени git.example.ru. На каком DNS сервере клиент должен отрезолвить (превратить git.example.ru в IP) это имя?


    На reg.ru в разделе "Управление зоной" я добавил A запись git.example.ru с IP-адресом того-же Linux-сервера, на котором пытаюсь настроить этот VPN-сервер. Отвечая на вопрос - получается на DNS-сервере reg.ru. Но сделал я это по привычке, как для публичного доступа, т.е. если бы на git.example.ru можно было бы зайти на прямую. Возможно для приватного варианта нужно как-то по другому?

    Подскажите, пожалуйста, правильно я понял, что команда "route XXX.XXX.XXX.XXX 255.255.255.255 vpn_gateway" как раз и прокидывает следующее = git.example.ru =>(через DNS)=> XXX.XXX.XXX.XXX =>(через VPN-сервер)=>vpn_gateway(который будет равен локальному адресу сервера с VPN и гитом соответственно, верно?
    Написано
  • Как правильно открыть доступ к ресурсам в локальной сети пользователям через VPN?

    @WhiteNinja Автор вопроса
    Valentin Barbolin,
    Спасибо!

    git.example.ru - на какой DNS оно резолвиться?


    Сейчас на тот же, где стоит VPN-сервер)

    push "route IP 255.255.255.255 vpn_gateway "


    Изменил server.conf. Сгенерировал новый файл *.ovpn для клиента, но там ничего нового не добавилось(
    Так и должно быть? Файл клиента как-то должен измениться?

    P.S. доступ по git.example.ru при подключении к VPN не заработал(
    Написано
  • Как правильно открыть доступ к ресурсам в локальной сети пользователям через VPN?

    @WhiteNinja Автор вопроса
    Zerg89, Я устанавливал VPN-сервер из скрипта - https://github.com/angristan/openvpn-install

    server.conf в итоге вот так выглядит:

    port 1194
    proto udp
    dev tun
    user nobody
    group nogroup
    persist-key
    persist-tun
    keepalive 10 120
    topology subnet
    server 10.8.0.0 255.255.255.0
    ifconfig-pool-persist ipp.txt
    push "dhcp-option DNS 8.8.8.8"
    push "dhcp-option DNS 8.8.4.4"
    push "redirect-gateway def1 bypass-dhcp"
    push "route git.example.ru 255.255.255.0 vpn_gateway"
    dh none
    ....


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

    client
    proto udp
    explicit-exit-notify
    remote XXX.XXX.XXX.XXX 1194
    dev tun
    resolv-retry infinite
    nobind
    persist-key
    persist-tun
    remote-cert-tls server
    verify-x509-name server_dShSFBpP9wieV5qv name
    auth SHA256
    auth-nocache
    cipher AES-128-GCM
    tls-client
    tls-version-min 1.2
    tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256
    ignore-unknown-option block-outside-dns
    setenv opt block-outside-dns # Prevent Windows 10 DNS leak
    verb 3
    ...


    Получается в конфигурации для клиента должен же появится маршрут?
    Написано
  • Как правильно открыть доступ к ресурсам в локальной сети пользователям через VPN?

    @WhiteNinja Автор вопроса
    Спасибо!

    Добавил строчку в server.conf:
    push "route git.example.ru 255.255.255.0 vpn_gateway "


    После этого перезагрузил VPN-сервер и переподключился как клиент, но по адресу адресу ничего не заработало :(

    Нужны еще какие-нибудь дополнительные действия?
    Написано
  • Как правильно организовать Exception Handling в бизнес-приложении?

    @WhiteNinja Автор вопроса
    Владимир Коротенко, Ок, спасибо! Но Вы прислали пример где именно "Server not awailable now, try later", а вот если на бэкенде было сгенерировано именно исключение для бизнес-правила и клиент должен увидеть у себя в браузере сообщение - "На вашем лицевом счете недостаточно средств для выполнения данной операции" - как это реализовывается?

    Например, на бэкенде вызвано исключение throw new InsufficientFundsException(command.UserId), как фронт преобразовывает код 500 (который Вы в итоге выдаете в API) в локализованный текст "На вашем лицевом счете недостаточно средств для выполнения данной операции"?
  • Как правильно организовать Exception Handling в бизнес-приложении?

    @WhiteNinja Автор вопроса
    Владимир Коротенко, А как фротенд узнает, что скрывается за 500 ошибкой? Там же могут быть разные варианты, например "В данный момент выбранный тип оплаты не поддерживается" или "На вашем лицевом счете недостаточно средств для выполнения данной операции" ?
  • Как правильно интегрировать несколько систем в компании?

    @WhiteNinja Автор вопроса
    Спасибо огромное за развернутый ответ!
    Все как Вы описали я себе и представляю)
    В итоге получается так:
    1. ESB - не подходит из-за большого и сложного внедрения и сдерживающих организационных моментов. Другими словами, на мой взгляд слишком "круто" (во всех смыслах) для масштабов нашей организации - сделать сделаем, а поддерживать будет слишком сложно и дорого. (это как внедрить микросервисы в парикмахерской у дома).
    2. API или NuGet Services - эти решения в целом очень похожи, просто API это более изолированный способ интеграции двух систем (не зависит от сервера и.т.д). Но проблема и там и там одна и та же - джоины... как Вы и написали. Сейчас мы решаем эту задачу так:
    В сервисах есть методы _userService.AppendUsers(IEnumerable users) - где изначально в UserDto заполнены только свойства UserId, а все остальные (Name, Surname, Age и.т.д) = null. Метод соответственно делает SQL запрос с условием WHERE u.UserId IN ({string.Join(",", users.Select(x => x.UserId))}) и потом полученные данные записывает и модифицирует исходный IEnumerable users. Так как в 99.9% в системах используется постраничная навигация (ну или в случае с отчетами используется _batchSize), то это решение просто сводится к получению информации "пачками". В целом решение пока кажется мне рабочим, в том числе и в случае API.

    Поэтому пока я всё таки склоняюсь к переводу архитектуры всех систем на работу по API (вместо текущего NuGet Services (SQL connection strings)) так как это повысит уровень изолированности, но при этом "проблему джоинов", решать также через /GetUsers/?ids=[..] (метод API). Только добавить еще API gateway, чтобы все системы обращались в одно место, которое уже будет заниматься маршрутизацией по API.
  • Как правильно интегрировать несколько систем в компании?

    @WhiteNinja Автор вопроса
    Я не понял на какие компоненты Вы предлагаете разбить системы? У каждой системы своя БД и своя бизнес-логика. Т.е. Кадры - занимается учетом сотрудников и управлением доступом этих сотрудников к другим системам. Система Договоры занимается учетом договоров и только и система Поддержки тоже занимается обработкой обращений и только. Просто, например, в системе Поддержка для специалистов службы поддержки удобно, когда они могут в карточке обращения сразу увидеть список договоров клиента (договоры как раз вытягиваются, например через метод GetContracts(int userId) из системы Договоров) и.т.д.
    Т.е. все системы уже достаточно разбиты по зонам ответственности.
  • Как правильно интегрировать несколько систем в компании?

    @WhiteNinja Автор вопроса
    Упростить это можно через API Gateway - тогда все секреты придётся положить только в него, а клиентам нужен будет только доступ к гейтвею.


    Вот именно так я бы и хотел сделать! Что-то вроде сервера авторизации. Можете пожалуйста подсказать, что почитать или посмотреть пример какой-нибудь (github) про такой вариант архитектуры с API на C#? Я пока не до конца понимаю как конечно решение должно выглядеть. Получается при вызове метода API система делает два запроса - 1ый к API Gateway для получения credentials (или access_token), и 2ой уже непосредственно с полученными credentials к методу API?
  • Как правильно интегрировать несколько систем в компании?

    @WhiteNinja Автор вопроса
    Василий Банников, у нас просто уже есть такая реализация в двух системах (т.е. они как раз по API общаются). И там сделано так:

    Например, нужно связать система Договоры и систему Кадры (как в примере).
    Допустим, где-то в настройках системы Договор хранится её идентификатор - CNRCTS_01 (В реальности это GUID), а у системы Кадры - STAFF_01.
    Для взаимодействия по API у системы Договоры есть файл api_settings.json примерно следующего содержимого:

    {
    	"clients": [
    		{
    			"app_name": "STAFF",
    			"client_id: "STAFF_01",
    			"client_secret": "_SECRET1_"
    		}
    	]
    }


    А у системы Кадры соответственно следующий файл api_settings.json:

    {
    	"clients": [
    		{
    			"app_name": "CONTRACTS",
    			"client_id: "CNRCTS_01",
    			"client_secret": "_SECRET1_"
    		}
    	]
    }


    Получается на каждой стороне информация о другой стороне + одинаковый client_secret.
    Сами вызовы API используют JWT-токены.

    Когда я указал это в минусы способу по REST API я имел ввиду то, что получается если я захочу теперь еще связать систему Поддержка с системой Кадры,
    мне придётся не только в api_settings.json системы-потребителя (Поддержка) указать credentials, но и изменить api_settings.json системы-поставщика (Кадры).

    Надеюсь у меня получилось объяснить.
  • Какой алгоритм хеширования использовать?

    @WhiteNinja Автор вопроса
    Dr. Bacon, Для задачи поиска именно похожих в системе используются алгоритмы нечеткого поиска (
    Расстояние Левенштейна, коэффициент Танимото, алгоритм Захарова и.т.д) - это все используется в другой части приложения.

    А описанная мной в вопросе задача скорее решает задачу нахождения Четкого соответствия, предварительно очищая входные строки... как-то так :) Только SQL-запросы
    работают медленно, из-за отсутсnвия INDEX-а на этом поле :(

    Сам хеш (например MD5) я буду по очищенным и приведенным данным (ПРОДУКТНОМЕРОДИН30461), по тем, что сейчас являются ProductNameHash. Просто хочется заменить строки на меньшие.

    Получается для этого можно попробовать использоваться MD5 без боязни получить одинаковые хешы для разных ProductName на массивах 1 000 000 записей?
  • Какой алгоритм хеширования использовать?

    @WhiteNinja Автор вопроса
    Dr. Bacon, Все верно, тут скорее речь о "жестком" сравнении именно названий. Т.е. текущее решение, где просто удаляются все кроме букв и чисел вполне рабочее и всем устраивает, кроме скорости поиска по БД. Поэтому хотелось заменить хранимый хеш на более компактный, но работающий по такому же принципу.

    Т.е. в текущем решении если поменять буквы местами (опечатка), то тоже будет дубль. Просто предметная область диктует примерно такое правило: "ProductName всегда написан без опечатки в буквах и числах, но при этом может быть приправлен мусорными символами и разным регистром".
  • Какой алгоритм хеширования использовать?

    @WhiteNinja Автор вопроса
    Dr. Bacon, например классическая реализация MD5 хеширования на C#:

    using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
    {
    	byte[] inputBytes = Encoding.UTF8.GetBytes(input);
    	byte[] hashBytes = md5.ComputeHash(inputBytes);
    
    	// Convert the byte array to hexadecimal string
    	StringBuilder sb = new StringBuilder();
    	for (int i = 0; i < hashBytes.Length; i++)
    	{
    		sb.Append(hashBytes[i].ToString("X2"));
    	}
    	return sb.ToString();
    }


    MD5 покороче, но я переживаю за возможность схватить одинаковые значения хеша, для разных входных данных :(
  • Какой алгоритм хеширования использовать?

    @WhiteNinja Автор вопроса
    Dr. Bacon, Спасибо! Но насколько я понял - prefix INDEX создаётся только на N-первых символов от ProductNameHash. Правильно? Если это так, то такое решение не подходит, так как нужно использовать всю длину ProductNameHash, иначе можно получить дубли.
  • Какой алгоритм хеширования использовать?

    @WhiteNinja Автор вопроса
    Rsa97, Задача не допустить дубли. Данные о продуктах приходят из разных источников (например по средствам API, в aормате json) и например из 1-го источника пришел продукт "ПРОДУКТ номер - один, 30461". Мы записали его в БД с данными ProductName="ПРОДУКТ номер - один, 30461" и ProductNameHash="ПРОДУКТНОМЕРОДИН30461" (это как сейчас). Далее через какой-то промежуток времени из 2-го источниках пришли данные - "Продукт, Номер один: 30461", если построить "простой хеш" (как сейчас), то это будет ProductNameHash="ПРОДУКТНОМЕРОДИН30461" и соответственно новая запись в базе создана не будет, а произойдет "мягкое" обновление уже существующего продукта.

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

    Просто я столкнулся с проблемой медленных запросов. Соответственно я решил добавить INDEX-ы, но ProductName может содержать строку длиной 2500+ символов, а в MySQL (движок InnoDB) есть ряд ограничений на индексы для полей типа TEXT. И я подумал, что можно решить эту задачу путем хеширования строки, например "ПРОДУКТНОМЕРОДИН30461", и получения меньшей, одинаковой длины. И уже на это поле я без проблем смогу создать INDEX.
  • Какой алгоритм хеширования использовать?

    @WhiteNinja Автор вопроса
    Есть, но к сожалению только на движке MEMORY. А в приложении используется InnoDB, возможности поменять нет. А в InnoDB только BTREE :(