Даем пользователям keenetic ipv6

Внезапно (тм) я обнаружил, что пользователям, которые сидят за кинетиком, не достается ipv6. Хотя сам кинетик исправно получает ipv6 и отображает его в дашборде. Немного погуглив, я обнаружил, что одной подсетки /64 кинетику мало, ему надо еще отдать некий prefix description.

Итак, схема соединения простая router - keenetic - user.

На роутере поднят radvd, который отдает RA.

$ cat /etc/radvd.conf 
interface ens19 {
  AdvSendAdvert on;
  AdvDefaultPreference low;
  MinRtrAdvInterval 10;
  MaxRtrAdvInterval 30;

  prefix 2001:db8:99::/64 {
    AdvOnLink on;
    AdvAutonomous on;
    AdvRouterAddr on;
    AdvValidLifetime 120;
    AdvPreferredLifetime 100;
  };

  RDNSS 2001:db8:1::1 {
    AdvRDNSSLifetime 30;
  };

  DNSSL hlevnoe.lan {
    AdvDNSSLLifetime 30;
  };
};

Роутер совершенно честно получает 2001:db8:99:0:52ff:20ff:fe7d:5d71 и показывает этот же адрес у себя в дашборде. И вот тут у меня возник затык. Везде рецепты по получению этого самого PD приводили к каким-то шаманским пляскам с systemd-network и прочим вещам. Естественно, роутеру на это было совершенно монопенисуально. В итоге индеец зоркий глаз обнаружил, что ISC DHCPD умеет отдавать этот самый PD.

$ cat /etc/dhcp/dhcpd6.conf 
default-lease-time 150;

preferred-lifetime 100;
option dhcp-renewal-time 50;
option dhcp-rebinding-time 50;
allow leasequery;
option dhcp6.name-servers 2001:db8:1::1;
option dhcp6.domain-search "hlevnoe.lan","iot.hlevnoe.lan","wifi.hlevnoe.lan";

option dhcp6.preference 255;

option dhcp6.info-refresh-time 60;

subnet6 2001:db8:99::/48 {
	prefix6 2001:db8:100:100:: 2001:db8:100:200:: /56;
}

Я вырезал лишнее. Если кратко, то вся суть в последних трех строчках. DHCPD садится на интерфейс, содержащий адрес из подсети 2001:db8:99::/48 и говорит, что любой обратившийся может взять префикс /56 из диапазона 2001:db8:100:100-200

Перезапускаем и тут же получаем в логах следующее

Sep 04 14:36:19 router-wifi dhcpd[2060]: Rebind message from fe80::52ff:20ff:fe7d:5d71 port 546, transaction ID 0x4E15F400
Sep 04 14:36:19 router-wifi dhcpd[2060]: Reply PD: address 2001:db8:100:200::/56 to client with duid 00:03:00:01:50:ff:20:7d:5d:71 iaid = 1 valid for 150 seconds
Sep 04 14:36:19 router-wifi dhcpd[2060]: Sending Reply to fe80::52ff:20ff:fe7d:5d71 port 546

Идем в дашборд кинетика и видим появившуся строчку IPv6 prefix

И клиент тоже подтверждает, что он получил айпишник из этого префикса

2: wlp0s20f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 68:3e:26:b0:b1:93 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.128/24 brd 192.168.1.255 scope global dynamic noprefixroute wlp0s20f3
       valid_lft 215sec preferred_lft 215sec
    inet6 2001:db8:100:200:fd6c:e8a9:6e3:7d75/64 scope global temporary dynamic 
       valid_lft 134sec preferred_lft 84sec
    inet6 2001:db8:100:200:ae30:1497:47c9:c0e7/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 134sec preferred_lft 84sec
    inet6 fe80::8e0b:e946:d9e4:9dfd/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

И теперь самое сложное: дать роутеру понять, куда надо роутить трафик для 2001:db8:100: . Вот тут я нормальных решений не нашел. Кинетик не умеет в динамические протоколы роутинга, а городить некий парсер логов и потом править роуты мне стало откровенно лень. Как делают большие пацаны из телекомов я тоже не нашел. Поэтому я взял и захардкодил это в роуты

      routes:
        - to: "2001:db8:100::/48"
          via: "2001:db8:99:0:52ff:20ff:fe7d:5d71"
          on-link: true

Да, криво. Да, может сломаться, если кто-то еще в этой сети попросит PD. Но, повторюсь, других вариантов я не нашел.

Ну а дальше наслаждаемся нормальным ipv6 и прочими положенными плюшками

Оживляю старую АТС Panasonic NCP

Для осуществления старой мечты про свой собственный модемный пул со 100% дозвоном мне потребовалась АТС. Поначалу я планировал воткнуть в нее два модема, поперезваниваться и успокоиться. Однако стоило приехать старой аналоговой, как мне уже захотелось получить дозвон с V.90. А это значит, что одним аналогом не обойтись и требуется уже цифра.

Цифра так цифра. Немного поискав на просторах интернета, я обнаружил продаваемые в большом количестве АТС Panasonic NCP 500/1000. Еще немного погуглив, прикинул список необходимых плат в ней для моего развлечения и заказал наиболее подходящую.

Для пытающихся повторить мой путь: необходима плата PRI30, по которой будет идти цифровой поток в cisco 5350 (она внизу, там платы 2PRI и NP60 – тоже очень широко распространенный бандл) и SLC8/16 (в нее будут вставляться аналоговые модемы и прочие телефоны).

Следующий вопрос, который необходимо решить: как настроить/узнать настройки АТС? И вот тут внезапно для любого ИТшника встает сразу несколько проблем. Самая главная в том, что телефонисты – это такие заносчивые и высокомерные индюки, которые хрена-с-два поделятся информацией. И фиг бы на них, но и официальная документация от самого панасоника представляет из себя лютейший фейспалм с кучей ошибок. В общем, если ты был на курсах и тебя научили как тыкать по менюшкам, то ты молодец. Остальные – быдло, достойные только для того, чтобы их поунижать. По большей части, этот пост родился благодаря таким телефонистам.

Итак, для начала достаем из станции SD карту и делаем бекап на всякий случай. Если изучить файлики, то становится понятно, что там лежит вся конфигурация АТС вместе с дополнительными лицензиями (если они были).

Теперь про пароли. Вроде можно вручную найти нужное в DBSYS, но мне лень и я отыскал программку KXTDA_password_recovery. Ей скармливаешь этот файлик и она выдает пароли, которые поставил ваш предшественник. Иногда это что-то сложное, но чаще это стандартные 1234 (на двух из трех АТС у меня было так).

Узнав пароли, засовываем карту назад в АТС. Но пока не включаем. Нужна программа для настройки. Она лежит в архиве UPCMCv7.8.1.1_R15.zip. Распаковываем, ставим и она спросит про ключ. Тут уже постаралась сама panasonic. Чтобы подсадить “инсталляторов атс” на толстую… ну пусть будет иглу, она требовала ежегодной дани от своей паствы. Прошедшие курсы получали дырку, через которую могли генерить эти ключи в количестве аж двух штук в год (если форумы не врут). Мы же просто воспользуемся программкой upcmc_kg_2024.exe, которая генерит ключи на 2024 год. Рядом лежит она же, но генерящая ключи на 2025й. Когда наступит 2026, то просто сравните побайтно эти программки, найдите один байт разницы и увеличьте его на еденицу.

Ок, программа поставилась, и согласна соединяться. Но куда и с чем? С этим тоже все просто: вставляем сетевой кабель в LAN, запускаем tcpdump или wireshark и включаем станцию. Немного помигав лампочками, она включит свой ethernet и согласно всяким стандартам, бросит ARP запрос на предмет совпадения ядреса. Ну и естественно, скажет свой. Хоть станция и умеет в DHCP, но телефонисты в него не умеют, поэтому везде рекомендуют ставить статику, так что в 99,99% вы не увидите bootp запросов. Ну а дельше дело техники: на компе настраиваем любой адрес из той же подсети и можно подключаться.

Теперь единственное, что может вас остановить, это регистр. Нет, я не шучу и програмисты-телефонисты настолько тупые, что не осилили функцию strup/strlow. Так что вводить INSTALLER надо исключительно в верхнем регистре. Я на этом пару раз погорел. Хорошо, что хоть пароль из цифр (в буквы они тоже не любят).

Дальше проблем нет. Программа открывает вам все потроха станции и вы можете изучить, что оставил вам ваш предшественник. Скажу сразу, будет немного больно, ибо для ИТшника настройки разбросаны хаотически и чтобы получить даже простую фигню типа “входящий звонок приходит сразу на несколько телефонов” надо попрыгать по нескольким экранам.

Но, если вы дочитали до этого момента, то есть способ завести АТС еще проще (на всякий: лицензии не пропадут). Сделав бекап, просто включите АТС с передвинутым влево, на SYSTEM INITIALIZE, движком. Подождите, пока светодиодик RUN замигает и передвиньте назад, на NORMAL. Все, теперь АТС на порту LAN будет ждать вас по адресу 192.168.0.101. После подключения вас спросят про пару глупостей и предложат настроить все по-минимуму. Говоря проще, программка раскидает телефонные номера согласуясь со вставленными картами слева-направо и сверху-вниз. Все, вы можете втыкать телефоны, перезваниваться и выходить в город “через девятку”. Конечно, если у вас есть плата для внешних линий LCOT.

Ну а теперь остается только читать документацию, сравнивать с тем, что можно в реальности и шариться по остаткам форумов. Как я писал выше, можно даже не регистрироваться – все равно толку не будет.

А теперь то, что я уже обнаружил.

Во-первых, забудьте про порт MNT. Да, это ethernet, да в инструкции написано, что можно через него администрировать АТС. Врут. На этом порту никогда ничего не появляется. Ни при ресете, ни при инициализации, ни при работе. Пусто и глухо. Так что только LAN.

