Шукати в цьому блозі

вівторок, 26 серпня 2025 р.

CloudFlare Client на MikroTIK (RouterOS)

Перше, що нам знадобиться це wgcf — is an unofficial, cross-platform CLI for Cloudflare Warp. Якщо ліниво збирати вручну то можна взяти готовий реліз під свою платформу. У мене wgcf_2.2.29_linux_amd64:

$ wget -O wgcf https://github.com/ViRb3/wgcf/releases/download/v2.2.29/wgcf_2.2.29_linux_amd64
$ chmod +x wgcf

Створимо конфігурацію для CloudFlare:

$ ./wgcf register --accept-tos --name HomeVPN

При цьому буде створено файл wgcf-account.toml, який містиме первинну конфігурацію.

В тому випадку якщо вже маємо ліцензію з оплаченим акаунтом (проте це не обов'язкова умова) можна оновити конфігурацію використовуючи наявний ключ.

./wgcf update --license-key QB………………-……………………-……………30H

Проте майте на увазі, що до одного акаунта може бути прив'язано не більше п'яти пристроїв. Якщо їх більше — виконання wgcf завершиться з помилкою.

Все, що нам залишилося це згенерувати текстовий файл конфігурації, щоб використовувати в подальшому наведені в ньому значення:

$ ./wgcf generate
2025/08/26 07:58:59 Using config file: wgcf-account.toml
2025/08/26 07:59:00 Successfully generated WireGuard profile: wgcf-profile.conf

Тепер ми маємо wgcf-profile.conf:

$ cat wgcf-profile.conf
[Interface]
PrivateKey = AGX……………………………………………………………………………………………………1g=
Address = 172.…….….…/32, 2606:…………:………:…………:…………:…………:…………:…………/128
DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
MTU = 1280
[Peer]
PublicKey = bmX…………………………………………………………………………………………………gyo=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = engage.cloudflareclient.com:2408

В першу чергу нас цікавитиме параметр PrivateKey.

Можемо приступити до налаштування MikroTIK. Створюємо інтерфейс клієнта:

/interface wireguard add listen-port=13231 mtu=1290 name=cloudflare-warp private-key="AGX……………………………………………………………………………………………………1g="

Налаштовуємо peer-параметри, всі значення беремо з wgcf-profile.conf:

/interface wireguard peers add allowed-address=0.0.0.0/0,::/0 endpoint-address=engage.cloudflareclient.com endpoint-port=2408 interface=cloudflare-warp name=cloudflare-peer public-key="bmX…………………………………………………………………………………………………gyo="
Ну і далі доволі стандартні кроки:
/interface list add comment=Internet name=INTERNET
/interface list member add interface=cloudflare-warp list=INTERNET
/ip firewall nat add action=masquerade chain=srcnat out-interface=cloudflare-warp
/routing table add disabled=no fib name=to-cloudflare
/ip address add address=172.…….….…/30 interface=cloudflare-warp
/ipv6 address add address=2606:…………:………:…………:…………:…………:…………:…………/128 advertise=no interface=cloudflare-warp
/ip route add dst-address=0.0.0.0/0 gateway=172.…….….1 routing-table=to-cloudflare
/ip firewall address-list add address=192.168.88.254 comment=og-home list=TO-CF-SRC
/ip firewall mangle add action=mark-connection chain=prerouting connection-mark=no-mark dst-address-list=TO-CF-SRC in-interface-list=LAN new-connection-mark=CF-conn
/ip firewall mangle add action=mark-connection chain=prerouting connection-mark=no-mark in-interface-list=LAN new-connection-mark=CF-conn src-address-list=TO-CF-SRC
/ip firewall mangle add action=mark-routing chain=prerouting connection-mark=CF-conn in-interface-list=LAN new-routing-mark=to-cloudflare
Ну от начебто і все. Всі інші налаштування — на власний самак ;)

вівторок, 18 лютого 2025 р.

Обмеження швидкості на етапі видачі ip-адреси DHCP-сервером в MikroTIK

Час від часу було необхідно обмежити швидкість тим чи іншим клієнтам локальної мережі, які отримують адресу по DHCP.

Що робили?

По-перше, створювали чергу для локальної мережі, наприклад так:

