Lunatik - это структура для сценария ядра Linux с Lua. Он составлен интерпретатором LUA, модифицированным для запуска в ядре; драйвер устройства (записанный в lua =)) и инструмент командной строки для загрузки и запуска сценариев и управления средами выполнения из пользовательского пространства; C API для загрузки и запуска сценариев и управления средами выполнения с ядра; и LUA API для связывающих средств ядра с сценариями LUA.
Вот пример драйвера устройства персонажа, написанного в LUA с использованием Lunatik для генерации случайных символов для печати ASCII:
-- /lib/modules/lua/passwd.lua
--
-- implements /dev/passwd for generate passwords
-- usage: $ sudo lunatik run passwd
-- $ head -c <width> /dev/passwd
local device = require ( " device " )
local linux = require ( " linux " )
local function nop () end -- do nothing
local s = linux . stat
local driver = { name = " passwd " , open = nop , release = nop , mode = s . IRUGO }
function driver : read () -- read(2) callback
-- generate random ASCII printable characters
return string.char ( linux . random ( 32 , 126 ))
end
-- creates a new character device
device . new ( driver )Установите зависимости (здесь для Debian/Ubuntu, чтобы быть адаптированным к своему распространению):
sudo apt install git build-essential lua5.4 dwarves clang llvm libelf-dev linux-headers- $( uname -r ) linux-tools-common linux-tools- $( uname -r ) pkg-config libpcap-dev m4 Скомпилируйте и установите lunatik :
LUNATIK_DIR= ~ /lunatik # to be adapted
mkdir " ${LUNATIK_DIR} " ; cd " ${LUNATIK_DIR} "
git clone --depth 1 --recurse-submodules https://github.com/luainkernel/lunatik.git
cd lunatik
make
sudo make install После этого сценарий debian_kernel_postinst_lunatik.sh из инструментов/может быть скопирован в /etc/kernel/postinst.d/ : это обеспечивает lunatik (а также необходимые для xdp LIBS) будет составлено при обновлении ядра.
sudo lunatik # execute Lunatik REPL
Lunatik 3.5 Copyright (C) 2023-2024 ring-0 Ltda.
> return 42 -- execute this line in the kernel
42
usage: lunatik [load | unload | reload | status | list] [run | spawn | stop < script > ]load : загрузка модулей ядра Lunatikunload : разгрузить модули ядра Lunatikreload : перезагрузить модули ядра Lunatikstatus : Покажите, какие модули ядра Lunatik в настоящее время загружаютсяlist : Покажите, какие среды выполнения в настоящее время работаютrun : Создайте новую среду выполнения для запуска Script /lib/modules/lua/<script>.luaspawn : Создайте новую среду времени выполнения и создайте поток для запуска Script /lib/modules/lua/<script>.luastop : Остановите среду выполнения, созданную для запуска сценария <script>default : запустите реплику (цикл Read -Eval -Print) Lunatik 3.4 основан на LUA 5.4, адаптированной для бега в ядре.
Lunatik не поддерживает арифметику с плавающей точкой, поэтому она не поддерживает __div или __pow метаметоды, а номер типа имеет только целое число подтипов.
Lunatik не поддерживает библиотеки IO и OS, а также заданные идентификаторы из следующих библиотек:
Lunatik изменяет следующие идентификаторы:
"Lua 5.4-kernel" ."/lib/modules/lua/?.lua;/lib/modules/lua/?/init.lua" .Lunatik не поддерживает Lual_stream, Lual_Execresult, Lual_FileResult, Luaopen_io и Luaopen_os.
Lunatik изменяет Lual_openlibs, чтобы удалить luaopen_io и luaopen_os.
#include <lunatik.h> int lunatik_runtime ( lunatik_object_t * * pruntime , const char * script , bool sleep ); lunatik_runtime () создает новую среду runtime затем загружает и запускает Script /lib/modules/lua/<script>.lua в качестве точки входа для этой среды. Это должно быть вызвано только из контекста процесса . Среда runtime - это объект Lunatik, который имеет состояние Луа. Объекты Lunatik - это специальные LUA UserData, которые также содержат тип блокировки и справочный счетчик. Если sleep верен , Lunatik_runtime () будет использовать мутекс для блокировки среды runtime и флага GFP_KERNEL для распределения новой памяти позже на вызовах LUNATIK_RUN (). В противном случае он будет использовать Spinlock и GFP_ATOMIC. Lunatik_runtime () открывает стандартные библиотеки LUA, присутствующие на Lunatik. В случае успеха, Lunatik_runtime () устанавливает адрес, указанный pruntime и дополнительным пространством Lua с указателем для новой созданной среды runtime , устанавливает ссылочный счетчик на 1 , а затем возвращает 0 . В противном случае он возвращает -ENOMEM , если недостаточная память доступна; или -EINVAL , если он не может загрузить или запустить script .
-- /lib/modules/lua/mydevice.lua
function myread ( len , off )
return " 42 "
end static lunatik_object_t * runtime ;
static int __init mydevice_init ( void )
{
return lunatik_runtime ( & runtime , "mydevice" , true);
} int lunatik_stop ( lunatik_object_t * runtime ); Lunatik_stop () закрывает состояние LUA, созданное для этой среды runtime и уменьшает контрольный счетчик. Как только эталонный счетчик уменьшается до нуля, выпускаются тип блокировки и память, выделенную для среды runtime . Если среда runtime была выпущена, она возвращает 1 ; В противном случае он возвращает 0 .
void lunatik_run ( lunatik_object_t * runtime , < inttype > ( * handler )(...), < inttype > & ret , ...); LUNATIK_RUN () блокирует среду runtime и называет handler , передающего связанное состояние Луа в качестве первого аргумента, за которым следует вариадические аргументы. Если штат Луа был закрыт, ret установлен с -ENXIO ; В противном случае ret устанавливается с результатом вызова handler(L, ...) . Затем он восстанавливает стек LUA и разблокирует среду runtime . Это определяется как макрос.
static int l_read ( lua_State * L , char * buf , size_t len , loff_t * off )
{
size_t llen ;
const char * lbuf ;
lua_getglobal ( L , "myread" );
lua_pushinteger ( L , len );
lua_pushinteger ( L , * off );
if ( lua_pcall ( L , 2 , 2 , 0 ) != LUA_OK ) { /* calls myread(len, off) */
pr_err ( "%sn" , lua_tostring ( L , -1 ));
return - ECANCELED ;
}
lbuf = lua_tolstring ( L , -2 , & llen );
llen = min ( len , llen );
if ( copy_to_user ( buf , lbuf , llen ) != 0 )
return - EFAULT ;
* off = ( loff_t ) luaL_optinteger ( L , -1 , * off + llen );
return ( ssize_t ) llen ;
}
static ssize_t mydevice_read ( struct file * f , char * buf , size_t len , loff_t * off )
{
ssize_t ret ;
lunatik_object_t * runtime = ( lunatik_object_t * ) f -> private_data ;
lunatik_run ( runtime , l_read , ret , buf , len , off );
return ret ;
} void lunatik_getobject ( lunatik_object_t * object ); Lunatik_getObject () Уравновешивает контрольный счетчик этого object (например, среда runtime ).
int lunatik_putobject ( lunatik_object_t * object ); lunatik_putobject () уменьшает контрольный счетчик этого object (например, среда runtime ). Если object был выпущен, он возвращает 1 ; В противном случае он возвращает 0 .
lunatik_object_t * lunatik_toruntime ( lua_State * L ); Lunatik_toruntime () возвращает среду runtime на которую ссылается дополнительное пространство L
Библиотека lunatik обеспечивает поддержку для загрузки и запуска сценариев и управления средами выполнения от LUA.
lunatik.runtime(script [, sleep]) Lunatik.runtime () создает новую среду выполнения, затем загружает и запускает Script /lib/modules/lua/<script>.lua в качестве точки входа для этой среды. Он возвращает объект Lunatik, представляющий среду runtime . Если sleep верен или пропущен, он будет использовать Mutex и gfp_kernel; В противном случае он будет использовать Spinlock и GFP_ATOMIC. Lunatik.runtime () открывает стандартные библиотеки LUA, присутствующие на Lunatik.
runtime:stop() Время выполнения: Stop () Остановит среду runtime и очищает ее ссылку на объект времени выполнения.
runtime:resume([obj1, ...]) Время выполнения: resume () возобновляет выполнение runtime . Значения obj1, ... передаются как аргументы для функции, возвращаемой при создании runtime . Если runtime уступило, resume() перезагружает его; Значения obj1, ... передаются как результаты урожайности.
Библиотека device обеспечивает поддержку для записи драйверов устройств символов в LUA.
device.new(driver) device.new () возвращает новый объект device и устанавливает свой driver в системе. driver должен быть определен как таблица, содержащая следующее поле:
name : строка определяет имя устройства; Он используется для создания файла устройства (например, /dev/<name> ). Таблица driver может при желании содержать следующие поля:
read : функция обратного вызова для обработки операции чтения в файле устройства. Он получает таблицу driver в качестве первого аргумента, за которым следует два целых числа, length , которая должна быть прочитана, и offset файла. Он должен вернуть строку и, необязательно, updated offset . Если длина возвращаемой строки превышает запрошенную length , строка будет исправлена до этой length . Если updated offset не будет возвращено, offset будет обновлено с помощью offset + length .write : Функция обратного вызова для обработки операции записи в файле устройства. Он получает таблицу driver в качестве первого аргумента, за которым следует записать строку, и целое число в качестве offset файла. Это может вернуть необязательно написанную length , за которой следует updated offset . Если возвращаемая длина больше, чем запрашиваемая length , возвращаемая длина будет исправлена. Если updated offset не будет возвращено, offset будет обновлено с помощью offset + length .open : Функция обратного вызова для обработки операции открытия в файле устройства. Он получает таблицу driver , и ожидается, что он ничего не вернет.release : Функция обратного вызова для обработки операции выпуска в файле устройства. Он получает таблицу driver , и ожидается, что он ничего не вернет.mode : целое число, указывающее режим файла устройства. Если обратный вызов операции не определен, device возвращает -ENXIO в VFS при его доступе.
device.stop(dev) , dev:stop() device.stop () Удаляет driver устройства, указанный объектом dev из системы.
Библиотека linux обеспечивает поддержку некоторых средств ядра Linux.
linux.random([m [, n]])linux.random () имитирует поведение математики .
При вызове без аргументов производит целое число со всеми битами (псевдо) случайным. При вызове с двумя целыми n m Linux.random () возвращает псевдолупольное целое число с равномерным распределением в диапазоне [m, n] . Call math.random(n) , для положительного n , эквивалентен math.random(1, n) .
linux.statlinux.stat - это таблица, которая экспортирует <linux/stat.h> целочисленные флаги в Lua.
"IRWXUGO" : разрешение читать , записать и выполнять для пользователя , группы и других ."IRUGO" : разрешение только на чтение для пользователя , группы и других ."IWUGO" : разрешение на писать только для пользователя , группы и других ."IXUGO" : разрешение только выполнить для пользователя , группы и других . linux.schedule([timeout [, state]]) Linux.schedule () устанавливает текущее state задачи и заставляет его спать до тех пор, пока не истечет timeout , на которые не истекают. Если timeout опущен, он использует MAX_SCHEDULE_TIMEOUT . Если state опущено, оно использует task.INTERRUPTIBLE .
linux.taskLinux.task - это таблица, которая экспортирует состояния задачи в LUA.
"RUNNING" : задача выполняется на процессоре или ожидает выполнения."INTERRUPTIBLE" : задача ждет сигнала или ресурса (сна)."UNINTERRUPTIBLE" : ведет себя как «прерывим», за исключением того, что сигнал не разбудит задачу."KILLABLE" : ведет себя как «непрерывное», за исключением того, что фатальные сигналы разбудили задачу."IDLE" : ведет себя как «непрестрашимый», за исключением того, что он избегает учета LoadAVG. linux.time()Linux.Time () возвращает текущее время в наносекундах с эпохи.
linux.errnoLinux.errno -это таблица, которая экспортирует <uapi/asm-Generic/errno-base.h> флаги в Lua.
"PERM" : операция не разрешена."NOENT" : нет такого файла или каталога."SRCH" : нет такого процесса."INTR" : прерванный системный вызов."IO" : ошибка ввода/вывода."NXIO" : нет такого устройства или адреса."2BIG" :, Список аргументов слишком долго."NOEXEC" : ошибка формата EXEC."BADF" : плохой номер файла."CHILD" : нет детей."AGAIN" : попробуйте еще раз."NOMEM" : вне памяти."ACCES" : разрешение отказано."FAULT" : плохой адрес."NOTBLK" : блокируется устройство."BUSY" : устройство или ресурс занят."EXIST" : файл существует."XDEV" : перекрестная ссылка."NODEV" : нет такого устройства."NOTDIR" : не каталог."ISDIR" : это каталог."INVAL" : неверный аргумент."NFILE" : переполнение таблицы файлов."MFILE" : слишком много открытых файлов."NOTTY" : не пишущая машинка."TXTBSY" : текстовый файл занят."FBIG" : файл слишком большой."NOSPC" : на устройстве не осталось места."SPIPE" : незаконные иски."ROFS" : файловая система только для чтения."MLINK" : слишком много ссылок."PIPE" : сломанная труба."DOM" : математический аргумент из домена фанка."RANGE" : математический результат не представлен. linux.hton16(num)linux.hton16 () преобразует порядок байта хоста в байт-порядок сети для 16-битного целого числа.
linux.hton32(num)linux.hton32 () преобразует порядок бата хоста в байт-порядок сети для 32-разрядного целого числа.
linux.hton64(num)Linux.hton64 () преобразует порядок бата хоста в байт-порядок сети для 64-разрядного целого числа.
linux.ntoh16(num)linux.ntoh16 () преобразует порядок байта сети для размещения байта для 16-битного целого числа.
linux.ntoh32(num)linux.ntoh32 () преобразует порядок байта сети для размещения байта для 32-разрядного целого числа.
linux.ntoh64(num)linux.ntoh64 () преобразует порядок байта сети для размещения байта для 64-разрядного целого числа.
linux.htobe16(num)linux.htobe16 () преобразует байт хоста в байт-орден биг-эндиан для 16-битного целого числа.
linux.htobe32(num)linux.htobe32 () преобразует байт хоста в байт-орден биг-эндиан для 32-разрядного целого числа.
linux.htobe64(num)Linux.htobe64 () преобразует байт хоста в байт-орден в большем эндэдиане для 64-разрядного целого числа.
linux.be16toh(num)linux.be16toh () преобразует байт-ордергин-эндэдийский байт на размещение байта для 16-битного целого числа.
linux.be32toh(num)linux.be32toh () преобразует байт-порядок крупных байтов для размещения байта для 32-разрядного целого числа.
linux.be64toh(num)linux.be64toh () преобразует байт-байт-порядок, чтобы размещать байт-порядок для 64-разрядного целого числа.
linux.htole16(num)Linux.htole16 () преобразует байт хоста в байт-орден в маленьком эндэндинском байте для 16-битного целого числа.
linux.htole32(num)linux.htole32 () преобразует байт хоста в малотинг-байт-орден для 32-разрядного целого числа.
linux.htole64(num)Linux.htole64 () преобразует байт хоста в байт-порядка маленького эндина для 64-разрядного целого числа.
linux.le16toh(num)linux.le16toh () преобразует байт-порядок с маленьким эендианским байтом для размещения байтового порядка для 16-битного целого числа.
linux.le32toh(num)linux.le32toh () преобразует байт-порядок с маленьким эендианским байтом для размещения байта для 32-разрядного целого числа.
linux.le64toh(num)linux.le64toh () преобразует байт-порядок с маленьким эендианским байтом для размещения байта для 64-разрядного целого числа.
Библиотека notifier обеспечивает поддержку цепочек уведомлений ядра.
notifier.keyboard(callback) Notifier.Keyboard () Возвращает новый объект notifier клавиатуры и устанавливает его в системе. Функция callback вызывается всякий раз, когда происходит консольное событие клавиатуры (например, нажата или выпущена клавиша). Этот callback получает следующие аргументы:
event : Доступные события определяются таблицей Notifier.kbd.down : true , если клавиша нажата; false , если он выпущен.shift : true , если ключ сдвига удерживается; false , иначе.key : Код ключа или ключ в зависимости от event . Функция callback может вернуть значения, определенные в таблице Notifier.notify.
notifier.kbdNotifier.kbd - это таблица, которая экспортирует флаги KBD в Lua.
"KEYCODE" : клавиш -код клавиши, вызванный любым другим."UNBOUND_KEYCODE" : клавиш -код клавиатуры, который не связан ни с одним другим."UNICODE" : клавиатура Unicode."KEYSYM" : клавиатура Keysym ."POST_KEYSYM" : называется интерпретацией клавишных клавиш . notifier.netdevice(callback) Notifier.netDevice () Возвращает новый объект notifier NetDevice и устанавливает его в системе. Функция callback вызывается всякий раз, когда происходит консольное событие NetDevice (например, сетевой интерфейс был подключен или отключен). Этот callback получает следующие аргументы:
event : доступные события определяются таблицей Notifier.netDev.name : имя устройства. Функция callback может вернуть значения, определенные в таблице Notifier.notify.
notifier.netdevNotifier.netDev - это таблица, которая экспортирует флаги NetDev в LUA.
notifier.notifyУведомление. НЕОТИФИЦИИ - это таблица, которая экспорта уведомляет флаги LUA.
"DONE" : не волнует."OK" : мне подходит."BAD" : плохое/вето."STOP" : Чистый способ вернуться от уведомления и остановить дальнейшие звонки. notfr:delete() notFR: delete () Удаляет notifier , указанное объектом notfr из системы.
Библиотека socket обеспечивает поддержку для обработки сети ядра. Эта библиотека была вдохновлена проектом GSOC Chengzhi Tan.
socket.new(family, type, protocol) Socket.new () создает новый объект socket . Эта функция получает следующие аргументы:
family : доступные адреса семьи определяются таблицей Socket.af.sock : доступные типы присутствуют на таблице сокета.protocol : Доступные протоколы определяются таблицей Socket.ipproto. socket.afSocket.af - это таблица, которая экспортирует обращение к семьям (AF) в LUA.
"UNSPEC" : неуточнен."UNIX" : доменные розетки Unix."LOCAL" : имя POSIX для AF_UNIX."INET" : интернет -протокол IP."AX25" : любительский радио AX.25."IPX" : Novell IPX."APPLETALK" : Appletalk Ddp."NETROM" : любительская радиотекала/ПЗУ."BRIDGE" : Многообразочный мост."ATMPVC" : ATM PVCS."X25" : зарезервирован для проекта X.25."INET6" : IP -версия 6."ROSE" : любительское радио X.25 PLP."DEC" : зарезервирован для проекта DECNET."NETBEUI" : зарезервирован для проекта 802.2LLC."SECURITY" : обратный вызов безопасности Pseudo AF."KEY" : PF_KEY KEY Management API."NETLINK" : NetLink."ROUTE" : псевдоним для подражания 4,4BSD."PACKET" : Семья пакетов."ASH" : Эш."ECONET" : Acorn Econet."ATMSVC" : ATM SVCS."RDS" : RDS Sockets."SNA" : Linux SNA Project (Nutters!)."IRDA" : Irda Stockets."PPPOX" : Pppox Sockets."WANPIPE" : Wanpipe API розетки."LLC" : Linux LLC."IB" : родной инфинибанд адрес."MPLS" : MPLS."CAN" : сеть области контроллера."TIPC" : Tipc Chockets."BLUETOOTH" : Bluetooth Chockets."IUCV" : Спекеты IUCV."RXRPC" : RXRPC Sockets."ISDN" : неправильные розетки."PHONET" : Phonet Chockets."IEEE802154" : IEEE802154 СОКЕТЫ."CAIF" : Caif Cockets."ALG" : алгоритм гнезда."NFC" : NFC Sockets."VSOCK" : Vsockets."KCM" : мультиплексор подключения ядра."QIPCRTR" : Qualcomm IPC маршрутизатор."SMC" : номер резерва для семейства протоколов PF_SMC, который повторно использует семейство AF_INET."XDP" : xdp stockets."MCTP" : протокол транспорта компонентов управления."MAX" : максимум. socket.sockSocket.sock - это таблица, которая экспортирует типы сокетов (носок):
"STREAM" : поток (соединение)."DGRAM" : Datagram (Conn.Less)."RAW" : сырой гнездо."RDM" : надежно отправленное сообщение."SEQPACKET" : последовательный пакет сокет."DCCP" : гнездо протокола управления затоками Datagram."PACKET" : Linux специфичный способ получить пакеты на уровне разработчика.и флаги (носок):
"CLOEXEC" : n/a."NONBLOCK" : n/a. socket.ipprotoSocket.ipproto - это таблица, которая экспортирует IP -протоколы (ipproto) в Lua.
"IP" : фиктивный протокол для TCP."ICMP" : протокол сообщений об управлении интернетом."IGMP" : протокол управления интернет -группой."IPIP" : IPIP -туннели (более старые туннели KA9Q используют 94)."TCP" : протокол управления передачей."EGP" : протокол внешнего шлюза."PUP" : протокол щенка."UDP" : протокол Datagram пользователя."IDP" : протокол IDP XNS."TP" : Итак, класс транспортного протокола 4."DCCP" : протокол управления затоками в DataGRAM."IPV6" : IPv6-in-IPV4 Туннелирование."RSVP" : протокол RSVP."GRE" : Cisco Gre Tunnels (RFC 1701,1702)."ESP" : протокол полезной нагрузки."AH" : протокол заголовка аутентификации."MTP" : протокол многоадресной переноса."BEETPH" : IP -опция псевдо -заголовок для свеклы."ENCAP" : заголовок инкапсуляции."PIM" : независимая протокола многоадресной рассылки."COMP" : протокол заголовка сжатия."SCTP" : протокол транспортировки управления потоком."UDPLITE" : udp-lite (RFC 3828)."MPLS" : MPLS в IP (RFC 4023)."ETHERNET" : Ethernet-Within-IPV6 Encapsulation."RAW" : RAW PACKETS."MPTCP" : Multyath TCP -соединение. sock:close() Носок: Close () Удаляет объект sock из системы.
sock:send(message, [addr [, port]]) Sock: Send () Отправляет строковое message через sock . Если семейство sock Address af.INET , то она ожидает следующих аргументов:
addr : integer описывает адрес назначения IPv4.port : integer описывает порт назначения IPv4.В противном случае:
addr : упакованная строка, описывающая адрес назначения. sock:receive(length, [flags [, from]]) Sock: recet () получает строку с байтами до length через sock сокета. Доступные флаги сообщений определяются таблицей Socket.msg. Если from , что это true , он возвращает полученное сообщение, за которым следует адрес сверстника. В противном случае он возвращает только полученное сообщение.
socket.msgSocket.msg - это таблица, которая экспортирует флаги сообщений в LUA.
"OOB" : n/a."PEEK" : N/A."DONTROUTE" : N/A."TRYHARD" : синоним "DONTROUTE" для Decnet."CTRUNC" : n/a."PROBE" : не отправляйте. Только путь зонда для MTU."TRUNC" : n/a."DONTWAIT" : неблокирующий io."EOR" : конец записи."WAITALL" : дождитесь полной запроса."FIN" : N/A."SYN" : N/A."CONFIRM" : подтвердите достоверность пути."RST" : N/A."ERRQUEUE" : извлечь сообщение из очереди ошибок."NOSIGNAL" : не генерируйте Sigpipe."MORE" : отправитель отправит больше."WAITFORONE" : recvmmsg (): блокируйте до 1+ пакетов."SENDPAGE_NOPOLICY" : SendPage () Internal: не применить политику."SENDPAGE_NOTLAST" : SendPage () Internal: не последняя страница."BATCH" : sendmmsg (): больше сообщений."EOF" : n/a."NO_SHARED_FRAGS" : SendPage () Internal: Fage Frags не совместно используются."SENDPAGE_DECRYPTED" : SendPage () Internal: Page может нести простой текст и требовать шифрования."ZEROCOPY" : используйте пользовательские данные в пути ядра."FASTOPEN" : отправьте данные в TCP Syn."CMSG_CLOEXEC" : SET CLOUL_ON_EXEC для дескриптора файла, полученного через SCM_RIGHTS. sock:bind(addr [, port]) Sock: bind () связывает sock сокета с данным адресом. Если семейство sock Address af.INET , то она ожидает следующих аргументов:
addr : integer описывает адрес хоста IPv4.port : integer описывает хост IPv4 Port.В противном случае:
addr : упакованная строка, описывающая адрес хоста. sock:listen([backlog]) Носок: Слушай () перемещает sock розетка в состояние прослушивания.
backlog : ожидающий размер очереди соединений. Если опущено, он использует SomaxConn в качестве по умолчанию. sock:accept([flags]) Sock: Accept () принимает соединение в сокете sock . Возвращает новый объект socket . Доступные флаги присутствуют на таблице Socket.Sock.
sock:connect(addr [, port] [, flags]) Sock: Connect () Подключает sock сокета к адресу addr . Если семейство sock Address af.INET , то она ожидает следующих аргументов:
addr : integer описывает адрес назначения IPv4.port : integer описывает порт назначения IPv4.В противном случае:
addr : упакованная строка, описывающая адрес назначения.Доступные флаги присутствуют на таблице Socket.Sock.
Для гнезда DataGrams addr - это адрес, на который действуйте, отправляются по умолчанию, и единственный адрес, с которого получены документы. Для выстрелов потока попытки подключиться к addr .
sock:getsockname() Sock: getockname () Получите адрес, который связан sock . Если семья sock - это af.INET , то он возвращает следующее:
addr : integer описывает ограниченный адрес IPv4.port : integer описывает ограниченный порт IPv4.В противном случае:
addr : упакованная строка, описывающая ограниченный адрес. sock:getpeername() Sock: getPeerName () Получите адрес, который подключен в sock сокета. Если семья sock - это af.INET , то он возвращает следующее:
addr : integer описывает адрес Peer IPv4.port : integer описывает порт Peer IPv4.В противном случае:
addr : упакованная строка, описывающая адрес сверстника. Библиотека socket.inet обеспечивает поддержку гнезда IPv4 высокого уровня.
inet.tcp() inet.tcp () создает новую socket с использованием семейства AF.Inet Adder, Sock.stream тип и протокола ipproto.tcp. Он переопределяет методы socket , чтобы использовать адреса в качестве нотации цифр и точек (например, "127.0.0.1" ), а не целые числа.
inet.udp() inet.udp () создает новую socket с использованием семейства AF.Inet Adder, типа Sock.dgram и протокол ipproto.udp. Он переопределяет методы socket , чтобы использовать адреса в качестве нотации цифр и точек (например, "127.0.0.1" ), а не целые числа.
udp:receivefrom(length [, flags]) udp: receptfrom () - это всего лишь псевдоним для sock:receive(length, flags, true) .
Библиотека rcu обеспечивает поддержку механизма синхронизации обновлений (RCU) обновления (RCU). Эта библиотека была вдохновлена проектом Caio Messias GSOC.
rcu.table([size]) rcu.table () создает новый объект rcu.table , который связывает общее хэш -таблицу ядра. Эта функция получает в качестве аргумента, количество ведер, окруженных до следующей мощности 2. Размер по умолчанию составляет 1024 . Ключ должен быть строкой, а значение должно быть объектом Lunatik или ноль.
Библиотека thread обеспечивает поддержку примитивов резьбы ядра.
thread.run(runtime, name) Thread.run () создает новый объект thread и разбудит его. Эта функция получает следующие аргументы:
runtime : среда выполнения для выполнения задачи в потоке созданных ядра. Задача должна быть указана путем возврата функции в сценарии, загруженном в среде runtime .name : строка, представляющая имя для потока (например, как показано на ps ). thread.shouldstop() thread.shouldstop () возвращает true если trade.stop () был вызван; В противном случае он возвращает false .
thread.current() Think.current () Возвращает объект thread представляющий текущую задачу.
thrd:stop() THRD: STOP () Устанавливает Thread.SHOULDSTOP () в потоке thrd , чтобы вернуть True, просыпаться thrd и ждет, пока он выйдет.
thrd:task() THRD: Task () возвращает таблицу, содержащую информацию о задаче этого thread (например, «ЦП», «Команда», «PID» и «TGID»).
Библиотека fib обеспечивает поддержку информации о передаче ядра.
fib.newrule(table, priority)fib.newrule () связывает ядро fib_nl_newrule api; Он создает новое правило FIB, которое соответствует указанной таблице маршрутизации с указанной Приоритетом . Эта функция похожа на правило IP-правила команды пользовательского пространства, предоставленное iProute2.
fib.delrule(table, priority)fib.delrule () связывает ядро fib_nl_delrule api; Он удаляет правило FIB, которое соответствует указанной таблице маршрутизации с указанной Приоритетом . Эта функция аналогична правилу IP-правила команды пользовательского пространства DEL, предоставленное iProute2.
Библиотека data обеспечивает поддержку для привязки системной памяти с LUA.
data.new(size) data.new () создает новый объект data , который выделяет байты size .
d:getnumber(offset) D: getNumber () извлекает lua_integer из памяти, на которую ссылается объект data и offset байта, начиная с нуля.
d:setnumber(offset, number) D: SetNumber () вставьте number LUA_INTEGER в память, на которую ссылается объект data и offset байта, начиная с нуля.
d:getbyte(offset) D: GetByte () извлекает байт из памяти, на который ссылается объект data и offset байта, начиная с нуля.
d:setbyte(offset, byte) D: SetByte () Вставьте байт в память, на которую ссылается объект data и offset байта, начиная с нуля.
d:getstring(offset[, length]) D: getString () извлекает строку с байтами length из памяти, на которую ссылается объект data и offset байта, начиная с нуля. Если length опущена, он извлекает все байты от offset до конца data .
d:setstring(offset, s) D: SetString () Вставьте строку s в память, на которую ссылается объект data и offset байта, начиная с нуля.
d:getint8(offset) D: GetInt8 (D, Offset) извлекает подписанное 8-битное целое число из памяти, на которое ссылается объект data и offset байта, начиная с нуля.
d:setint8(offset, number) D: setInt8 () вставляет подписанное 8-битное число в память, на которую ссылается объект data и offset байта, начиная с нуля.
d:getuint8(offset) D: getUint8 () извлекает беспигнированное 8-битное целое число из памяти, на которое ссылается объект data и offset байта, начиная с нуля.
d:setuint8(offset, number) D: setUint8 () вставляет беззнательное 8-битное число в память, на которую ссылается объект data и offset байта, начиная с нуля.
d:getint16(offset) D: GetInt16 () извлекает подписанное 16-битное целое число из памяти, на которое ссылается объект data и offset байта, начиная с нуля.
d:setint16(offset, number) D: setInt16 () вставляет подписанное 16-битное число в память, на которую ссылается объект data и offset байта, начиная с нуля.
d:getuint16(offset) D: getUint16 () извлекает не знаковое 16-битное целое число из памяти, на которое ссылается объект data и offset байта, начиная с нуля.
d:setuint16(offset, number) D: setUint16 () вставляет беспигнированное 16-битное число в память, на которую ссылается объект data и offset байта, начиная с нуля.
d:getint32(offset) D: GetInt32 () извлекает подписанное 32-разрядное целое число из памяти, на которое ссылается объект data и offset байта, начиная с нуля.
d:setint32(offset, number) D: setInt32 () вставляет подписанное 32-разрядное число в память, на которую ссылается объект data и offset байта, начиная с нуля.
d:getuint32(offset) D: getUint32 () извлекает не знаковое 32-разрядное целое число из памяти, на которое ссылается объект data и offset байта, начиная с нуля.
d:setuint32(offset, number) D: setUint32 () вставляет беззнательное 32-разрядное число в память, на которую ссылается объект data и offset байта, начиная с нуля.
d:getint64(offset) D: GetInt64 () извлекает подписанное 64-разрядное целое число из памяти, на которое ссылается объект data и offset байта, начиная с нуля.
d:setint64(offset, number) D: setInt64 () вставляет подписанное 64-разрядное число в память, на которую ссылается объект data и offset байта, начиная с нуля.
Библиотека probe обеспечивает поддержку зондов ядра.
probe.new(symbol|address, handlers) grove.new () Возвращает новый объект probe для мониторинга symbol ядра (строки) или address (Light userdata) и устанавливает свои handlers в системе. handler должен быть определен как таблица, содержащая следующее поле:
pre : функция, которая будет вызвана до проведенной инструкции. Он получает symbol или address , за которым следует закрытие, которое можно вызвать, чтобы показать регистры процессора и стека в журнале системы.post : функция, которая должна быть вызвана после проверенной инструкции. Он получает symbol или address , за которым следует закрытие, которое можно вызвать, чтобы показать регистры процессора и стека в журнале системы. p:stop() P: Stop () Удаляет обработчики probe из системы.
p:enable(bool) P: enable () включает или отключает обработчики probe , соответственно, в bool .
Библиотека syscall обеспечивает поддержку адресов и номеров системного вызова.
syscall.address(number) syscall.address () Возвращает адрес системного вызова (Light userdata), на который ссылаются заданный number .
syscall.number(name) syscall.number () Возвращает номер системного вызова, на который ссылаются заданное name .
Библиотека syscall.table обеспечивает поддержку для перевода системных имен вызовов на адреса (Light userdata).
Библиотека xdp обеспечивает поддержку подсистемы пути данных Cernel Express (XDP). Эта библиотека была вдохновлена проектом GSOC Victor Nogueira.
xdp.attach(callback) xdp.attach () регистрирует функцию callback в текущее runtime , которая будет вызвана из программы XDP/EBPF всякий раз, когда она вызывает bpf_luaxdp_run kfunc. Этот callback получает следующие аргументы:
buffer : объект data , представляющий сетевой буфер.argument : объект data , содержащий аргумент, переданный программой XDP/EBPF. Функция callback может вернуть значения, определенные таблицей XDP.Action.
xdp.detach() xdp.detach () Нерегистрирует callback связанный с текущим runtime , если таковые имеются.
xdp.actionxdp.action - это таблица, которая экспортирует флаги xdp_action в Lua.
"ABORTED" : указывает, что программа XDP прерывается, как правило, из -за ошибки."DROP" : указывает, что пакет должен быть отброшен, полностью отбрасывая его."PASS" : позволяет пакету переходить в стек сети Linux."TX" : передает пакет обратно на тот же интерфейс, который он был получен."REDIRECT" : перенаправляет пакет на другой интерфейс или контекст обработки. Библиотека xtable обеспечивает поддержку для разработки расширений NetFilter XTable.
xtable.match(opts)xtable.match () возвращает новый объект xtable для расширений матчей. Эта функция получает следующие аргументы:
opts : таблица, содержащая следующие поля:name : Строка, представляющая имя расширения xtable.revision : целое число представляющее xTable Extension Revision.family : адреса семьи, один из netfilter.family.proto : номер протокола, один из сокетов.hooks : крючок, чтобы прикрепить расширение к одному значению из любой из таблицы крючков - netfilter.inet_hooks, netfilter.bridge_hooks и netfilter.arp_hooks (Примечание: netfilter.netdev_hooks не доступен для Legacy x_tables). (Например, 1 << inet_hooks.LOCAL_OUT ).match : функция для подходящих пакетов. Он получает следующие аргументы:skb (readonly): объект data , представляющий буфер сокета.par : Таблица, содержащая hotdrop , thoff (Offset Transport Header) и fragoff (Fragment Offset) Поля.userargs : строка LUA, передаваемая из модуля пользовательского пространства xtable.true если пакет соответствует расширению; В противном случае он должен вернуть false .checkentry : функция для проверки записи. Эта функция получает userargs в качестве аргумента.destroy : функция, которая должна быть вызвана для уничтожения расширения Xtable. Эта функция получает userargs в качестве аргумента. xtable.target(opts)xtable.target () Возвращает новый объект xtable для целевого расширения. Эта функция получает следующие аргументы:
opts : таблица, содержащая следующие поля:name : Строка, представляющая имя расширения xtable.revision : целое число представляющее xTable Extension Revision.family : адреса семьи, один из netfilter.family.proto : номер протокола, один из сокетов.hooks : крючок, чтобы прикрепить расширение к одному значению из любой из таблицы крючков - netfilter.inet_hooks, netfilter.bridge_hooks и netfilter.arp_hooks (Примечание: netfilter.netdev_hooks не доступен для Legacy x_tables). (Например, 1 << inet_hooks.LOCAL_OUT ).target : Функция, которая будет вызвана для таргетинга. Он получает следующие аргументы:skb : объект data , представляющий буфер сокета.par (READONLY): Таблица, содержащая hotdrop , поля thoff (смещение транспорта) и fragoff (смещение фрагмента).userargs : строка LUA, передаваемая из модуля пользовательского пространства xtable.checkentry : функция для проверки записи. Эта функция получает userargs в качестве аргумента.destroy : функция, которая должна быть вызвана для уничтожения расширения Xtable. Эта функция получает userargs в качестве аргумента. Библиотека netfilter обеспечивает поддержку новой системы NetFilter Hook.
netfilter.register(ops) netfilter.register () регистрирует новый крючок NetFilter с данной таблицей ops . Эта функция получает следующие аргументы:
ops : таблица, содержащая следующие поля:pf : Семейство протоколов, один из Netfilter.familyhooknum : Hook, чтобы прикрепить фильтр к одному значению из любой из таблицы Hooks - NetFilter.inet_hooks, netfilter.bridge_hooks, netfilter.arp_hooks и netfilter.netdev_hooks. (Например, inet_hooks.LOCAL_OUT + 11 ).priority : приоритет крючка. Одно из значений из таблиц netfilter.ip_priority или netfilter.bridge_priority.hook : Функция, которая будет вызвана для крючка. Он получает следующие аргументы:skb : a data object representing the socket buffer.netfilter.familynetfilter.family is a table that exports address families to Lua.
"UNSPEC" : Unspecified."INET" : Internet Protocol version 4."IPV4" : Internet Protocol version 4."IPV6" : Internet Protocol version 6."ARP" : Address Resolution Protocol."NETDEV" : Device ingress and egress path"BRIDGE" : Ethernet Bridge. netfilter.actionnetfilter.action is a table that exports netfilter actions to Lua.
"DROP" : NF_DROP . The packet is dropped. It is not forwarded, processed, or seen by any other network layer."ACCEPT" : NF_ACCEPT . The packet is accepted and passed to the next step in the network processing chain."STOLEN" : NF_STOLEN . The packet is taken by the handler, and processing stops."QUEUE" : NF_QUEUE . The packet is queued for user-space processing."REPEAT" : NF_REPEAT . The packet is sent through the hook chain again."STOP" : NF_STOP . Processing of the packet stops."CONTINUE" : XT_CONTINUE . Return the packet should continue traversing the rules within the same table."RETURN" : XT_RETURN . Return the packet to the previous chain. netfilter.inet_hooksnetfilter.inet_hooks is a table that exports inet netfilter hooks to Lua.
"PRE_ROUTING" : NF_INET_PRE_ROUTING . The packet is received by the network stack."LOCAL_IN" : NF_INET_LOCAL_IN . The packet is destined for the local system."FORWARD" : NF_INET_FORWARD . The packet is to be forwarded to another host."LOCAL_OUT" : NF_INET_LOCAL_OUT . The packet is generated by the local system."POST_ROUTING" : NF_INET_POST_ROUTING . The packet is about to be sent out. netfilter.bridge_hooksnetfilter.bridge_hooks is a table that exports bridge netfilter hooks to Lua.
"PRE_ROUTING" : NF_BR_PRE_ROUTING . First hook invoked, runs before forward database is consulted."LOCAL_IN" : NF_BR_LOCAL_IN . Invoked for packets destined for the machine where the bridge was configured on."FORWARD" : NF_BR_FORWARD . Called for frames that are bridged to a different port of the same logical bridge device."LOCAL_OUT" : NF_BR_LOCAL_OUT . Called for locally originating packets that will be transmitted via the bridge."POST_ROUTING" : NF_BR_POST_ROUTING . Called for all locally generated packets and all bridged packets netfilter.arp_hooksnetfilter.arp_hooks is a table that exports arp netfilter hooks to Lua.
"IN" : NF_ARP_IN . The packet is received by the network stack."OUT" : NF_ARP_OUT . The packet is generated by the local system."FORWARD" : NF_ARP_FORWARD . The packet is to be forwarded to another host. netfilter.netdev_hooksnetfilter.netdev_hooks is a table that exports netdev netfilter hooks to Lua.
"INGRESS" : NF_NETDEV_INGRESS . The packet is received by the network stack."EGRESS" : NF_NETDEV_EGRESS . The packet is generated by the local system. netfilter.ip_prioritynetfilter.ip_priority is a table that exports netfilter IPv4/IPv6 priority levels to Lua.
"FIRST" : NF_IP_PRI_FIRST"RAW_BEFORE_DEFRAG" : NF_IP_PRI_RAW_BEFORE_DEFRAG"CONNTRACK_DEFRAG" : NF_IP_PRI_CONNTRACK_DEFRAG"RAW" : NF_IP_PRI_RAW"SELINUX_FIRST" : NF_IP_PRI_SELINUX_FIRST"CONNTRACK" : NF_IP_PRI_CONNTRACK"MANGLE" : NF_IP_PRI_MANGLE"NAT_DST" : NF_IP_PRI_NAT_DST"FILTER" : NF_IP_PRI_FILTER"SECURITY" : NF_IP_PRI_SECURITY"NAT_SRC" : NF_IP_PRI_NAT_SRC"SELINUX_LAST" : NF_IP_PRI_SELINUX_LAST"CONNTRACK_HELPER" : NF_IP_PRI_CONNTRACK_HELPER"LAST" : NF_IP_PRI_LAST netfilter.bridge_prioritynetfilter.bridge_priority is a table that exports netfilter bridge priority levels to Lua.
"FIRST" : NF_BR_PRI_FIRST"NAT_DST_BRIDGED" : NF_BR_PRI_NAT_DST_BRIDGED"FILTER_BRIDGED" : NF_BR_PRI_FILTER_BRIDGED"BRNF" : NF_BR_PRI_BRNF"NAT_DST_OTHER" : NF_BR_PRI_NAT_DST_OTHER"FILTER_OTHER" : NF_BR_PRI_FILTER_OTHER"NAT_SRC" : NF_BR_PRI_NAT_SRC"LAST" : NF_BR_PRI_LAST The luaxt userspace library provides support for generating userspace code for xtable extensions.
To build the library, the following steps are required:
usr/lib/xtable and create a libxt_<ext_name>.lua file.luaxt ) in the created file.LUAXTABLE_MODULE=<ext_name> make to build the extension and LUAXTABLE_MODULE=<ext_name> make install (as root) to install the userspace plugin to the system. Now load the extension normally using iptables .
luaxt.match(opts)luaxt.match() returns a new luaxt object for match extensions. This function receives the following arguments:
opts : a table containing the following fields:revision : integer representing the xtable extension revision ( must be same as used in corresponding kernel extension).family : address family, one of luaxt.familyhelp : function to be called for displaying help message for the extension.init : function to be called for initializing the extension. This function receives an par table that can be used to set userargs . ( par.userargs = "mydata" )print : function to be called for printing the arguments. This function recevies userargs set by the init or parse function.save : function to be called for saving the arguments. This function recevies userargs set by the init or parse function.parse : function to be called for parsing the command line arguments. This function receives an par table that can be used to set userargs and flags . ( par.userargs = "mydata" )final_check : function to be called for final checking of the arguments. This function receives flags set by the parse function. luaxt.target(opts)luaxt.target() returns a new luaxt object for target extensions. This function receives the following arguments:
opts : a table containing the following fields:revision : integer representing the xtable extension revision ( must be same as used in corresponding kernel extension).family : address family, one of luaxt.familyhelp : function to be called for displaying help message for the extension.init : function to be called for initializing the extension. This function receives an par table that can be used to set userargs . ( par.userargs = "mydata" )print : function to be called for printing the arguments. This function recevies userargs set by the init or parse function.save : function to be called for saving the arguments. This function recevies userargs set by the init or parse function.parse : function to be called for parsing the command line arguments. This function receives an par table that can be used to set userargs and flags . ( par.userargs = "mydata" )final_check : function to be called for final checking of the arguments. This function receives flags set by the parse function. luaxt.familyluaxt.family is a table that exports address families to Lua.
"UNSPEC" : Unspecified."INET" : Internet Protocol version 4."IPV4" : Internet Protocol version 4."IPV6" : Internet Protocol version 6."ARP" : Address Resolution Protocol."NETDEV" : Device ingress and egress path"BRIDGE" : Ethernet Bridge.completion The completion library provides support for the kernel completion primitives.
Task completion is a synchronization mechanism used to coordinate the execution of multiple threads, similar to pthread_barrier , it allows threads to wait for a specific event to occur before proceeding, ensuring certain tasks are complete in a race-free manner.
completion.new() completion.new() creates a new completion object.
c:complete()c:complete() signals a single thread waiting on this completion.
c:wait([timeout]) c:wait() waits for completion of a task until the specified timeout expires. The timeout is specified in milliseconds. If the timeout parameter is omitted, it waits indefinitely. Passing a timeout value less than zero results in undefined behavior. Threads waiting for events can be interrupted by signals, for example, such as when thread.stop is invoked. Therefore, this function can return in three ways:
truenil, "timeout"nil, "interrupt" spyglass is a kernel script that implements a keylogger inspired by the spy kernel module. This kernel script logs the keysym of the pressed keys in a device ( /dev/spyglass ). If the keysym is a printable character, spyglass logs the keysym itself; otherwise, it logs a mnemonic of the ASCII code, (eg, <del> stands for 127 ).
sudo make examples_install # installs examples
sudo lunatik run examples/spyglass # runs spyglass
sudo tail -f /dev/spyglass # prints the key log
sudo sh -c "echo 'enable=false' > /dev/spyglass" # disable the key logging
sudo sh -c "echo 'enable=true' > /dev/spyglass" # enable the key logging
sudo sh -c "echo 'net=127.0.0.1:1337' > /dev/spyglass" # enable network support
nc -lu 127.0.0.1 1337 & # listen to UDP 127.0.0.1:1337
sudo tail -f /dev/spyglass # sends the key log through the network
keylocker is a kernel script that implements Konami Code for locking and unlocking the console keyboard. When the user types ↑ ↑ ↓ ↓ ← → ← → LCTRL LALT , the keyboard will be locked ; that is, the system will stop processing any key pressed until the user types the same key sequence again.
sudo make examples_install # installs examples
sudo lunatik run examples/keylocker # runs keylocker
<↑> <↑> <↓> <↓> <←> <→> <←> <→> <LCTRL> <LALT> # locks keyboard
<↑> <↑> <↓> <↓> <←> <→> <←> <→> <LCTRL> <LALT> # unlocks keyboard
tap is a kernel script that implements a sniffer using AF_PACKET socket. It prints destination and source MAC addresses followed by Ethernet type and the frame size.
sudo make examples_install # installs examples
sudo lunatik run examples/tap # runs tap
cat /dev/tap
shared is a kernel script that implements an in-memory key-value store using rcu, data, socket and thread.
sudo make examples_install # installs examples
sudo lunatik spawn examples/shared # spawns shared
nc 127.0.0.1 90 # connects to shared
foo=bar # assigns "bar" to foo
foo # retrieves foo
bar
^C # finishes the connection
echod is an echo server implemented as kernel scripts.
sudo make examples_install # installs examples
sudo lunatik spawn examples/echod/daemon # runs echod
nc 127.0.0.1 1337
hello kernel!
hello kernel!
systrack is a kernel script that implements a device driver to monitor system calls. It prints the amount of times each system call was called since the driver has been installed.
sudo make examples_install # installs examples
sudo lunatik run examples/systrack # runs systracker
cat /dev/systrack
writev: 0
close: 1927
write: 1085
openat: 2036
read: 4131
readv: 0
filter is a kernel extension composed by a XDP/eBPF program to filter HTTPS sessions and a Lua kernel script to filter SNI TLS extension. This kernel extension drops any HTTPS request destinated to a blacklisted server.
Compile and install libbpf , libxdp and xdp-loader :
mkdir -p " ${LUNATIK_DIR} " ; cd " ${LUNATIK_DIR} " # LUNATIK_DIR must be set to the same value as above (Setup section)
git clone --depth 1 --recurse-submodules https://github.com/xdp-project/xdp-tools.git
cd xdp-tools/lib/libbpf/src
make
sudo DESTDIR=/ make install
cd ../../../
make libxdp
cd xdp-loader
make
sudo make installCome back to this repository, install and load the filter:
cd ${LUNATIK_DIR} /lunatik # cf. above
sudo make btf_install # needed to export the 'bpf_luaxdp_run' kfunc
sudo make examples_install # installs examples
make ebpf # builds the XDP/eBPF program
sudo make ebpf_install # installs the XDP/eBPF program
sudo lunatik run examples/filter/sni false # runs the Lua kernel script
sudo xdp-loader load -m skb < ifname > https.o # loads the XDP/eBPF programFor example, testing is easy thanks to docker. Assuming docker is installed and running:
sudo xdp-loader load -m skb docker0 https.o
sudo journalctl -ft kerneldocker run --rm -it alpine/curl https://ebpf.io The system logs (in the first terminal) should display filter_sni: ebpf.io DROP , and the docker run… should return curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to ebpf.io:443 .
This other sni filter uses netfilter api.
dnsblock is a kernel script that uses the lunatik xtable library to filter DNS packets. This script drops any outbound DNS packet with question matching the blacklist provided by the user.
sudo make examples_install # installs examples
cd examples/dnsblock
make # builds the userspace extension for netfilter
sudo make install # installs the extension to Xtables directory
sudo lunatik run examples/dnsblock/dnsblock false # runs the Lua kernel script
sudo iptables -A OUTPUT -m dnsblock -j DROP # this initiates the netfilter framework to load our extension
sudo make examples_install # installs examples
sudo lunatik run examples/dnsblock/nf_dnsblock false # runs the Lua kernel script
dnsdoctor is a kernel script that uses the lunatik xtable library to change the DNS response from Public IP to a Private IP if the destination IP matches the one provided by the user. For example, if the user wants to change the DNS response from 192.168.10.1 to 10.1.2.3 for the domain lunatik.com if the query is being sent to 10.1.1.2 (a private client), this script can be used.
sudo make examples_install # installs examples
cd examples/dnsdoctor
setup.sh # sets up the environment
# test the setup, a response with IP 192.168.10.1 should be returned
dig lunatik.com
# run the Lua kernel script
sudo lunatik run examples/dnsdoctor/dnsdoctor false
# build and install the userspace extension for netfilter
make
sudo make install
# add rule to the mangle table
sudo iptables -t mangle -A PREROUTING -p udp --sport 53 -j dnsdoctor
# test the setup, a response with IP 10.1.2.3 should be returned
dig lunatik.com
# cleanup
sudo iptables -t mangle -D PREROUTING -p udp --sport 53 -j dnsdoctor # remove the rule
sudo lunatik unload
cleanup.sh
sudo make examples_install # installs examples
examples/dnsdoctor/setup.sh # sets up the environment
# test the setup, a response with IP 192.168.10.1 should be returned
dig lunatik.com
# run the Lua kernel script
sudo lunatik run examples/dnsdoctor/nf_dnsdoctor false
# test the setup, a response with IP 10.1.2.3 should be returned
dig lunatik.com
# cleanup
sudo lunatik unload
examples/dnsdoctor/cleanup.sh
Lunatik is dual-licensed under MIT or GPL-2.0-only.
Lua submodule is licensed under MIT. For more details, see its Copyright Notice.
Klibc submodule is dual-licensed under BSD 3-Clause or GPL-2.0-only. For more details, see its LICENCE file.