Потом, кнопочка Reset – это просто выключение-включение питания. Сделали поблажку, ибо на морде атс всегда висит пучок кабелей и добраться до выключателя сзади проблематично.

Следом: если у вас атс NS (там все, окромя прошивок, подходит от NCP), то никогда не дергайте ее по питанию! Погромисты из панасоника не осилили повторить то, что они сделали в NCP и очень велик шанс все угробить на SD карте.

Ну и наконец, вот вам ссылочка https://tygh.ru/s/iiwLyPKpzGESZCX , куда я выложил все то, что на данный момент нарыл для панасоника. Включая вышеупомянутые программки. Да, там есть дубликаты в доках, но мне пока лень их вычищать.

Оживляю старую Cisco 881G

Достал я тут из закромов чудного зверька, с которым раньше не сталкивался. Cisco 881G. Маленькая настольная коробочка с двумя антеннами и 5 ethernet портами. Если на езернеты мне было пофиг, то вот антеннки возбудили мое любопытство.

Оказалось, что в этой коробочке спрятали 3G модем, совмещенный с GPS. Ну и роутер в довесок.

Ок, цепляюсь к коробочке кабелем и смотрю, что там в наличии отсутствия.

show flash
copy flash:c880data-universalk9_npe-mz.153-3.M.bin tftp://100.64.1.1 

Такой версии IOSа в моей коллекции честно спертых нет, поэтому ныкаем поближе.

Ладно, вытаскиваю коробочку на окно и смотрю, к чему прицепился модем

Router#show cellular 0 network
Current Service Status = Normal, Service Error = None
Current Service = Combined
Packet Service = HSPA (Attached)
Packet Session Status = Inactive
Current Roaming Status = Home
Network Selection Mode = Automatic
Country = RUS, Network = ROSTELEC
Mobile Country Code (MCC) = 250
Mobile Network Code (MNC) = 20
Location Area Code (LAC) = 28600
Routing Area Code (RAC) = 202
Cell ID = 34499
Primary Scrambling Code = 329
PLMN Selection = Automatic
Registered PLMN =  , Abbreviated = 
Service Provider = ROSTELECOM
Router#show cellular 0 radio  
Radio power mode = ON
Current Band = WCDMA 2100, Channel Number = 10612
Current RSSI = -90 dBm
Band Selected = Auto
Number of nearby cells = 1
Cell 1
        Primary Scrambling Code = 0x149
        RSCP = -91 dBm, ECIO = -5 dBm

Все верно. Мне выдали вместе с GPON симку от “Ростелеком”, вот он туда и прицепился. Курю маны, читаю старые архивы. Гуглю… В общем, прошло пара дней. Теперь вы можете быстренько пробежаться вместе со мной. Если что, у коробочки есть встроенный веб-сервер, но он сделан на технологиях 2000х годов и современные браузеры в нем только статус могут показать.

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

cellular 0 gsm profile create 1 internet.rtk.ru chap rtk rtk

Теперь конфигурируем, конфигурируем и заканчиваем конфигурировать. Подозреваю, что есть лишние ошметки, но это рабочая конфигурация. Болдом – то, что я вводил. Остальное оно само.

cisco-881G#show run
Building configuration...

Current configuration : 2041 bytes
!
! Last configuration change at 12:11:05 UTC Sun Aug 18 2024
! NVRAM config last updated at 12:11:07 UTC Sun Aug 18 2024
! NVRAM config last updated at 12:11:07 UTC Sun Aug 18 2024
version 15.3
no service pad
service timestamps debug datetime msec
service timestamps log datetime msec
no service password-encryption
!
hostname cisco-881G
!
boot-start-marker
boot-end-marker
!
!
enable password cisco
!
no aaa new-model
!
!
!         
no ip dhcp use vrf connected
!
!
!
ip cef
no ipv6 cef
!
!
multilink bundle-name authenticated
chat-script hspa-R7 "" "AT!SCACT=1,1" TIMEOUT 60 "OK"
!
!
license udi pid C881G+7-K9 sn FCZ1806C3EH
license boot module c880-data level advipservices_npe
!
!
!
!
controller Cellular 0
 gsm sms archive path tftp://100.64.1.1/SMS
 gsm gps mode standalone
 gsm gps nmea
!         
ip tftp source-interface Vlan1
!
!
!
!
interface FastEthernet0
 no ip address
!
interface FastEthernet1
 no ip address
 shutdown
!
interface FastEthernet2
 no ip address
 shutdown
!
interface FastEthernet3
 no ip address
 shutdown
!
interface FastEthernet4
 no ip address
 shutdown 
 duplex auto
 speed auto
!
interface Cellular0
 ip address negotiated
 ip nat outside
 ip virtual-reassembly in
 encapsulation slip
 history BPS
 dialer in-band
 dialer idle-timeout 0
 dialer string hspa-R7
 dialer-group 1
 async mode interactive
!
interface Vlan1
 ip address 100.64.1.4 255.255.255.0
 ip nat inside
 ip virtual-reassembly in
!
ip forward-protocol nd
ip http server
no ip http secure-server
!
!
ip nat inside source list 1 interface Cellular0 overload
ip route 0.0.0.0 0.0.0.0 Cellular0
!
dialer-list 1 protocol ip permit
!
access-list 1 permit 100.64.1.0 0.0.0.255
!
control-plane
!
!
!
line con 0
 password cisco
 login
 no modem enable
line aux 0
line 3
 script dialer hspa-R7
 modem InOut
 no exec
 rxspeed 21600000
 txspeed 5760000
line 6
 modem InOut
 no exec
 transport input all
 transport output all
 stopbits 1
 speed 4800
line vty 0 4
 password cisco
 login
 transport input all
!
ntp source Cellular0
ntp master 1
ntp update-calendar
!
end

Конфигурация следующая. 100.64.1.4 – это адрес циски. Работает только порт 0. Всё, что приходит с 100.64.1.0/24 – натить в интернет через сотовый модем. Ну и попутно включить GPS и попытаться брать с него время.

В чем была проблема? Я никак не мог поднять интерфейс модема. Он радостно сообщал, что включен, но адрес от провайдера получать категорически отказывался. В статусе было, что он занимается спуфингом. Покурив интернеты еще раз, я обнаружил, что достаточно добавить в line 3 строку про modem inout, как все тут же зажурчало, как и положено. Почему ее нет ни в одном официальном гайде циски про 880е – я не знаю. И почему dialer idle-timeout 0 игнорируется до первого подьема – я тоже не знаю.

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

#ping 8.8.8.8
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds:
...
*Aug 18 10:55:41.267: %LINK-3-UPDOWN: Interface Cellular0, changed state to up
*Aug 18 10:55:42.267: %LINEPROTO-5-UPDOWN: Line protocol on Interface Cellular0, changed state to up.!
Success rate is 20 percent (1/5), round-trip min/avg/max = 84/84/84 ms

Вот он, исторический момент. Сработало все, хотя и 4 пакета потерялись, пока модем поднимался. А что насчет смс? Отправляю себе на телефон и отвечаю.

# cellular 0 gsm sms send 8926295хххх "Test from cisco"
Aug 18 11:55:37.691: %CELLWAN-5-INCOMING_SMS: Cellular0 has just received new incoming SMS.
#cellular 0 gsm sms view all
SMS ID: 0
TIME: 24/08/18 16:00:01
FROM: 7926295хххх
SIZE: 4
^D^^^D:
--------------------------------------------------------------------------------
SMS ID: 1
TIME: 24/08/18 16:09:39
FROM: 7926295хххх
SIZE: 7
Privet 
--------------------------------------------------------------------------------

Ну с смс тут все очень кондово. Первая смс это “Ок” на русском. Ладно, а что с GPS?

#show cellular 0 gps

GPS Info
-------------
GPS State: GPS acquiring
GPS Mode Configured: standalone
GPS Error Count: 0
Latitude: 0 Deg 0 Min 0 Sec North
Longitude: 0 Deg 0 Min 0 Sec East
Timestamp (GMT): Sun Jan  6 00:00:00 1980

Fix type index: 0
Satellite Info
----------------
Satellite #11, elevation 0, azimuth 0, SNR 26 *
Satellite #20, elevation 0, azimuth 0, SNR 24 *
Satellite #6, elevation 0, azimuth 0, SNR 19 *

А вот с GPS все плохо. С трудом нашла 3 спутника, хоть и стоит на окне и близко к стеклу. Да и у тех уровень сигнала около плинтуса. Вот она, корпоративная надежность! Рядом лежащий usb GPS приемник за 300 рублей видит кучу и совершенно ничем не смущается. Обидно.. надо подумать, как там антенну поближе вытащить или сделать ее побольше. Ибо хочу свой NTP сервер со стратумом 1 и все тут!

Соеденить две площадки…

… Казалось бы, что может пойти не так?

Недавно мне потребовалось соеденить две площадки с виртуалками. Обе у нас (ПОДЧЕРКИВАЮ!), обе у достаточно крупных провайдеров. В общем, надо сделать так, чтобы Н машин у одного провайдера видели М машин у другого. Трафик не большой, но достаточно критичный.

“ХА!” – сказал я и нарисовал классическую схему соединения.

Выделяем на каждой площадке машинку (или на одну из доступных вешаем внешний ip), обвешиваемся файрволами и закрываем трафик тем же IPSec. Инструкций много, вариантов много – в общем, прорвемся!

Быстренько собрал, накидал конфиги и получил веслом по морде. Протокол ESP где-то по пути заблокирован. Техподдержка обоих провайдеров клянется, что это не у них, но ipsec не верит и отказывается подниматься. Ладно, хотелось по-корпоративному, пойдем по-молодежному.