/queue simple add burst-limit=200M/200M burst-threshold=2M/2M burst-time=5s/5s max-limit=198M/198M name=lan queue=pcq-upload-src/pcq-download-dst target=bridge-local total-queue=pcq-dst-src

По-друге, фіксували за mac-адресою ту чи іншу ip-адресу. По-третє, створювали чергу, яку через parent підв'язували до створеної черги локальної мережі і обмежували швидкість для саме цієї ip-адреси.

Така схема робоча, але не дуже зручна, коли треба обмежити швидкість, скажемо так, масово.

Припустимо купуємо у провайдера 100 мегабіт. У нас 10 робочих місць. Задача - кожному роздати по 10 мегабіт.

Звісно можна зафіксувати адреси, а можна…

Варіант 1. Старе рішення.

Перший варіант, який приходить на думку: обійти таблицю leases і під кожну виділену ip-адресу створити відповідне правило в черзі. Це вирішується якось так (позичено і перероблено з форуму MikroTIK):

/ip dhcp-server lease
:foreach x in=[find] do={
 
    # grab variables for use below
    :local leaseaddr ([get $x address])
    :local leasemacaddr [get $x mac-address]
    :local leasehostname [get $x host-name]
    :local leasename [get $x comment]
    :local queuecomment

    :local minlimit 192.168.100.20
    :local maxlimit 192.168.100.100
 
    :local leaseinqueue false
 
    /queue simple
    :foreach y in=[find] do={
 
        #grab variables for use below
        :local queuetargetaddr [get $y target]
        :set queuecomment [get $y comment]
 
        # Isolate information  from the comment field (MAC, Hostname)
        :local queuemac [:pick $queuecomment 4 21]
        :local queuehostname [:pick $queuecomment 22 [:len $queuecomment]]
 
        # If MAC from lease matches the queue MAC then refresh the queue item
        :if ($queuemac = $leasemacaddr) do={
            # build a comment field
            :set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)

            set $y target=$leaseaddr comment=$queuecomment
            :if ($leasename != "") do= {
                set $y name=($leasename . " (" . $leasemacaddr . ")")
            } else= {
                :if ($leasehostname != "") do= {
                    set $y name=($leasehostname . " (" . $leasemacaddr . ")")
                } else= {
                    set $y name=$leasemacaddr
                }
            }
            :set leaseinqueue true
        } else= {
            # if ip exists for this lease but mac is different then update mac/hostname and reset counter
            :if ($queuetargetaddr = $leaseaddr) do={
                # build a comment field
                :set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)
 
                set $y comment=$queuecomment
                reset-counters $y
                :if ($leasename != "") do= {
                    set $y name=($leasename . " (" . $leasemacaddr . ")")
                } else= {
                    :if ($leasehostname != "") do= {
                        set $y name=($leasehostname . " (" . $leasemacaddr . ")")
                    } else= {
                        set $y name=$leasemacaddr
                    }
                }
                :set leaseinqueue true
            }
        }
    }
 
    # There was not an existing entry so add one for this lease
    :if ($leaseinqueue = false) do={
        # build a comment field
        :set queuecomment ("dtq," . $leasemacaddr . "," . $leasehostname)
        # build command
        :local cmd "/queue simple add parent=lan target=$leaseaddr max-limit=100M/100M comment=$queuecomment"
        :if ($leasename != "") do={ 
            :set cmd "$cmd name=\"$leasename ($leasemacaddr)\"" 
        } else= {
            :if ($leasehostname != "") do={
                :set cmd "$cmd name=\"$leasehostname ($leasemacaddr)\""
            } else= {
                :set cmd "$cmd name=\"$leasemacaddr\""
            }
        }
 
        # If within the range is executed
        :if ($leaseaddr >= $minlimit && $leaseaddr <= $maxlimit) do={
            :execute $cmd
        }
    }
}
 
# Cleanup Routine - remove dynamic entries that no longer exist in the lease table
/queue simple
:foreach z in=[find] do={
    :local queuecomment [get $z comment]
    :local queue1stpart [:pick $queuecomment 0 3]
    :local queue2ndpart [:pick $queuecomment 4 21]
    :if ( $queue1stpart = "dtq") do={
        :if ( [/ip dhcp-server lease find mac-address=$queue2ndpart] = "") do={
            :log info ("DTQ: Removing stale entry for MAC Address - " . $queue2ndpart)
            remove $z
        }
    }
}