OpenVPN шустро поднялся, поначалу начал бодро гонять трафик, но через некоторое время начались проблемы. Он переподсоединялся, слал немного байт и снова уходил в нирвану. Смена протокола с UDP на TCP приносила лишь временное облегчение.

Кто виноват – мне, если честно говорить, абсолютно пофиг. Мне трафик нужно гонять. Поэтому расчехлил тяжелую хипстерскую артиллерию – shadowsocks + v2ray. Качаем с гита, просто распаковываем, плюем в конфиг сервера следующее (1.1.1.1 – это внешний адрес сервера, если что):

{
  "server": "1.1.1.1",
  "server_port": 888,
  "password": "verysecretpass",
  "method": "chacha20-ietf-poly1305",
  "timeout": 7200,
  "no_delay": true,
  "fast_open": true,
  "mode": "tcp_and_udp",
  "plugin": "/opt/shadowsocks/v2ray-plugin_linux_amd64",
  "plugin_opts": "server"
} 

А в конфиг клиента вот это:

{
  "server": "1.1.1.1",
  "server_port": 888,
  "local_address": "127.0.0.1",
  "local_port": 1080,
  "password": "verysecretpass",
  "method": "chacha20-ietf-poly1305",
  "timeout": 7200,
  "no_delay": true,
  "fast_open": true,
  "mode": "tcp_and_udp",
  "plugin": "/opt/shadowsocks/v2ray-plugin_linux_amd64",
  "plugin_opts": ""
}

Запускаем и получаем на клиенте socks5 сервер на 1080 порту. А теперь – финт конем. В конфиг OpenVPN на клиенте добавляем одну единственную строчку:

socks-proxy 127.0.0.1 1080

Ну и перезапускаем все, чтобы прочитало конфиги. Вуаля! У нас получилась следующая схема:

OpenVPN ходит через ShadowSocks, который ходит через хрен знает как настроенный интернет.

Но через некоторое время проявилась та же самая боль: немного погодя клиент терял соединение с сервером. Причем перезапустишь – все снова начинает бегать. Ставил опции ping, менял MSS и MTU – пофиг: рандомно теряем коннект.

Ок, перевел openvpn и shadowsock на TCP. Всё магически исправилось. Коннект стабильный, не рвется, пакетики бегают туда-сюда.

Отключил "mode": "tcp_and_udp", позакрывал фаирволлами и начал тестить.

Итак, прямой tcp линк безо всяких штук

[  1] 0.0000-10.2561 sec   112 MBytes  91.8 Mbits/sec

Да, клиент сидит на дешевом тарифном плане в 100 мегабит, поэтому практически упираемся в полку. Теперь через все эти навороты:

[  1] 0.0000-10.3474 sec  50.8 MBytes  41.1 Mbits/sec

И это без какого-либо тюнинга! Да, tcp-over-tcp-over-tcp еще тот изврат, но ведь работает же! А после тюнинга (банальные буфера и прочее – в любом мануале по openvpn) я получил следующее:

[  1] 0.0000-100.4276 sec   896 MBytes  74.8 Mbits/sec

Что в плюсах:

  1. Нам надо платить меньше. На одной стороне не нужен выделенный ip (а они нынче дорогие). Выпускают всех через SNAT и норм.
  2. Настраивается не просто, а очень просто.
  3. Снаружи на сервере порт OpenVPN можно спокойно закрыть фаирволлом. Соединение идет с локалхоста. Больше сесуретей богу сесурити!
  4. Память не жрет. Можно смело брать самую дешевую виртуалку под “роутеры”. Вся вот эта машинерия + FRR с OSPF сьели 200 мегов.
  5. Оно работает. Реально, за неделю уже не одиного разрыва.

Что в минусах:

  1. Потеряли в скорости. Немного, но есть. Проблема в том, что на стороне клиента я банально уперся в единственный ЦПУ виртуалки. Когда тесты идут, на той стороне в топе такое:

С другой стороны, там трафик в 20-30 мегабит уже редкость, так что в любом случае все в порядке. Но запас карман не тянет.

Ну и нафига я все это делал: мне нужно было среплицировать один MySQL в другой. Предложенная схема их удовлетворила, значит задача выполнена.

CentOS 7 – надо выжить!

Слишком много серверов осталось на centos. И, внезапно, приходят странные заказчики, которым кровь из носу нужен именно centos и именно 7й версии. Поставить-то можно поставить, но где найти новые версии пакетов, ведь эти редиски грохнули имя mirror.centos.org?

Рецепт простой. Пока (пока!) работает такой рецепт

sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* && yum update

Influx и Telegraf

Поначалу я планировал этот пост про InfluxDB. Дескать, вот так поставим, вот так настроим… Однако реальность больно тыкнула вилкой в глаз: поставил, запустил, зашел на influx:8086, установил пароль, завел организацию… и всё. Нет, реально всё. Больше там ничего не потребовалось делать.

А вот с телеграфом пришлось повозиться. Дело в том, что я возжелал с одной машины отправлять разные метрики в разные бакеты. Ну всякие там “загрузка процессора и памяти” в один, а “температура в доме” – в другой. Ну вот захотелось мне так.

Все просто. Для начала прямо в telegraf.conf добавим тег influxdb_database

# Global tags can be specified here in key="value" format.
[global_tags]
  # dc = "us-east-1" # will tag all metrics with dc=us-east-1
  # rack = "1a"
  ## Environment variables can be used as tags, and throughout the config file
  # user = "$USER"
  influxdb_database = "default"

Да, я очень неоригинален в этом плане. Теперь ко всему, что собирает telegraf по умолчанию добавляется тэг influxdb_database со значением default.

Теперь добавляем сборку данных с mqtt. Заполняем файл /etc/telegraf/telegraf.d/mqtt.conf

[[inputs.mqtt_consumer]]
  servers = ["tcp://127.0.0.1:1883"]

  ## Topics that will be subscribed to.
  topics = [
    "/devices/+/controls/temperature",
    "/devices/+/controls/battery",
    "/devices/+/controls/humidity",
    "/devices/+/controls/pressure",
    "/devices/+/controls/co2",
    "/devices/+/controls/MCU Temperature",
    "/devices/+/controls/CPU Temperature",
    "/devices/dark_room_power/controls/voltage",
    "/devices/dark_room_power/controls/power",
    "/devices/sleeping_room_power2/controls/voltage",
    "/devices/sleeping_room_power2/controls/power",
  ]

    data_format = "value"
    data_type = "float"

[inputs.mqtt_consumer.tags]
    influxdb_database = "mqtt"

Тут тоже все просто: указываем адрес сервера, указываем, на какие топики подписаться, их формат и последней строчкой меняем значение тега на mqtt. И теперь самая магия:

[[outputs.influxdb_v2]]
urls = ["http://influxdb.hlevnoe.lan:8086"]
token = "xf3w6SKIPSKIP7z1hPQ=="
organization = "hlevnoe"
bucket = "hlevnoe"
[outputs.influxdb_v2.tagpass]
influxdb_database = ["default"]

И сравните с вторым

[[outputs.influxdb_v2]]
urls = ["http://influxdb.hlevnoe.lan:8086"]
token = "xf3w6nSKIPSKIPvam7z1hPQ=="
organization = "hlevnoe"
bucket = "mqtt"
[outputs.influxdb_v2.tagpass]
influxdb_database = ["mqtt"]

Наверняка для матерых инфлюксоводов это покажестя легкой шуткой, но я честно потратил пару часов на раскуривание функционала tagpass. Больше, правда, на выяснение, как и куда его правильно прописать. В общем, теперь все с influxdb_database = default попадает в бакет hlevnoe, а mqtt в mqtt.

Запустив все это и убедившись в отсутствии ошибок, можно вернуться в influx. Там есть простенький data explorer, позволяющий потыкаться и порисовать графики. Даже можно простейшие дашборды собрать!

Вот, к примеру, график потребления электричества у морозильника.

Или график температуры у меня за окном

В общем, это далеко не графана, но по-быстрому позырить что к чему – можно.

Готовим котёнка

Умная мысля приходит обычно слишком поздно. Вот и тут, я много лет страдал при переходе с одного компа на другой. В каждой операционке своя терминалка, со своими дрючками и глючками. Я ходил, настраивал и пытался их подогнать одну к другой.. Хорошо еще, что хоть чуть-чуть шорткаты устаканились, а то вообще боль была…

В общем, я решил сменить терминалку. Немного подумал и составил офигенно длинный лист требований:

  • Терминалка должна работать под Linux, MacOS и Windows (WSL)
  • Она должна работать одинаково. То есть один и тот же параметр в конфиге должен приводить к одним и тем же изменениям в поведении.
  • Терминалка должна уметь в truecolor.
  • Терминалка должна уметь в шрифтовые лигатуры.

Всё остальное, типа рендеринга на GPU или особо правильной поддержке многих систем, мне было совершенно не нужно. Главное, чтобы я взял ноутбук на другой операционке и получил абсолютно тот же… сейчас это модно называть экспириенсом. Внезапно самым сложным для терминалок оказался последний пункт.

Я не понимаю, чего сложного в подобной конвертации символов -> >> <> != ? Но, например, авторы gnome terminal не осилили подобного и отмазались, что не для всех языков это может работать. Ну сделали бы не для всех…

И, внезапно, всем моим хотелкам удовлетворила только одна терминалка – kitty. Если быть до конца честным, то нет, были и другие, но они не такие гламурные. Ставить котёнка можно 100500 способами, но я предпочел через пакетный менеджер.

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

font_family Fira Code
font_size 12
cursor_shape block
cursor_shape_unfocused hollow
shell_integration no-cursor
scrollback_lines 10000
sync_to_monitor yes
remember_window_size  yes
initial_window_width  800
initial_window_height 600
include theme.conf
tab_bar_style slant
update_check_interval 0
term xterm-256color
paste_actions quote-urls-at-prompt
background_opacity 1
confirm_os_window_close 0
map super+n new_os_window_with_cwd
map super+t new_tab_with_cwd
map super+w close_os_window
map super+c copy_to_clipboard
map super+v paste_from_clipboard

Последние строчки – это дань моей лени, чтобы новые окошки открывались как на макоси. Win+n и не надо пальцы ломать об Ctrl+Shift+n . Мелочь, а удобно. Ну и файлик theme.conf, честно спертый из интернета и имитирующий тему homebrew

# Theme ported from the Mac Terminal application.

background #000000
foreground #00ff00
cursor #23ff18
selection_background #083905
color0 #000000
color8 #666666
color1 #990000
color9 #e50000
color2 #00a600
color10 #00d900
color3 #999900
color11 #e5e500
color4 #0000b2
color12 #0000ff
color5 #b200b2
color13 #e500e5
color6 #00a6b2
color14 #00e5e5
color7 #bebebe
color15 #e5e5e5
selection_foreground #e5e5e5

И вот я уже почти неделю живу на двух операционках и с одним терминалом. Нормально …

Теперь операционко-специфичные штуки.

MacOS: надо в ENV переменные добавить KITTY_CONFIG_DIRECTORY=~/.config/kitty/ , иначе котенок хз где хранит конфиги. А так все в одинаковом месте. Чтобы сменить иконку, надо ее просто рядом с конфигом положить и обозвать kitty.app.png.

Linux: чтобы сменить иконку, надо сделать desktop файл, аналогичный нижеприведенному, и положить его в .local/share/applications/ . Главная боль – путь до иконки должен быть абсолютным.

[Desktop Entry]
Version=1.0
Type=Application
Name=kitty
GenericName=Terminal emulator
Comment=Fast, feature-rich, GPU based terminal
TryExec=kitty
StartupNotify=true
Exec=kitty
Icon=/home/kiltum/.config/kitty/kitty.app

Все 🙂

Всё своё ношу с собой. Локальное зеркало.

Пора, пора описывать то, что было сделано. А то как обычно, забудется и всё, пиши “прощай”.

Итак, давным-давно, когда ещё существовала страна под названием “Украина”, я начал делать свою… Ну даже не знаю, на лабораторию это не тянет, на свой датацентр тоже. В общем, несколько серверов, выполняющих нужные для меня задачи. Часть арендованные, часть свои… И всё было совсем хорошо, пока не началась СВО. Тут же вылезла куча говна и давай блочить доступ. Следом к ним присоеденились убегуны и давай портить до чего руки дотянутся. Дескать, они все такие чувствительные, что не могут позволить такое и вааще, они только за самое хорошее! Но тут не про них, а про то, как сделать себе хорошо и нагло игнорировать подобное сейчас и в будущем.

Итак, условия для этой задачи и последующих простые: я должен иметь возможность поставить или обновить нужное мне в любой момент времени. Есть интернет, нету – все равно. И первым шагом я сделаю зеркало для пакетов дистрибутива ubuntu.

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

apt install apache2 debmirror gnupg xz-utils rsync

mkdir -p /mirror
mkdir /mirror/debmirror
mkdir /mirror/debmirror/amd64
mkdir /mirror/debmirror/mirrorkeyring
mkdir /mirror/scripts

gpg --no-default-keyring --keyring /mirror/debmirror/mirrorkeyring/trustedkeys.gpg --import /usr/share/keyrings/ubuntu-archive-keyring.gpg

cd /var/www/html
ln -s /mirror/debmirror/amd64 ubuntu

cd /mirror/scripts

А вот теперь скрипт, который все друг у друга таскают. Я не исключение

# cat > debmirroramd64.sh 
#!/bin/bash

## Setting variables with explanations.

#
# Don't touch the user's keyring, have our own instead
#
export GNUPGHOME=/mirror/debmirror/mirrorkeyring

# Arch=         -a      # Architecture. For Ubuntu can be i386, powerpc or amd64.
# sparc, only starts in dapper, it is only the later models of sparc.
# For multiple  architecture, use ",". like "i386,amd64"

arch=amd64

# Minimum Ubuntu system requires main, restricted
# Section=      -s      # Section (One of the following - main/restricted/universe/multiverse).
# You can add extra file with $Section/debian-installer. ex: main/debian-installer,universe/debian-installer,multiverse/debian-installer,restricted/debian-installer
#
section=main,restricted,universe,multiverse

# Release=      -d      # Release of the system (, focal ), and the -updates and -security ( -backports can be added if desired)
# List of updated releases in: https://wiki.ubuntu.com/Releases
# List of sort codenames used: http://archive.ubuntu.com/ubuntu/dists/

release=noble,noble-security,noble-updates,noble-backports

# Server=       -h      # Server name, minus the protocol and the path at the end
# CHANGE "*" to equal the mirror you want to create your mirror from. au. in Australia  ca. in Canada.
# This can be found in your own /etc/apt/sources.list file, assuming you have Ubuntu installed.
#
server=ru.archive.ubuntu.com

# Dir=          -r      # Path from the main server, so http://my.web.server/$dir, Server dependant
#
inPath=/ubuntu

# Proto=        --method=       # Protocol to use for transfer (http, ftp, hftp, rsync)
# Choose one - http is most usual the service, and the service must be available on the server you point at.
# For some "rsync" may be faster.
proto=rsync

# Outpath=              # Directory to store the mirror in
# Make this a full path to where you want to mirror the material.
#
outPath=/mirror/debmirror/amd64

# By default bandwidth is not limited. Uncommend this variable and set it to the apropriate
# value in Kilobytes per second. Also don't forget to uncomment the --rsync-options line in the last section below.
bwlimit=1000

# The --nosource option only downloads debs and not deb-src's
# The --progress option shows files as they are downloaded
# --source \ in the place of --no-source \ if you want sources also.
# --nocleanup  Do not clean up the local mirror after mirroring is complete. Use this option to keep older repository
# Start script
#
debmirror       -a $arch \
                --no-source \
                -s $section \
                -h $server \
                -d $release \
                -r $inPath \
                --progress \
                --method=$proto \
                --rsync-options "-aIL --partial --bwlimit=$bwlimit" \
                $outPath

Скрипт настроен на российский миррор и лимит в 1 мегабайт в секунду, чтобы не забивать канал, как минимум при первоначальной скачке. Ну и релиз поменял на noble, ибо нынче уже 2024 год и в ходу у меня 24.04. Далее просто запускаем этот скрипт и идем заниматься своими делами. Оно медленно и печально высосет кучу гигабайт. Реально КУЧУ гигабайт. На момент написания размер зеркала был в районе двухсот гигов.

Ну а дальше просто везде разбрасываем новый ubuntu.list, заменяя им ubuntu.sources

deb http://mirror/ubuntu noble main restricted universe multiverse
deb http://mirror/ubuntu noble-security main restricted universe multiverse
deb http://mirror/ubuntu noble-updates main restricted universe multiverse

И точно так же миррорим что-то другое. К примеру, возжелал я поставить InfluxDB. Можно пакетики тащить, а можно зеркало сделать.

wget -q https://repos.influxdata.com/influxdata-archive_compat.key
gpg --no-default-keyring --keyring /mirror/debmirror/mirrorkeyring/trustedkeys.gpg --import influxdata-archive_compat.key
mkdir -p /mirror/debmirror/influx/
cat influxdata-archive_compat.key | gpg --dearmor > /mirror/debmirror/influx/key.gpg
cd /var/www/html
ln -s /mirror/debmirror/influx influx

И чуточку поправленный скрипт без комментариев. Изменил только откуда брать, куда ложить и то, что не надо использовать rsync. Адреса и прочее я нагло упер из инструкции с официальной страницы https://www.influxdata.com/downloads/, когда выбрал Ubuntu&Debian

# cat influx.sh 
#!/bin/bash

export GNUPGHOME=/mirror/debmirror/mirrorkeyring
arch=amd64
section=main
release=stable
server=repos.influxdata.com
inPath=/debian
proto=http
outPath=/mirror/debmirror/influx

debmirror       -a $arch \
                --no-source \
                -s $section \
                -h $server \
                -d $release \
                -r $inPath \
                --progress \
                --method=$proto \
                --rsync-extra=none \
                $outPath

Ну и потом на хосте, куда что-то от influx будет ставиться:

wget http://mirror.hlevnoe.lan/influx/key.gpg -O /usr/share/keyrings/influx.gpg

cat > /etc/apt/sources.list.d/influx.sources 
Types: deb
Architectures: amd64
Signed-By: /usr/share/keyrings/influx.gpg
URIs: http://mirror.hlevnoe.lan/influx
Suites: stable
Components: main

Дальше совершенно стандартно: apt update && apt install...

Умный дом. MQTT сервер

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

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

Вообще у меня уже есть один mqtt сервер, встроенный в wirenboad. Но есть два больших но: 1) сам по себе wirenboard очень дохлый (хотя народ радостно на него даже Home Assistant в докере водружает) и 2) у меня будет очень много устройств, общающихся по MQTT.

Поэтому решение простое: поднимаем на виртуалке MQTT сервер и заставляем всех с ним работать. А кто не умеет или умеет не кошерно – забирать с тех данные самим. Для реально больших нагрузок или отказоустойчивости народ ставит EMQX, но у меня такого не будет, поэтому использую mosquitto.

apt install mosquitto mosquitto-clients

Все настройки оставляю по умолчанию, просто добавляю один мост wirenboard->mosquitto.

# cat /etc/mosquitto/conf.d/wirenboard.con
connection wirenboard
address wirenboard:1883
bridge_insecure true
topic # in 0

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

mosquitto_sub -t \#

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

Первая ачивка получена!

Как сбросить кеш только для одного файла