Це дійсно працює. Цей скрипт можна додати в Scheduler і насолоджуватися його роботою. Звісно за необхідності варто змінити на свій смак встановлення локальної змінної cmd.

Цей метод працює на будь-яких версіях RouterOS (правда на дуже старих не перевіряв, але має працювати, бо тут нічого складного і специфічного немає.

Явним недоліком є саме необхідність використання Scheduler, щоб підтримувати черги в актуальному стані.

Про те є інший, більш елегантний метод. Більш легкий метод.

Варіант 2. Lease Script.

В WinBox (або в WebFig, кому як подобається) переходимо в IP → DHCP Server. Відкриваємо налаштування свого DHCP. Переходимо у вкладку Script. Тут у нас велике поле для Lease Script, який буде виглядати приблизно так:

:local queueName "lan-$leaseActIP-$leaseActMAC";
:if ($leaseBound = "1") do={
    :log info "DHCP Lease START: $queueName"
    :local hostName [/ip dhcp-server lease get [find where active-mac-address=$leaseActMAC && active-address=$leaseActIP] host-name]
    /queue simple add burst-limit=50M/50M burst-threshold=1M/1M burst-time=5s/5s max-limit=49M/49M total-burst-limit=50M total-burst-threshold=1M total-burst-time=5s total-limit-at=48M total-max-limit=49M total-queue=pcq-dst-src name=$queueName parent=lan target=($leaseActIP . "/32") comment="$leaseActIP [ $leaseActMAC ] $hostName";
} else={
    :log info "DHCP Lease STOP: $queueName"
    /queue simple remove $queueName
}

І все. Скрипт викликається DHCP-сервером коли він «видає» або «забирає» ip-адресу. Відповідним чином встановлюється змінн $leaseBound, коли сервер видає адресу вона дорівнює "1".

Звісно, що тут можна додати й інші умови, інші виключення, тощо. Можна зробити й іншу структуру самих черг. Але, сподіваюся, що все й без того прозоро й зрозуміло. Користуймося.

пʼятниця, 20 вересня 2024 р.

Як зробити так щоб Linux віддавав перевагу IPv4 адресації, а не IPv6?

Багато провайдерів в Україні ще не надають користувачам IPv6. В принципі, в повсякденні, користувачі цього не помічають. Але є випадки коли все-ж-таки треба отримувати доступ до тих чи інших IPv6 ресурсів. В таких випадках доводиться користуватися Hurricane Electric’s IPv6 tunnel.

З помічених недоліків такого підходу можу визначити два. По-перше, це не дуже швидко. Але це не скарга, бо врешті-решт це безкоштовне рішення. І за це рішення можна лише подякувати. А по-друге, хоч все й чудово працює, але подекуди виникають певні труднощі, коли ресурси на кшталт Google починають активно перевіряти тебе "Підтвердьте, що ви не робот".

Підозрюю, що це виникає саме тому, що за замовчуванням Linux, як в принципі і більшість операційних систем, віддає перевагу саме IPv6. Але чи можна змінити таку поведінку і, в тому випадку коли ресурс має IPv4 та IPv6 адресацію, віддавати перевагу IPv4?

Поведінка за замовчуванням: getaddrinfo та RFC 3484

Виклик getaddrinfo(3) може повернути декілька відповідей. Відповідно до RFC 3484 ці відповіді мають бути відсортовані таким чином, щоб відповідь із найвищим показником успіху була першою у списку. RFC надає алгоритм для сортування.

Цей алгоритм сортування за замовчуванням і набір правил, що стоять за ним, призводять до того, що IPv6 завжди має перевагу перед IPv4:

…
EXAMPLES
       The default table according to RFC 3484 would be specified with the following configuration file:

           label  ::1/128       0
           label  ::/0          1
           label  2002::/16     2
           label ::/96          3
           label ::ffff:0:0/96  4
           precedence  ::1/128       50
           precedence  ::/0          40
           precedence  2002::/16     30
           precedence ::/96          20
           precedence ::ffff:0:0/96  10
…

Це визначає підмережі IPv6 та їхній пріоритет. IPv4 фактично є вбудованою підмножиною IPv6, і ::ffff:0:0/96 вказує 32-розрядну мережу, яка і є IPv4 (подивіться на шпаргалку RIPE щодо префіксів адрес IPv6, щоб дізнатися більше). Це означає, що, наприклад, адреса IPv6 ::ffff:192.168.0.2 і адреса IPv4 192.168.0.2 ідентичні.

Усвідомлюючи це, тепер ми розуміємо, чому перевага буде надаватися адресам IPv6, і бачимо, як можемо легко підвищити пріоритет для IPv4. Просто перетворимо пріоритет 10 на щось на зразок 100, що є вищим за будь-що інше.

Застосування конфігурації

Щоб застосувати конфігурацію, просто відредагуємо або створимо файл /etc/gai.conf і встановимо стандартну конфігурацію зі зміненим пріоритетом для IPv4:

label  ::1/128       0
label  ::/0          1
label  2002::/16     2
label ::/96          3
label ::ffff:0:0/96  4
precedence  ::1/128       50
precedence  ::/0          40
precedence  2002::/16     30
precedence ::/96          20
precedence ::ffff:0:0/96  100

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

Переконаємося, що все працює

Простий спосіб перевірки – просто побачити, який тип IP-адреси використовується під час запиту того чи іншого веб-сайту. В цьому прикладі надсилаємо запит до my.ip.fi через IPv4, потім через IPv6, а потім використовуючи типове значення:

$ SITE=my.ip.fi; curl -4 ${SITE} && curl -6 ${SITE} && curl ${SITE}
176.104.xxx.xxx
2001:470:64xx:xxxx:xxxx:xxxx:98b7:29cc
176.104.xxx.xxx

За замовчуванням тепер IPv4 🎉

четвер, 4 липня 2024 р.

Налаштування WireGuard-сервера на Mikrotik

Раніше я був поверхнево написав про Встановлення з'єднання wireguard між Mikrotik та Linux (Debian), але є нюанс… тоді була задача поєднати швиденько Linux-хост з Mikrotik-ом, але досконало вивчати нюанси було ліньки 😢

Але от нещодавно відбулася подія яка примусила більш докладно підійти до процесу: злетів офісний vpn-сервер на базі Debian і було прийнято рішення перенести конфігурацію на RB3011. Окрім того, що було піднято сервіси L2TP/IPSec та інші, також захотілося більш докладно підійти до WireGuard…

Що сказати, незважаючи на те, що MikroTIK молодці і доволі докладно підходять до написання документації, але не все, що хочеться там є. Доводиться притягати весь попередній досвід щоб розібратися що до чого і як. Звісно, можливо, десь є більш докладне документування (я переконаний, що є), але ж то було б не настільки цікавим процесом.

Що хотілося? Хотілося створити багато клієнтів, які б підключалися по wireguard і отримували через організований тунель доступ до ресурсів та до Інтернет.

Спочатку думалося, що можна створити один wireguard інтерфейс і до нього купу малу peer-ів, але… але щось в мене пішло не так. Нормально в такій схемі захотів працювати тільки перший peer, всі хто підключалися після нього чомусь пасли задніх, хоча трафік від них в wireguard-інтерфейсі через torch я бачив. Пляски з бубном не допомогали… можливо бубен був не тієї конструкції, можливо щось інше, але прийшов врешті-решт до схеми яка не те що запрацювала, а запрацювала майже ідеально.

Далі по кроках.

По-перше, під кожного клієнта створюємо окремий wireguard-інтерфейс. При цьому слухати будемо різні порти.

/interface wireguard
add listen-port=12001 mtu=1420 name=wireguard1
add listen-port=12005 mtu=1420 name=wireguard5
add listen-port=12009 mtu=1420 name=wireguard9
add listen-port=13231 mtu=1420 name=wireguard13

Далі до кожного інтерфейса додамо адресу в мережі /30, в якій молодшу адресу й надаму інтерфейсу:

/ip address
add address=192.168.77.1/30 interface=wireguard1
add address=192.168.77.5/30 interface=wireguard5
add address=192.168.77.9/30 interface=wireguard9
add address=192.168.77.13/30 interface=wireguard13

Далі для кожного інтерфейса створимо peer-а:

/interface wireguard peers
add allowed-address=0.0.0.0/0 client-address=192.168.77.2/30 client-endpoint=NA.NB.NC.ND client-keepalive=20s interface=wireguard1 is-responder=yes name=peer-2 private-key=auto
add allowed-address=0.0.0.0/0 client-address=192.168.77.6/30 client-endpoint=NA.NB.NC.ND client-keepalive=20s interface=wireguard5 is-responder=yes name=peer6  private-key=auto
add allowed-address=0.0.0.0/0 client-address=192.168.77.10/30 client-endpoint=NA.NB.NC.ND client-keepalive=20s interface=wireguard9 is-responder=yes name=peer-10 private-key=auto
add allowed-address=0.0.0.0/0 client-address=192.168.77.14/30 client-endpoint=NA.NB.NC.ND client-keepalive=20s interface=wireguard13 is-responder=yes name=peer-10 private-key=auto

Тут NA.NB.NC.ND це ip-адреса серверної частини WireGuard.

В принципі все, що стосується налаштування саме серверної частини WireGuard ми фактично зробили. Ми створили клієнтів яким дозволили через тунель весь трафік (тобто не тільки приватні мережі, а й вихід до Інтернет).

Подивитися конфігурацію для налаштування клієнта, а також і QR-код, можна, наприклад, так:

/interface/wireguard/peers show-client-config number=[find interface=wireguard1 ]

або ж через winbox.

Тепер пару слів про налаштування файрволу. Звісно, що у кожного може бути своє бачення, але поділюся своїм. Весь файрвол, безумовно, наводити не стану, лише ту частину яка стосується саме WireGuard.

/interface list
add name=WIREGUARD
/interface list member
add interface=wireguard1 list=WIREGUARD
add interface=wireguard5 list=WIREGUARD
add interface=wireguard9 list=WIREGUARD
add interface=wireguard13 list=WIREGUARD
/ip firewall address-list
add address=192.168.77.0/24 list=WIREGUARD
/ip firewall filter
add action=accept chain=input in-interface-list=WIREGUARD
add action=jump chain=input in-interface-list=INTERNET jump-target=wireguard
add action=fasttrack-connection chain=forward connection-state=established,related hw-offload=yes
add action=accept chain=forward connection-state=established,related
add action=accept chain=forward in-interface-list=WIREGUARD out-interface-list=LAN
add action=accept chain=forward in-interface-list=WIREGUARD out-interface-list=INTRANET
add action=accept chain=forward in-interface-list=WIREGUARD out-interface-list=INTERNET
add action=accept chain=wireguard dst-port=12001 protocol=udp
add action=accept chain=wireguard dst-port=12005 protocol=udp
add action=accept chain=wireguard dst-port=12009 protocol=udp
add action=accept chain=wireguard dst-port=12013 protocol=udp
/ip firewall nat
add action=masquerade chain=srcnat out-interface-list=LAN src-address-list=WIREGUARD
add action=masquerade chain=srcnat out-interface-list=INTRANET src-address-list=WIREGUARD
add action=masquerade chain=srcnat out-interface-list=INTERNET src-address-list=WIREGUARD

Ідея, сподіваюся, є прозорою і зрозумілою, тому розжовувати що тут до чого, ну от не хочу.

От і все. В такій конфігурації клієнти (peer-и) чудово працюють паралельно, не заважаючи один одному.

Звісно, що порти та назви інтерфейсів кожен може взяти і обізвати так як йому зручно. Мені було зручно щоб був збіг з останнім октетом приватної адреси… якщо ж не вистачить то буде якось інакше.

Про налаштування кліантів на Android писати не стану там все не просто, а дуже просто: скануєте qr-код і все працює!

З очевидних недоліків такої конфігурації - дуже багато інтерфейсів і адрес, які треба прописати. Тому там де можна було введено list-и.

Очевидний плюс: простота налаштування клієнта - в переважній більшості все зводиться до простого сканування qr-кода.

вівторок, 23 квітня 2024 р.

dpkg-deb: error: archive '…skip….deb' uses unknown compression for member 'control.tar.zst', giving up

 За останні декілька днів вже два рази зіткнувся з помилкою "unknown compression for member" при встановленні deb-пакетів. Один раз це відбулося в Linux-контейнері FydeOS, другий раз в Debian Bullseye (11.9). І так, я цілком усвідомлюю, що є новіша версія Debian і там такої помилки не буде. Але що робити якщо є?

Було знайдено наступний "рецепт" (на прикладі apache-netbeans_21-1_all.deb):

$ mkdir apache-netbeans_21-1
$ cd apache-netbeans_21-1/
$ ln -s ../apache-netbeans_21-1_all.deb .
$ ar x apache-netbeans_21-1_all.deb
$ zstd -d < control.tar.zst | xz > control.tar.xz
$ zstd -d < data.tar.zst | xz > data.tar.xz
$ rm apache-netbeans_21-1_all.deb
$ ar -m -c -a sdsd apache-netbeans_21-1_all.deb debian-binary control.tar.xz data.tar.xz
$ rm debian-binary control.tar.xz data.tar.xz control.tar.zst data.tar.zst
$ sudo dpkg -i apache-netbeans_21-1_all.deb

субота, 6 квітня 2024 р.

Key is stored in legacy trusted.gpg keyring, see the DEPRECATION section in apt-key(8) for details

 Дано:

$ apt update
В кеші:1 http://raspbian.raspberrypi.org/raspbian bookworm InRelease
В кеші:2 http://archive.raspberrypi.org/debian bullseye InRelease                                                    
В кеші:3 https://download.docker.com/linux/raspbian bullseye InRelease                                               
Зчитування переліків пакунків... Виконано           
Побудова дерева залежностей... Виконано
Зчитування інформації про стан... Виконано   
1 package can be upgraded. Run 'apt list --upgradable' to see it.
W: http://raspbian.raspberrypi.org/raspbian/dists/bookworm/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.

"Ліки":

$ apt-key list | grep -A4 "trusted.gpg$"
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
/etc/apt/trusted.gpg
--------------------
pub   rsa2048 2012-04-01 [SC]
      A0DA 38D0 D76E 8B5D 6388  7281 9165 938D 90FD DD2E
uid           [невідома] Mike Thompson (Raspberry Pi Debian armhf ARMv6+VFP) <mpthompson@gmail.com>

$ sudo apt-key export 90FDDD2E | sudo gpg --dearmor -o /tmp/raspi.gpg
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).