Дело было как-то вечером. Есть у меня дома контроллер wirenboard. Пока идет знакомство, наладка и отстройка, управляет светом около стола, да и меряет температуру по всему дому. Но не суть. наткнулся я на одну интересную багофичу: если пощелкать переключателями, а потом тут же обрубить питание, то эти самые переключатели после загрузки окажутся в рандомном состоянии.

Небольшое расследование со службой поддержки wirenboard показало, что дело в одном маленьком файлике. Вернее с тем, как linux с ним обращается. Верхнеуровневый софт честно в него пишет нужное, а вот линукс, желая сберечь ресурс emmc, начинает активно кешировать и сбрасывает файловый кеш тогда, когда в 99% уже поздно.

Казалось бы, фигня вопрос: засунь в крон sync и дело в шляпе. Ок, не в крон, это перебор, а после inotify и всё. Но сбрасывать всю FS ради одного файла… В общем, рецепт ниже.

# cat /etc/systemd/system/libwbmqtt-saver.service 
[Unit]
Description=Drop file cache for libwbmqtt.db if it changed

[Service]
ExecStart=/bin/bash -c 'inotifywait -qq -e modify /var/lib/wb-mqtt-gpio/libwbmqtt.db && dd of=/var/lib/wb-mqtt-gpio/libwbmqtt.db oflag=nocache conv=notrunc,fdatasync count=0 status=none'
Restart=always

[Install]
WantedBy=multi-user.target

Всё написано на скорую руку, но тем не менее, прекрасно работает. Вся магия в том, что dd открывает фаил на запись, записывает 0 байт и закрывает, сбрасывая кеш. Такую оптимизацию подсмотрел где-то в инете, мое первоначальное решение было гораздо страшнее (и нет, не покажу).

В общем, жужжит как надо.

Проверяем своего провайдера

… на вшивость. Или как проверить, что вам дают ровно столько интернета, сколько положено по тарифному плану.

В самом начале обязан раскрыть спойлер. Если обнаружится, что вам не докладывают интернета, то вы с этим ничего сделать не сможете. Ну разве что в воздух поорать чаечкой или попробовать счастья у другого провайдера. Техподдержка будет отвечать, что все в порядке и вообще так и должно быть. В общем, у вас просто нет никаких ручек для изменения ситуации.

Итак, для начала первый и единственный признак, что вам дают мало интернета: качается медленно. Но слово “медленно” очень субьективное, а нам нужна обьективность.

Итак, пойдем проверять по шагам:

Шаг первый: проверить вашу линию и устройства на ней. Ну сколько она может переварить в нынешних условиях. Откройте на том устройстве, на котором медленно, сайт speedtest.net. Почему именно его? Причина простая: все провайдеры в курсе этого сайта и специально оптимизируют свою инфраструктуру под него. Так что показанное значение скорости можно считать максимальным для данных условий.

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

Когда не надо волноваться: показометр скорости интернета регулярно показывает 85% и больше от вашего тарифного плана. Иначе говоря, если у вас тарифный план в 300 мегабит, то увидеть вы должны 260 мегабит и больше. И да, на скорость исходящего трафика особого внимания можете не обращать.

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

Шаг второй: проверяем реальную скорость. Просто берем, гуляем по интернету и качаем большие файлы. Лично я по роду увлечений иду и качаю дистрибутивы линукса. Они в меру большие, часто лежат на отдельных серверах с хорошим каналом и поэтому вполне себе подходят под такое использование.

Что не надо делать: использовать большие и популярные сайты для скачивания. Причина простая: на них обычно ограничивается скорость скачивания для одного клиента.

Для визуализации очень полезно использовать монитор загруженности системы. В windows его можно позвать по комбинации клавиш Ctrl-Shift-Esc. В MacOS он в папке Утилиты, ну а линуксоиды сами знают, где его найти.

Опять же, когда не надо волноваться: файлики качаются быстро. Скорость, которую показывает браузер или монитор, очень похожа на то, что обещает провайдер. Редкие закачки, на которых скорость не растет – сорян, но это не показатель. Интернет на самом деле так устроен.

Когда надо волноваться: что бы вы не качали, откуда бы не пробовали – всегда скорость низкая.

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

      Для начала обратите внимание на уровень крутизны левой границы. Чем она вертикальнее, тем свободнее канал. Ну или если говорить другими словами, тем меньше расстояние до сервера, откуда вы качаете. Верхняя “полочка” своей ровностью говорит о том, что скорость что-то ограничивает. В данном случае – ограничение канала. Он просто физически быстрее не умеет передавать данные. Картинка ниже показывает, что сервер далеко (скорость растет гораздо медленней), но тоже упирается в какие-то внешние ограничения.

      А теперь картинка, которую вы должны видеть в 99% случаев.

      Скорость растет и потом начинает “колбаситься” возле верхней границы тарифа. Такое поведение абсолютно нормальное. В интернете постоянно летают туда-сюда тонны данных, маршруты перестраиваются, оборудование провайдера ограничивает вашу скорость согласно тарифному плану и так далее.

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

      На что тут необходимо обратить внимание?

      1. Скорость загрузки далека от возможностей канала и тарифного плана. Но повторюсь, это не абсолютный признак – может, просто сервер далеко или перегружен.
      2. Верхний левый угол всегда содержит пик вверх, а следом яму. Вот это уже 100% признак ограничения скорости. Суть в том, что все ограничители настраивают по одной схеме: всегда есть какой-то объем данных, отдаваемых на максимальной скорости. Это очень помогает улучшить “отзывчивость” интернета. Следом яма – это ограничитель скорости понимает, что клиент вылез за границы и необходимо его “вогнать” лимиты. Высота пика и ямы может быть разная (сравните картинки выше) – это зависит от настроек шейпера.
      3. “Расколбас” скорости дальше гораздо меньше, чем при нормальном скачивании. И он никогда не перепрыгивает первый пик. При “злых” ограничителях расколбас вообще исчезает.

      Что можно сделать? Ну в общем-то только абсолютно банальные вещи:

      1. Все-таки проверьте свое оборудование и условия, в котором оно работает. Как бы вы не были уверены, но и на старуху бывает проруха. Покачайте файлики локально, погоняйте тесты.
      2. Смените сервер, откуда качаете. Совсем не факт, что выбранный (по расстоянию, национальной принадлежности и прочему) самый быстрый.
      3. Пожалуйтесь в техподдержку провайдера. Может, вы просто чего-то упустили? Например, на всех “безлимитных” тарифных планах сейчас есть приписка мелким шрифтом, что можно скачать столько-то, а дальше либо скорость режут, либо вообще в инет не пускают. Вполне вероятен ваш случай.
      4. Пожалуйтесь в соцсетях, с обязательным упоминанием провайдера. Это задействует совершенно другой канал коммуникаций с техперсоналом. Да, идиотизм, но это иногда работает
      5. Смиритесь и забейте.

      Fedora 40 Wifi cannot connect to network

      После какого-то обновления мой ноутбук стал плохо соединяться с Wifi. Ну как плохо… Регулярно стал терять сеть, ругаться на то, что не может соедениться и так далее и тому подобное. Так как у меня идет ремонт и я регулярно перетряхиваю сеть, то я грешил на точки доступа, линукс-сервер, выступающий роутером и на прочее, что могло повлиять.

      Однако через некотрое время индеец зоркий глаз стал замечать, что на WiFi жалуется только ноутбук на Fedora. Windows, MacOS и андроиды и iOS цеплялись хорошо и никаких призывов не выдавали. И это бы продолжалось еще долго, но вчера линукс сказал “все, я больше не хочу соединяться с сетью”. Совсем.

      Симптомы простые: ноутбук видит WiFi, соединяется, но через 45 секунд происходит тайм-аут DHCP и он отсоединяется. Установка статического адреса не помогает. Он перестает отваливаться, но пакеты никуда не ходят.

      Проверка с помощью tcpdump показала, что в общем-то на это есть резоны: в канале было тихо. Причем настолько тихо, что даже запущенный с ноутбука ping не было видно. Тут я наконец-то понял, что проблемы именно на моей стороне.

      Первым делом я решил, что проблема в сетевой. Воткнул USB, она со второго или третьего раза зацепилась. Тут бы мне насторожиться, но я пропустил этот момент. Начал играться с настройками WIFi на роутере. Ну так отключать/включать MIMO и прочее. Не помогло.

      Включил точку доступа на телефоне. Ноутбук мгновенно прицепился и сообщил, что все в порядке.

      То есть у ноутбука проблемы именно с моей точкой доступа. Стал разбираться. Ни каналы, ни смены настройки меш-сети – ничего не помогало. В веб-панели роутера я видел, что ноутбук соединяется и потом через некоторое время отваливается.

      Так я сделал вывод, что железная часть работает. Дело в софте. И тут мне повезло запустить еще раз tcpdump как раз во время той самой паузы до таймаута. И внезапно я увидел бегающие туда-сюда пакетики, характерные для любой сети. Точно софт!

      Стал разбираться. Оказалось, что добрые идиоты, пишущие Network Manager, где-то налажали в последних апдейтах и теперь мак-адрес меняется так, что он вводит сетевую в кому (или что-то еще в потрохах, но разбираться было лень). Ок, значит проблема простая: надо найти, где это выключается и дело в шляпе!

      А вот тут возникла проблема. Оно нигде не выключается. Все найденные рецепты про wifi.cloned-mac-address и ethernet.cloned-mac-address не дали ровном счетом ничего. Повторяю: николай, иван, хартон, ульяна, яна. Так как дело было вечером, я решил не мучаться и вернуться на шаг назад. Говоря другими словами, вырубить нафиг NetworkManager.

      Первым делом отвязываем wpa_supplicant от NM, хардкодим интерфейс и выключаем сам NM

      # cat /usr/lib/systemd/system/wpa_supplicant.service
      [Unit]
      Description=WPA supplicant
      Before=network.target
      Wants=network.target
      #After=dbus.service
      
      [Service]
      #Type=dbus
      Type=oneshot
      RemainAfterExit=yes
      #BusName=fi.w1.wpa_supplicant1
      EnvironmentFile=-/etc/sysconfig/wpa_supplicant
      ExecStart=/usr/sbin/wpa_supplicant -B -i wlp0s20f3 -c /etc/wpa_supplicant/wpa_supplicant.conf
      # -u $INTERFACES $DRIVERS $OTHER_ARGS
      ExecStart=/usr/sbin/dhclient wlp0s20f3
      ExecStop=/usr/bin/killall -q wpa_supplicant
      ExecStop=/usr/bin/killall -q dhclient
      [Install]
      WantedBy=multi-user.target
      
      # systemctl daemon-reload
      # systemctl disable NetworkManager.service
      # systemctl stop NetworkManager.service

      Потом конфигурируем ручками wpa_supplicant

      # cat /etc/wpa_supplicant/wpa_supplicant.conf 
      ctrl_interface=/var/run/wpa_supplicant
      ctrl_interface_group=wheel
      
      network={
          ssid="multik"
          psk="VERY_SECRET_PASSWORD"
      }

      И рассказываем системе, что делать с сетью (ну и чтобы dhclient не ругался)

      # cat /etc/sysconfig/network-scripts/ifcfg-wlp0s20f3 
      DEVICE="wlp0s20f3"
      ONBOOT=yes
      NETBOOT=yes
      IPV6INIT=yes
      BOOTPROTO=dhcp
      HWADDR="68:3e:26:b0:b1:93"
      NAME="wlp0s20f3"
      NM_CONTROLLED="no"

      И самым последним шагом правим конфиг NSS, чтобы он не страдал херней, ибо всякие resolvd тоже ушли гулять вслед за NM

      # cat /etc/nsswitch.conf 
      ....
      #hosts:      files mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] myhostname dns
      hosts:      files myhostname dns
      ....

      Все. Можно перезапустить сервисы, а можно отребутиться для проверки. Сеть есть, внезапно никто ни на что не жалуется и не отваливается.

      Update: проверил на live образах. Все отлично коннектится и радуется жизни. То есть это именно обновления как-то и где-то что-то наковыряли

      Фильтр анонсируемых адресов

      Продолжаю делать записи для себя. На этот раз потребовалось отфильтровать роуты, отдаваемые другим. OSPF для этого не подходит: стандарт такого попросту не предусматривает. Значит, переключаемся на BGP. Минимальный конфиг для FRR

      !
      router bgp 65000
       bgp router-id 10.0.0.2
       no bgp ebgp-requires-policy
       neighbor 10.0.0.3 remote-as 65000
       !
       address-family ipv4 unicast
        redistribute connected
        redistribute static
        neighbor 10.0.0.3 next-hop-self
       exit-address-family
      exit
      !

      На другой стороне есть адрес 6.7.8.9, котрый не должен попасть на этот роутер.

      !
      ip route 6.7.8.9/32 10.1.0.254
      !
      router bgp 65000
       bgp router-id 10.0.0.3
       no bgp ebgp-requires-policy
       neighbor 10.0.0.2 remote-as 65000
       !
       address-family ipv4 unicast
        redistribute connected
        redistribute static
        neighbor 10.0.0.2 next-hop-self
        neighbor 10.0.0.2 prefix-list nobad-out out
       exit-address-family
      exit
      !
      ip prefix-list nobad-out seq 5 deny 6.7.8.9/32 le 32
      ip prefix-list nobad-out seq 10 permit 10.1.0.0/24 le 32
      !

      Проверяем

      router2# show ip route bgp
      Codes: K - kernel route, C - connected, S - static, R - RIP,
             O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
             T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
             f - OpenFabric,
             > - selected route, * - FIB route, q - queued, r - rejected, b - backup
             t - trapped, o - offload failure
      
      B>* 10.1.0.0/24 [200/0] via 10.0.0.3, ens19, weight 1, 00:16:06

      ВНИМАНИЕ: правка “на живую” permit-list не приведет к перечитыванию правил на другой стороне. Надо вручную в router bgp прицепить-отцепить их. Почему так – хз.

      Вариант лечения: не важно где сказать clear ip bgp 10.0.0.3 (ессно, на передатчике адрес приемника и наоборот), это сбросит сессию bgp и заставит перечитать роуты.

      MultiWAN без боли и шума

      О, сколько боли в слове MultiWAN! Стоит погуглить что-нибудь типа “есть два провайдера, как сделать так, чтобы можно было пользоваться одновременно или использовать второй как бекапный”, так сразу высыпается куча советов про метрики, маркировку трафика с помощью iptables и так далее. Правда, в последнее время все поутихло, но это потому, что в большинстве прошивок для домашних роутеров наконец-то доделали этот функционал.

      Но я-то другой! У меня закидоныпросы! Вот прямо сейчас мне надо разрулить аж трех “провайдеров” на одной точке. Плюс пустить один из адресов через одного провайдера… В общем, попробовал я сначала натыкать галочек в любимом кинетике, потом сдался в сторону {pf|opn}sense, но и так не преуспел… Нет, наверняка можно было допинать, но я устал и сдался.

      Итак, первоначальные условия. Есть три провайдера: через сотовую связь, ADSL и GPON. Работают одновременно. Рядом стоит сервер, который легко потянет кучу виртуалок. Необходимо клиентов (то есть меня) пускать в интернет, при этом приоритет gpon, adsl, сотик. Но один из служебных маршрутов должен уходить через ADSL. Вроде бы просто, да?

      Для начала я вообще решил проверить, а возможно ли это без боли. Для этого я сделал стенд из трех виртуалок. Две я обозвал router1 и router2, а клиента – естественно client.

      internet - (ens18)router1(ens19) - 10.0.0.1 - network
      internet - (ens18)router2(ens19) - 10.0.0.2 - network
                        client (ens19) - 10.0.0.3 - network

      Я опускаю настройку роутеров и клиента. Все друг друга видят, на роутерах включен форвард пакетов и SNAT, в общем, все работает на ручном приводе хорошо. Теперь необходима автоматика.

      Ставлю на каждый хост FRR. Редактирую /etc/frr/daemons на предмет включения ospfd и запускаю. Далее скармливаю на всех хостах одну и ту же конструкцию, только меняю router id

      !
      interface ens18
       ip ospf passive
      exit
      !
      interface ens19
       ip ospf dead-interval 30
      exit
      !
      router ospf
       ospf router-id 10.0.0.1
       network 10.0.0.0/24 area 0.0.0.0
      exit
      !

      Никакой авторизации и прочих заморочек. Поднимаю OSPF, запрещаю ему спамить в сторону провайдера и говорю, что все в сети 10/24 – наше. Проверяю, что роутеры видят друг друга.

      client# show ip ospf neighbor 
      
      Neighbor ID     Pri State           Dead Time Address         Interface                        RXmtL RqstL DBsmL
      10.0.0.1          1 Full/DR           27.376s 10.0.0.1        ens19:10.0.0.3                       0     0     0
      10.0.0.2          1 Full/Backup       28.362s 10.0.0.2        ens19:10.0.0.3                       0     0     0
      

      В принципе, теперь можно расставлять роуты куда надо и радоваться жизни. Но мне-то надо рулить default роутом. И тут засада: по-умолчанию, чтобы не расхреначить все, роутеры по умолчанию дропают роуты на 0.0.0.0/0. Можно, конечно, воспользоваться хаком имени OpenVPN и анонсировать роуты 0.0.0.0/1 и 128.0.0.0/1, но это не наш метод. Немного погуглив, выянил, что достаточно добавить default-information originate always в секцию router ospf и все получится. Дескать, я edge/border/ваще_крутой роутер и ходи через меня.

      client# show ip ospf route 
      ============ OSPF network routing table ============
      N    10.0.0.0/24           [1] area: 0.0.0.0
                                 directly attached to ens19
      
      ============ OSPF router routing table =============
      R    10.0.0.1              [1] area: 0.0.0.0, ASBR
                                 via 10.0.0.1, ens19
      
      ============ OSPF external routing table ===========
      N E2 0.0.0.0/0             [1/1] tag: 0
                                 via 10.0.0.1, ens19

      И действительно, стоило мне такое сказать, как client тут же все увидел и обновил. Добавляю ту же строку в конфиг второго. Вуаля!

      root@client:~# ip r
      default nhid 22 proto ospf metric 20 
      	nexthop via 10.0.0.1 dev ens19 weight 1 
      	nexthop via 10.0.0.2 dev ens19 weight 1 
      10.0.0.0/24 dev ens19 proto kernel scope link src 10.0.0.3 

      Клиент прописал себе оба роута и казалось бы наступила красота. И даже все заработало, как положено: если один из роутеров исчезал или я дропал на нем интерфейс, то соответствующий роут исчезал тоже. И тут я познал боль (правда, небольшую, на уровне фейспалма)

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

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

      client# show ip ospf neighbor 
      
      Neighbor ID     Pri State           Dead Time Address         Interface                        RXmtL RqstL DBsmL
      10.0.0.1          1 Full/DR           24.884s 10.0.0.1        ens19:10.0.0.3                       0     0     0
      10.0.0.2          1 Full/Backup       25.013s 10.0.0.2        ens19:10.0.0.3                       0     0     0
      10.1.0.4          1 Full/Backup       22.051s 10.1.0.4        ens20:10.1.0.3                       0     0     0
      
      client# 
      
      client# show ip ospf border-routers 
      ============ OSPF router routing table =============
      R    10.0.0.1              [1] area: 0.0.0.0, ASBR
                                 via 10.0.0.1, ens19
      R    10.0.0.2              [1] area: 0.0.0.0, ASBR
                                 via 10.0.0.2, ens19
      R    10.1.0.4              [1] area: 0.0.0.0, ASBR
                                 via 10.1.0.4, ens20
      
      root@client:~# ip r
      default nhid 79 proto ospf metric 20 
      	nexthop via 10.0.0.1 dev ens19 weight 1 
      	nexthop via 10.0.0.2 dev ens19 weight 1 
      	nexthop via 10.1.0.4 dev ens20 weight 1 
      10.0.0.0/24 dev ens19 proto kernel scope link src 10.0.0.3 
      10.1.0.0/24 dev ens20 proto kernel scope link src 10.1.0.3 

      Как видно, теперь у меня аж три некстхопа. Ходи – не хочу.

      Проверяю, как OSPF на client видит интерфейсы

      client# show ip ospf interface 
      ens19 is up
        ifindex 3, MTU 1500 bytes, BW 4294967295 Mbit <UP,BROADCAST,RUNNING,MULTICAST>
        Internet Address 10.0.0.3/24, Broadcast 10.0.0.255, Area 0.0.0.0
        MTU mismatch detection: enabled
        Router ID 10.0.0.3, Network Type BROADCAST, Cost: 1
        Transmit Delay is 1 sec, State DROther, Priority 1
        Designated Router (ID) 10.0.0.1 Interface Address 10.0.0.1/24
        Backup Designated Router (ID) 10.0.0.2, Interface Address 10.0.0.2
        Saved Network-LSA sequence number 0x80000004
        Multicast group memberships: OSPFAllRouters
        Timer intervals configured, Hello 10s, Dead 30s, Wait 30s, Retransmit 5
          Hello due in 6.368s
        Neighbor Count is 2, Adjacent neighbor count is 2
      ens20 is up
        ifindex 4, MTU 1500 bytes, BW 4294967295 Mbit <UP,BROADCAST,RUNNING,MULTICAST>
        Internet Address 10.1.0.3/24, Broadcast 10.1.0.255, Area 0.0.0.0
        MTU mismatch detection: enabled
        Router ID 10.0.0.3, Network Type BROADCAST, Cost: 1
        Transmit Delay is 1 sec, State DR, Priority 1
        Designated Router (ID) 10.0.0.3 Interface Address 10.1.0.3/24
        Backup Designated Router (ID) 10.1.0.4, Interface Address 10.1.0.4
        Multicast group memberships: OSPFAllRouters OSPFDesignatedRouters
        Timer intervals configured, Hello 10s, Dead 30s, Wait 30s, Retransmit 5
          Hello due in 0.712s
        Neighbor Count is 1, Adjacent neighbor count is 1

      Все правильно, по умолчанию для ethernet cost 1.

      Добавляю на клиенте на интерфейс ens19, который смотрит на первые два роутера, опцию ip ospf cost 100. Согласно мануалам, это должно сказать, что туда надо трафик отправлять в последнюю очередь (ведь 100>1)

      Проверяю. Вот это было до.

      root@client:~# ip r
      default nhid 87 proto ospf metric 20 
      	nexthop via 10.0.0.1 dev ens19 weight 1 
      	nexthop via 10.0.0.2 dev ens19 weight 1 
              nexthop via 10.1.0.4 dev ens20 weight 1
      10.0.0.0/24 dev ens19 proto kernel scope link src 10.0.0.3 
      10.1.0.0/24 dev ens20 proto kernel scope link src 10.1.0.3 

      Включаю ip ospf cost

      root@client:~# ip r
      default nhid 91 via 10.1.0.4 dev ens20 proto ospf metric 20 
      10.0.0.0/24 dev ens19 proto kernel scope link src 10.0.0.3 
      10.1.0.0/24 dev ens20 proto kernel scope link src 10.1.0.3 

      Проверяю, что вообще-то роуты вернутся, если что-то случится с router3

      root@client:~# ip link set ens20 down
      root@client:~# ip r
      default nhid 95 proto ospf metric 20 
      	nexthop via 10.0.0.1 dev ens19 weight 1 
      	nexthop via 10.0.0.2 dev ens19 weight 1 
      10.0.0.0/24 dev ens19 proto kernel scope link src 10.0.0.3 

      Работает, прямо как я и задумал. Теперь садим на каждый роутер по скрипту, который будет проверять доступность интернета. Таких скриптов уйма на любой вкус, цвет и запах. Можно вообще какой-нибудь zabbix присобачить. Но главное, чтобы они шли и пускали два скриптика

      root@router3:~# cat enable.sh 
      #!/bin/bash
      cat << EOF | /usr/bin/vtysh
      conf t
      router ospf
      default-information originate always
      exit
      exit
      exit
      EOF
      
      root@router3:~# cat disable.sh 
      #!/bin/bash
      cat << EOF | /usr/bin/vtysh
      conf t
      router ospf
      no default-information originate always
      exit
      exit
      exit
      EOF

      Их названия говорят сами за себя, как и то, что они делают. Позапускал их, проверил, что таблица роутинга перестраивается, как и положено, согласно правилам.

      Теперь последнее: пустить определенный маршрут через определенный роутер. Пусть это будет 1.2.3.4/32 на router2. Это вообще просто. Просто создаем статический роут и просим распростанить статику.

      root@router2:~# vtysh
      
      Hello, this is FRRouting (version 8.1).
      Copyright 1996-2005 Kunihiro Ishiguro, et al.
      
      router2# conf t
      router2(config)# ip route 1.2.3.4/32 192.168.1.1
      router2(config)# router ospf
      router2(config-router)# redistribute static

      И все получается согласно заветам лучших сетевиков.

      root@client:~# ip r
      default nhid 113 via 10.1.0.4 dev ens20 proto ospf metric 20 
      1.2.3.4 nhid 115 via 10.0.0.2 dev ens19 proto ospf metric 20 
      10.0.0.0/24 dev ens19 proto kernel scope link src 10.0.0.3 
      10.1.0.0/24 dev ens20 proto kernel scope link src 10.1.0.3 

      Теперь осталось развести router1 и router2 по разным подсетям, донастроить точно так же, как и router3, забекапить все и забыть до появления новых вводных.

      А, да. Ну и всех жаждущих интернета отправить на client. Теперь точно все.

      Видеонаблюдение, часть 1

      В целях покупки домика загорелось мне устроить видеонаблюдение. И чтобы потом как в фильмах “вот преступник, увеличь кадр. еще! ага, попался!”. У меня преступников не ожидается, но хотелку осуществить очень охота.

      И в процессе погружения в мир видеонаблюдения оказалось, что все в нем совсем не так просто. Вернее наоборот, просто, но совершенно перпендикулярно сознанию обычного ИТшника.

      В начале было самое простое: система будет аналоговая или цифровая? В пользу первой говорит ровно два фактора: сейчас она очень (подчеркиваю очень) дешевая и она базируется на отработанных решениях. Все давно изучено, вылизано и понятно. Самое простое решение: купить валяющийся на складе готовый комплект, раскидать кабеля и успокоиться.

      Но у аналогов есть и минус: от каждой камеры нужен прямой кабель до регистратора. 16 камер? 16 линков на коаксиале. В общем, не мой размерчик от слова совсем.

      Значит, цифровая. Тем более, что ethernet с wifi у меня точно будет в каждом угле.

      Открываю браузер, иду в магазин и немного охреневаю от изобилия камер со всякими аббревиатурами. А цены скачут на три порядка. Что делать, куда бежать?

      Первое условие “никаких облаков” сразу отсеивает большую половину камер. Эти камеры потому и дешевы, что сливают китайцам и корейцам все, что можно слить. Новомодным системам надо же на чем-то обучаться? Да и безопасность таких камер хромает на обе ноги – достаточно погуглить и вы обнаружите кучу кредов на любой вкус: хоть напрямую, хоть через “облако”.

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

      Пока камеры ехали, я принялся изучать, чем же их обслуживать. Или, говоря другими словами, DVR, NVR или ip-видеорегистратор. Тут я тоже сразу задрал планку “работает под linux, управление через браузер”. Казалось бы, софта на рынке дофига и больше – бери и пробуй.

      Ан, нет. 99% софта – это откровенные поделки, лишь бы было. Особенно этим отличаются отечественные производители. Ни инструкций по настройке, ни поддержки чего-то более-менее распространенного… ничего вообще. Я ставил, смотрел, плевался и удалял. “серверные” версии, которые требуют qtgui? да легко!

      Где-то тут приехали и сами камеры, сразу же добавив много интересных аспектов. Например, некоторые камеры сами по себе видеорегистраторы. Можно вставить sd карту, обрисовать зоны для детектора движений и вуаля – все заработает.

      Но в итоге самым важным оказалось совершенно другое. Формат, в котором передается видео. MJPEG, H264 и самый моднявый, H265 с плюсиками и буквами на конце. Внезапно для меня это стало могильным камнем для 99,99% видеорегистраторов. Дело в том, что чем моднее формат, тем меньше он требует диска для хранения. В проспектах буржуев я встречал, что H265 S+ требует до 70% меньше места, чем H264.

      В итоге с банальной задачей “смотри в камеры, если обнаружишь движение, пиши на диск” справился только один видеорегистратор – AgentDVR. Все остальные, включая широко известный ZoneMinder – тупо крешились, жрали проц и память и так далее и тому подобное. Отдавать им такую важную задачу – глупость высшего уровня.

      Выше – скриншот с тестовой инсталляции AgentDVR. Три камеры – 4МП, 2МП и 2МП. Пишется по детектору движения. Как видите, за 11 дней сожрало 120 гигов. И процессор совершенно не нагружен. Было бы прелестно, если бы была хоть какая-то интеграция со сторонними системами. Нет, она вроде заявлена, но за помесячную денежку. Не подходит – я готов заплатить за софт, но единоразово.

      Увидев подобные цифры потребления, я воспрял духом. Никаких петабайт на глубину в неделю не нужно – хватит и обычных объемов! А их, как вы понимаете, есть у меня!

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

      И тут очередная засада. Как выбрать видеорегистратор? Ни одна собака не пишет, сколько камер он может понятнуть. Вместо этого вовсю рекламируют, сколько потоков с каким разрешением он может одновременно отображать. Но мне-то это не надо…

      Когда ко мне приехала очередная пачка железок, то тайна оказалась не такой-то уж и тайной. У каждого приличного видеорегистратора есть параметр “максимальный входной поток”. Он измеряется в мегабитах. И чтобы подсчитать, сколько камер потянет регистратор, надо просто принять “1 мегапиксел камеры = 1 мегабит на регистраторе”. И не смотрите, что 4МП камера выдает по сети всего 600-800 килобайт в секунду – это не те потоки, не итшные. В итоге для трех камер на 4, 2 и 2 мегапикселя нужен регистратор, умеющий переваривать поток в 9+ мегабит. Почему не 8? Оставьте небольшой процент на всякие просадки, усушки и утруски.

      С дисками вообще все просто: подойдет абсолютно любой. Но если деньги есть, то надо взять именно для систем видеонаблюдения. Во-первых, они все медленные, 5200, а значит холодные и тихие. А во-вторых, в них льется спецпрошивка, которая оптимизирована для постоянной записи в кучу потоков. Мелочь, но по словам бывалых, на нагруженных системах увеличивает срок службы с года до трех практически гарантированно.

      Вот мой, купленный на пробу от tiandy. Два диска, 200МБ входного. Усб справа для ориентира в размерах.

      Сами регистраторы тоже разные. Самые простые умеют просто писать поток с камеры на диск. Платы таких на али можно найти от 1500 рублей. У регистраторов покруче добавляется возможность писать на внешние диски, в случае каких-то событий отправлять письма, включать что-то внешнее и прочее подобное.

      И тут меня настигла первая засада: у “дешевых” регистратов вся аналитика (распознование человек-машина, границы и так далее) ложится исключительно на камеры. Если камера не умеет (или железка не знает про возможности камеры) – то регистратор напишет “ой, и я тоже не могу”. Вот мой, к примеру, не может.

      Вторая засада та же, что и с отечественными: документации нет. Вообще. Пара-тройка страничек с общими телодвижениями и все. Поначалу я думал, что это мне так повезло. Но нет, даже у хваленого HikVision та же фигня.

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

      Даешь звук в vmware

      Я как-то привык к заикающемуся и запинающемуся звуку внутри виртуалки. Ну сколько не пробовал разных рецептов, помогали … не очень. А тут внезапно выдался свободный часик и я решил немного погуглить. Оказывается, проблема известная, только не все знают про ее решение.

      Скопировал файлик, заменил значения … и вуаля! Звук снова в наличии.

      Привожу медиатеку к единому стилю

      В предидущем посте я прошелся по библиотеке и расставил везде теги и обложки. Но теперь надо решить другую проблему: у меня есть mp3, m4a и flac файлы. Причем я точно знаю, что некоторые flac и m4a получены из mp3. Да, источники музыки были не всегда адекватными …

      Поэтому шаг номер раз: приводим всю библиотеку в mp3 формат. То, что из m4a и flac перезапишутся mp3 – пофиг

      find . -type f -name "*.m4a" | parallel 'ffmpeg -y -i {}  -map_metadata 0 -codec:a libmp3lame -qscale:a 1 {.}.mp3'
      
      find . -type f -name "*.flac" | parallel 'ffmpeg -y -i {}  -map_metadata 0 -codec:a libmp3lame -qscale:a 1 {.}.mp3'

      Теперь можно грохнуть “оригиналы”. И совсем маленький шаг: необходимо избавиться от дубликатов. Так как источников было много, то и для некоторых популярных песен было аж до 5 вариантов. Пишу маленький скрипт, который удаляет все дубликаты меньшего размера (да, буду считать, что бОльший размер означает лучшее качество).

      #!/bin/bash
      
      IFS=$(echo -en "\n\b")
      
      function traverse() { 
          # lets find copies in directory and i dont want use .m?? in search
          for file in $(ls -1 ${1} |grep -e \(1\).mp3 -e \(2\).mp3 -e \(3\).mp3 -e \(4\).mp3 -e \(5\).mp3) 
          do
              l="${1}/${file%????????}*" # cut (X).mp3 from file name
              # delete all files except first and biggest
              ls -1S ${l} | tail -n +2 | xargs -d '\n' rm -f
              # Now rename file. Leave mv alone for errors "the file is same" - its working indicator for me :)
              ffin="${l%?}.mp3"
              mv  $l $ffin        
          done
          # now lets find another directory to deep in
          for file in $(ls "$1")
          do
              if [[ -d ${1}/${file} ]]; then
                  traverse "${1}/${file}"
              fi
          done
      }
      
      function main() {
          traverse "$1"
      }
      
      main "$1"
      

      И натравливаем его на библиотеку. Я специально не стал обрамлять вокруг mv, что бы хоть что-то выводило во время работы, поэтому сообщения типа mv: '/mnt/swamp/Reloaded//松居慶子/Dream Walk/04 Fire in the Desert.mp3' and '/mnt/swamp/Reloaded//松居慶子/Dream Walk/04 Fire in the Desert.mp3' are the same file стали для меня индикатором, что скрипт работает.

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

      Навожу порядок в музыке

      Довольно долго я таскаю с собой архив музыки. Первые треки в нем датируются аж 1995 годом. Естественно, что за все это время внутри образовалась каша. Я много раз пытался подойти к этой свалке, что бы разгрести ее содержимое и разложить все по полочкам. Однако регулярно обламывался из-за банальной лени: все-таки раскидать почти 100 тысяч файлов нужно адское терпение.

      Ситуацию усложняло то, что куча файлов имело очень говорящие названия типа 3.mp3. Естественно, каких-либо тегов тоже ожидать не приходилось. Ну вот просто как-то понравилась мне песенка, я ее и забросил в архив …

      Наконец в очередной раз я подошел к этой свалке. Тыкался, тыкался, смотрел на всякие редакторы тегов и горестно вздыхал. Пока не решил погуглить, как можно для всего этого поиспользовать всякие шазамы и прочие новомодные (почти) штучки. И вуаля!

      https://picard.musicbrainz.org/

      Оставлю эту ссылку отдельной строкой. Жрет mp3, ищет по аудиотпечатку что же это за трек и заполняет теги, добавляет обложку и раскладывает получившееся красиво. Я в совершеннейшем восторге. На тестовой выборке в 7 тыщ файлов не нашла соответствие только для 3. Но их никто не знает, ни яндекс, ни яблоки. Мелочь …

      Bitwarden -> KeePassXC

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

      Не то, что бы мне жалко денег, но заводить какой-то странный bitcoin кошелек на не менее странных биржах мне стремно. А оплата карточкой через paypal не доступна, ибо они поддерживают нацистов и типа санкции.

      Сначала я подумал поднять свой сервер для него, благо есть аж два варианта. Но реально, как-то стало очень лень. Решил попробовать KeePassXC. Нашел репу https://github.com/davidnemec/bitwarden-to-keepass, сделал три шага по мануалу и вуаля – оно все заработало и заработало подозрительно легко. И даже клиент не такой вырвиглазный, каким я его помню …

      OS X странный   login item

      Пробегал мимо настроек, решил на всякий случай заглянуть в то, что у меня пускается автоматом.  Settings-General-Login Items, а там такое

      Что за ln? При нажатии на значок информации честно перекидывает на /bin/ln. Троян?

      $ codesign -dvvv /bin/ln
      Executable=/bin/ln
      Identifier=com.apple.ln
      Format=Mach-O universal (x86_64 arm64e)
      CodeDirectory v=20400 size=453 flags=0x0(none) hashes=9+2 location=embedded
      Platform identifier=14
      Hash type=sha256 size=32
      CandidateCDHash sha256=da717c2e8dc49817f70f208029b3533b4c9cdb2c
      CandidateCDHashFull sha256=da717c2e8dc49817f70f208029b3533b4c9cdb2ceacfa90a43b19009331880fb
      Hash choices=sha256
      CMSDigest=da717c2e8dc49817f70f208029b3533b4c9cdb2ceacfa90a43b19009331880fb
      CMSDigestType=2
      Launch Constraints:
      	None
      CDHash=da717c2e8dc49817f70f208029b3533b4c9cdb2c
      Signature size=4442
      Authority=Software Signing
      Authority=Apple Code Signing Certification Authority
      Authority=Apple Root CA
      Signed Time=5 Nov 2022, 04:23:08
      Info.plist=not bound
      TeamIdentifier=not set
      Sealed Resources=none
      Internal requirements count=1 size=60
      

      Нет, не троян. Уже лучше. Значит ищем в {~}/Library/LaunchAgents то, что под это маскируется. Оказывается, это Docker Desktop такой херней развлекается

      $ cat com.docker.socket.plist 
      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
      <plist version="1.0"><dict><key>KeepAlive</key><false/><key>Label</key><string>com.docker.socket</string><key>ProcessType</key><string>Background</string><key>Program</key><string>/bin/ln</string><key>ProgramArguments</key><array><string>/bin/ln</string><string>-s</string><string>-f</string><string>/Users/kiltum/.docker/run/docker.sock</string><string>/var/run/docker.sock</string></array><key>RunAtLoad</key><true/></dict></plist>

      Что делать? Да ничего. При запуске Docker Desktop он просто сругается и предложит сделать эту ссылку заново. Ну или оставьте “сервис ln” включенным