$ file /tmp/raspi.gpg
/tmp/raspi.gpg: OpenPGP Public Key Version 4, Created Sun Apr  1 21:02:33 2012, RSA (Encrypt or Sign, 2048 bits); User ID; Signature; OpenPGP Certificate

$ sudo apt-key del 90FDDD2E
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
OK

$ sudo mv /tmp/raspi.gpg /etc/apt/trusted.gpg.d/

$ apt update
В кеші:1 http://archive.raspberrypi.org/debian bullseye InRelease
В кеші:2 https://download.docker.com/linux/raspbian bullseye InRelease                                              
В кеші:3 http://raspbian.raspberrypi.org/raspbian bookworm InRelease                                                
Зчитування переліків пакунків... Виконано        
Побудова дерева залежностей... Виконано
Зчитування інформації про стан... Виконано   
1 package can be upgraded. Run 'apt list --upgradable' to see it.

пʼятниця, 29 березня 2024 р.

Enable additional developer mode features: root file system write permission

 

Last Update: 2024-03-12

The following guide or recipe requires shell access to your FydeOS installation, therefore “developer mode” is assumed to be enabled.

In FydeOS, if you need to modify system files or perform custom operations, you must first disable root file system verification. This step is taken for security reasons, aimed at preventing system stability and security issues that could arise from unauthorized modifications. Here are the detailed instructions:

  1. Press Control + Alt + T on your FydeOS desktop to open the terminal.
  2. Type shell and hit Enter to access the shell environment.
  3. Enter sudo -i to get root permissions.
  4. Execute /usr/sbin/crossystem_mode-switch.sh disable-rootfs-verification to turn off root file system verification.
  5. Reboot your device.