Introduction
Let me introduce my self, Who is Fadhil? Fadhil Riyanto (real-name), is a self-taught system programmer (also backend programmer) which live in Indonesian, This is some short & dirty tutorial about computer science and litte about math.
mirrors: blog.fadhils.eu.org
Contributing
Found a mistake? You can freely DM me on telegram or just email me on
- me@fadev.org (primary, fast respond)
- fadhilriyanto@duck.com (gmail mirror)
- fadhil.riyanto@gnuweeb.org (alternative-1)
- xor@3xploit.dev (alternative-2)
Language
Because I'm indonesian, some part of this website may written in indonesian. But I will try to translating it into english language.
Note
[EN] If you found a mistake, let me know. BIG thanks!
[ID] Jika kamu menemukan sesuatu yang sepertinya itu salah, bisa langsung kasih kabar ke saya. Terimakasih.
todo
- MAKE:
./server/php-fpm-config.md
book - COMPLETION:
./database/postgresql_system_table
- COMPLETION:
./database/postgresql_functions
- MAKE:
./crypto/ca-certificates
- MAKE: "freeRADIUS deploy"
System programming
How data movement changes a destination register
This snippets is from "Computer Systems A Programmer’s Perspective, by Randal E. Bryant and David R. O’Hallaron"
As described, there are two different conventions regarding whether and how data movement instruc- tions modify the upper bytes of a destination register. This distinction is illustrated by the following code sequence:
1 movabsq $0x0011223344556677, %rax %rax = 0011223344556677
2 movb $-1, %al %rax = 00112233445566FF
3 movw $-1, %ax %rax = 001122334455FFFF
4 movl $-1, %eax %rax = 00000000FFFFFFFF
5 movq $-1, %rax %rax = FFFFFFFFFFFFFFFF
In the following discussion, we use hexadecimal notation. In the example, the instruction on line 1 initializes register %rax to the pattern 0011223344556677. The remaining instructions have immediate value −1 as their source values. Recall that the hexadecimal representation of −1 is of the form FF. . .F, where the number of F’s is twice the number of bytes in the representation. The movb instruction (line 2) therefore sets the low-order byte of %rax to FF, while the movw instruction (line 3) sets the low-order 2 bytes to FFFF, with the remaining bytes unchanged. The movl instruction (line 4) sets the low-order 4 bytes to FFFFFFFF, but it also sets the high-order 4 bytes to 00000000. Finally, the movq instruction (line 5) sets the complete register to FFFFFFFFFFFFFFFF.
some useful links
General embedded ASM linked in C
this is program is succesfully compiled with as
, but failed to run due to SIGSEGV.
this is will fail
.data
val:
.byte 0xF6
.byte 0xF6
.byte 0xF6
.byte 0xF6
.globl do_asm
do_asm:
# movl 0x12345678, %eax
# movl 0xAABBCCDD, %edx
# # move edx 8 bit high into al (eax)
# movb %dh, %al
movq $9, %rax
ret
this is will compile
.data
val:
.byte 0xF6
.byte 0xF6
.byte 0xF6
.byte 0xF6
.globl do_asm
.text
do_asm:
# movl 0x12345678, %eax
# movl 0xAABBCCDD, %edx
# # move edx 8 bit high into al (eax)
# movb %dh, %al
movq $9, %rax
ret
the difference only in .text
section
Move sign & zero-extends a single byte
Disini saya akan membahas apa itu instruksi MOVSBL dan MOVZBL. pertama tama silahkan baca dulu disini
MOVSBL and MOVZBL
* MOVSBL sign-extends a single byte, and copies it into a
double-word destination
* MOVZBL expands a single byte to 32 bits with 24 leading
zeros, and copies it into a double-word destination
pertama tama, lihat kode asm ini.
.section .data
val:
.byte 0xF6
.byte 0xF6
.byte 0xF6
.byte 0xF6
.globl do_asm
.text
do_asm:
movl $0x12345678, %eax
movl $0xAABBCCDD, %edx
# move edx 8 bit high into al (eax)
movb %dh, %al
# reset
movl $0x12345678, %eax
movl $0xAABBCCDD, %edx
MOVSBL %dh, %eax
# reset
movl $0x12345678, %eax
movl $0xAABBCCDD, %edx
MOVZBL %dh, %eax
movq $9, %rax
ret
dan ini hasilnya, movb biasa (tanpa hapus bagian atas data, bagian atas tetep utuh)
ini hasil signed bagian atas
ini hasil ketika bagian atas kita zerokan
catatan
movb %dh, %al
memindahkan rdx bagian high ke rax bagian bawah.
movabsq
simplenya, ini kepanjangan dari move absolute quad word (64 bit) contoh kecil
itu contoh initial moveabsq int 64 bit, lalu
contoh move 1 bytes
move 16 bit, 2 bytes word
move 32 bit, 4 bytes, tapi disini keformat sebagai int32 wkwk
full 64 bit move
x86_64 register (fiks technical grade)
analisis kenapa pakai movabsq, daripada movq
movq hanya bisa accept integer
analisis patch movq pakai 0xffffffff
ada asm
kita akan memaksa dari 0x7fffffff menjadi 0xffffffff untuk membuktikan bahwa harusnya movq error, dan digantikan oleh movabsq
initial dulu
lalu, next replace address 0x555555555119 dengan
set {unsigned char[8]}0x555555555119 = {0x48, 0xc7, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x90}
confirmed berubah jadi 0xffffffff disini
saatnya kita lanjutkan, apakah error
ext4 unknown RO compact features
this error come from linux kernel
/* Check that feature set is OK for a read-write mount */
if (ext4_has_unknown_ext4_ro_compat_features(sb)) {
ext4_msg(sb, KERN_ERR, "couldn't mount RDWR because of "
"unsupported optional features (%x)",
(le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_ro_compat) &
~EXT4_FEATURE_RO_COMPAT_SUPP));
return 0;
}
which EXT4_FEATURE_RO_COMPAT_SUPP
#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\
EXT4_FEATURE_RO_COMPAT_BIGALLOC |\
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
EXT4_FEATURE_RO_COMPAT_QUOTA |\
EXT4_FEATURE_RO_COMPAT_PROJECT |\
EXT4_FEATURE_RO_COMPAT_VERITY |\
EXT4_FEATURE_RO_COMPAT_ORPHAN_PRESENT)
#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/ext4.h#n2188
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/ext4.h#n2024
qemu custom cpio HDA
skrip init custom linux
qemu-system-x86_64 \-kernel ./vmlinux \
-nographic \
--append "console=tty0 console=ttyS0 panic=1 root=/dev/sda rootfstype=ext2" \
-hda root.img \
-m 1024 \
-vga none \
-display none \
-serial mon:stdio \
-no-reboot \
-initrd vfs/root.cpio.gz
generate cpio
find . | cpio -o -H newc | gzip > root.cpio.gz
``
step TCP
TCP steps
- isi dulu sockaddr_storage, isi pakai inet_pton(); .so_family = AF_INET; sin_port = htons(port)
- syscall socket(AF_INET, SOCK_STREAM, 0);
- setsocksopt(fd, SO_REUSEADDR = 1)
- bind(fd, ss_addr (cast dulu ke sockaddr_in), len nya)
- listen()
penjelasan ttg kenapa pakai sockaddr_storage dipakai https://stackoverflow.com/questions/19528820/difference-between-sockaddr-and-sockaddr-storage
kenapa harus setsocksopt SO_REUSEADDR? karna jika tidak, TCP Masuk ke timewait state.
sekiranya itu aja sih step TCP ini. untuk UDP pakai aja dgram.
GDB attach
jadi ceritanya, ada bug yg kala di run di terminal, ia buggy, pas di run di gdb, dia gak error sama sekali
gw bingung dah, nah disini. ternyata ada trick nya
-
jalanin dulu programnya kek biasa di terminal, dah running kan
-
ambil pid nya pakai ps aux | grep xyz
-
setelah dapet pid nya, jalankan gdb dengan mode attach pid
pakai sudo gdb -p 12345
- program akan freeze sejenak, pencet
c
,enter
nah, lakukan cara yg dipake buat reproduce bug nya, misal pakai nc buat nyepam tcp ke program. ok dapet bug nya
ni kalau kata orang internet, beberapa bug kek app multi thread agak susah di caught. pakai valgrind pun perlu flags2 khusus buat inspect sampai thread nya
hasil oprek socket programming, case socks5 server
bagian IETF SOCKS5 section 6
https://datatracker.ietf.org/doc/html/rfc1928#section-6
BND.ADDR haruslah berupa IPV4/IPV6 address, bukan domain :)
secara general, bentuk packet yg akan dikirim untuk versi IPV4 seperti ini
[0] [VER] => 0x5
[1] [REP] => 0x0
[2] [RSV] => 0x0
[3] [ATYP] => 0x1 atau 0x4
[4] [BND.ADDR] 0xac
[5] [BND.ADDR] 0x43
[6] [BND.ADDR] 0x93
[7] [BND.ADDR] 0x39
[8] [BND.PORT] 0x50
[9] [BND.PORT] 0x50
maka perhitungannya memory awal + 4 (karna 4 field dah dipakai), start dari sini, insert 4 oktet lagi ipv4 address, lalu insert 2 oktet uint8 sebagai port.
bagian BND.PORT itu unsigned int 16 bit. jadi harus digabung bitnya + diubah dari network order ke host order
fix ncurses kernel build
suppose
*** Unable to find the ncurses libraries or the
*** required header files.
*** 'make menuconfig' requires the ncurses libraries.
***
*** Install ncurses (ncurses-devel) and try again.
***
make[2]: *** [/home/fadhil_riyanto/linux-kernel/busybox-1.37.0/scripts/kconfig/lxdialog/Makefile:15: scripts/kconfig/lxdialog/dochecklxdialog] Error 1
make[1]: *** [/home/fadhil_riyanto/linux-kernel/busybox-1.37.0/scripts/kconfig/Makefile:14: menuconfig] Error 2
make: *** [Makefile:444: menuconfig] Error 2
maka solusi
nano scripts/kconfig/lxdialog/Makefile
ubah
always := $(hostprogs-y) dochecklxdialog
PHP-SRC variadic params
the source code: https://github.com/php/php-src/blob/ba6c00505d4218ff9fe4feb060f636524acfb125/ext/standard/array.c#L1204
mayan ngebantu jg gw ngepahami variadic params di php. ref: https://www.zend.com/resources/php-extensions/basic-php-structures
selfnote :
ZEND_PARSE_PARAMETERS_START(num_required_args, num_max_args) Z_PARAM_VARIADIC('*' or '+', destptr, argc);
catatan:
- * nol atau lebih parameter
- + satu atau lebih parameter
nb: akan diupdate berkala
ref: https://wiki.php.net/rfc/fast_zpp
PHP-SRC minit()
https://github.com/php/php-src/blob/3704947696fe0ee93e025fa85621d297ac7a1e4d/main/main.c#L2009
Ketika module PHP diload ke zend engine, yang dipanggil adalah MINIT(), di step ini yg terjadi cuman memory alokasi di ZendMM, dan disini engga ada process atau thread yg dijalan, pure cuman initialisasi data
nah, yang mentrigger MINIT() adalah zend_startup_modules(), trus secara beurutan, ia jg manggil RINIT() via PHP_RINIT_FUNCTION()
struct nya
zend_result (*request_startup_func)(INIT_FUNC_ARGS);
gcc compiler visibility
intresting buat diulik
class rectangle {
int width, height;
public:
void set_value(int, int);
int area();
};
void rectangle::set_value(int x, int y)
{
width = x;
height = y;
}
int rectangle::area()
{
return width * height;
}
compile pakai
g++ -Wall -c -fPIC abc.cc
g++ -o librec.so --shared abc.o
nm -C librec.so
akan ada
000000000000110e T rectangle::area()
00000000000010ea T rectangle::set_value(int, int)
nah, disitu kalau di compile pakai -fvisibility=hidden
ntar pas di cek pakai
nm -CD librec.so
bakalan gak ada. nah ini ada kaitannya sama
__attribute__ ((visibility ("hidden")))
tambahan: https://groups.google.com/g/ode-users/c/T3qiy-4dviQ
load effective address
computes a memory address using the same arithmetic that a MOV instruction uses. But unlike the MOV instruction, the LEA instruction just stores the computed address in its target register, instead of loading the contents of that address and storing it.
Consider your first LEA instruction:
tldr nya: mov bisa mengkalkulasi operasi aritmetika dari alamat memori, trus ngambil isinya kalau lea, ia cuman mengkalkulasi alamatnya, hasil itung2an nya disimpan ke operand2
lea -0x18(%ebp), %ebx
tambahan catatan
mov (op1, op2, op3), dest
equal (pseudo): mov op1 + op2 * op3, dest
and lea op1(op2), dest
equal lea op2 + op1, dest (address of op2 + op1, store result into dest)
bahasan tentang rip https://stackoverflow.com/questions/54745872/how-do-rip-relative-variable-references-like-rip-a-in-x86-64-gas-intel-sy
AT&T asm prelude
push eax equal with: mov [esp], eax sub esp, 4
pop eax get values out of stack equal with
add rsp, 4 mov eax, [esp]
Rust stuff
Welcome in this rust stuff section.
Rust cursor, How it works
Cursor in rust basically just a in-memory implementation of Seek. see fseek() here
Imagine, we have a file. and this is representation of contents
abcde
seek start from 1, is bcde
, start from 2 is cde
and so-on, this is also happen when we use seek from end, for example, seek end -1 is mean e
, -2 is de
, etc.
From code perspective
this is signature of cursor
pub struct Cursor<T> {
inner: T,
pos: u64,
}
and also, this struct implement Write and Seek
so, in order to understanding this concept, let code first in C
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct seekfd {
FILE *file;
};
int start_open(struct seekfd *seekfd) {
seekfd->file = fopen("a.txt", "r");
if (seekfd->file == NULL) {
fprintf(stderr, "%s", "error");
return -1;
}
}
int do_op(struct seekfd *seekfd) {
char allocated_buf[2048];
memset(allocated_buf, 0, 2048);
fseek(seekfd->file, 1, SEEK_SET);
int ret = fread(allocated_buf, 1, 3, seekfd->file);
printf("%s", allocated_buf);
}
int main() {
struct seekfd seekfd;
int ret = start_open(&seekfd);
if (ret < 0) {
return -9;
}
ret = do_op(&seekfd);
if (ret < 0) {
return ret;
}
}
compile with
clang fseek.c -o p -g
next step, create dummy files named a.txt with content abcdefghijklmnopqr
first run with fseek(seekfd->file, 0, SEEK_SET);
= abc
second run with fseek(seekfd->file, 1, SEEK_SET);
= bcd
etc...
this concept is basically same in Rust
Rust context
this is small example show Seek works (in-memory) instead utilize real file
use std::io::prelude::*;
use std::io::{self, SeekFrom};
use std::io::Cursor;
fn write_bytes<W: Write + Seek>(mut w: W) -> io::Result<()> {
w.seek(SeekFrom::Start(5))?;
for i in 1..6 {
w.write(&[i])?;
}
Ok(())
}
fn main() {
let mut buf = Cursor::new(vec![0; 20]);
write_bytes(&mut buf).unwrap();
println!("{:?}", &buf.get_ref()); // print vector
}
this is the output
[0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
instead, we change SeekFrom::Start(5)
with SeekFrom::Start(10)
, the write will started at offset 10. this is the output
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
Rust bytes has_remaining() method
this function return whatever any best left on buffer. example, let make simple tcp/ip
impl Connection {
pub fn new(stream: TcpStream) -> Connection {
Connection {
stream: BufWriter::new(stream),
buffer: BytesMut::with_capacity(4096)
}
}
pub async fn read(&mut self)
-> std::result::Result<Option<Frame>, Box<dyn std::error::Error + Send + Sync>> {
let _ = self.stream.read_buf(&mut self.buffer).await;
println!("hasremaining: {}", self.buffer.has_remaining());
while self.buffer.has_remaining() {
let bytes = self.buffer.get_u8();
println!("{} -> {}", bytes as char, self.buffer.has_remaining());
}
println!("{}", self.buffer.has_remaining());
// Frame::check(&mut self.buffer);
Ok(Some(Frame::Null))
}
}
let's see the server result using ncat
which the input is something look like this
[22:55:41] fadhil_riyanto@integral2 /home/fadhil_riyanto [SIGINT]
> ncat 127.0.0.1 6380
abc
from this output, we know
hasremaining: true <--- this is initial, didn't mean anything
a -> true <--- a already read, but next char is b, why this is true
b -> true <--- next is c, also true
c -> true <--- next is \n char, also true
-> false <--- this is false because no next chars
false <--- confirm
Also, get_u8
returns the first byte in the buffer. Each time it's called, it advances the position, so subsequent calls return the next bytes.
How Rust into() Box + Error analysis
suppose, we have function return signature like this
std::result::Result<Option<Frame>, Box<dyn std::error::Error + Send + Sync>>
and then, we return something like this from our function
return Err("connection reset".into())
how the into()
works?
analysis
look at this snippet
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
/// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
///
/// [`str`]: prim@str
///
/// # Examples
///
/// ```
/// use std::error::Error;
/// use std::mem;
///
/// let a_str_error = "a str error";
/// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
/// assert!(
/// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
/// ```
#[inline]
fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
From::from(String::from(err))
}
}
if we go deeper into From::from
, we found this
#[inline]
fn from(err: String) -> Box<dyn Error + Send + Sync + 'a> {
struct StringError(String);
impl Error for StringError {
#[allow(deprecated)]
fn description(&self) -> &str {
&self.0
}
}
impl fmt::Display for StringError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
// Purposefully skip printing "StringError(..)"
impl fmt::Debug for StringError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
Box::new(StringError(err))
}
nb: actually StringError is string aliases. then, we see in this section. we created a heap-allocated using Box::new(StringError(err))
.
Rust buffer advance
this simple article show how buffer advance works
use bytes::Buf;
fn main() {
let mut buf = &b"hello world"[..];
println!("{}", String::from_utf8_lossy(buf.chunk()));
buf.advance(6);
println!("{}", String::from_utf8_lossy(buf.chunk()));
}
and the result
hello world
world
Rust RESP get_line analysis
if we look at simple tokio redis example (mini redis), we can see how the data is parsed. look at this
the resp is generally read something like this `+abc\r\n'
this is the code that actually crop down the buffer
fn get_line<'a>(src: &mut Cursor<&'a [u8]>) -> Result<&'a [u8], Error> {
// Scan the bytes directly
let start = src.position() as usize;
// Scan to the second to last byte
let end = src.get_ref().len() - 1;
for i in start..end {
if src.get_ref()[i] == b'\r' && src.get_ref()[i + 1] == b'\n' {
// We found a line, update the position to be *after* the \n
src.set_position((i + 2) as u64);
// Return the line
return Ok(&src.get_ref()[start..i]);
}
}
Err(Error::Incomplete)
}
and I will show you how they works (algorithm)
variables setup
we have start
and end
, which consist of
let start = src.position() as usize;
let end = src.get_ref().len() - 1;
the src.position()
always return 0, also depending on the context. src.get_ref().len()
return the length of the buffer, for example, +rand\n\n
has length 7.
because we wan't to read two chars at the end, which is \r and \n
so we substract length with 1, this is avoid buffer overflow
suppose this situation:
buf: +rand\n\n
when we add everything with 1, we got this
idx: 012345 6 7
, it is idx[7]is found? no, so we need to sub with 1, the idx is something like this
idx: 012345 6
, no overflow
then we check the i
and i + 1
, make sure there is \r\n
set position
now, we set the cursor to the next incoming buffer. which after \r\n
src.set_position((i + 2) as u64);
suppose:
+rand\r\n+randomsomething\r\n
012345 6 ^
^^ ^ this is i + 2, indicates next buffer
ii+1 orig i
postgresql - get() generic function signature
In someday, i found
#[track_caller]
pub fn get<'a, I, T>(&'a self, idx: I) -> T
where
I: RowIndex + fmt::Display,
T: FromSql<'a>,
{
match self.get_inner(&idx) {
Ok(ok) => ok,
Err(err) => panic!("error retrieving column {}: {}", idx, err),
}
}
some sort of notes:
- https://doc.rust-lang.org/rust-by-example/generics.html
- https://serokell.io/blog/rust-generics
how to call it
let data2 = data_actual[0].get::<_, i32>(0);
Rust build logging
rust build usually don't show any output if you try to println!() in build.rs, in order to force this, use
println!("cargo:warning=start build!");
result
warning: ourcrate-rs@0.1.0: Something went wrong!
all docs: https://doc.rust-lang.org/cargo/reference/build-scripts.html
Rust tonic gRPC server build process
topik ini khusus membahas gRPC di rust,
build
contoh template build rs:
use std::{env, path::PathBuf};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let out_dir = PathBuf::from(
"/home/fadhil_riyanto/BALI64/fadev-service-rs/rpc/src/pb".to_string()
);
println!("cargo:warning=start build!");
tonic_build::configure()
.build_server(true)
.build_client(false)
.file_descriptor_set_path(out_dir.join("random_service.bin"))
.compile_protos(
&["proto/random_service.proto"],
&["proto"]
)?;
Ok(())
}
nb:
file_descriptor_set_path
: dipakai sebagai reflection, bakal ketemu kalau pakai grpcurl.build_server
danbuild_client
: disini ada 2 mode build, untuk server atau untuk client. maka kita set server true, client falsecompile_protos
: masing2 berisi 2 param yg menerima slice, param pertama berisi lokasi protobuf, param kedua berisi root foldernya.
anda bisa lihat-lihat contoh lain disini: https://github.com/hyperium/tonic/tree/master/examples
optional:
- use
.out_dir()
ketimbang harus nurut dengan apa yang OUT_DIR katakan
OUT_DIR
what it is, simplenya OUT_DIR
ini akan diset jika protobuf sudah di compile, dalam artian, file *.proto
diubah jadi kumpulan file *.rs
yang bakal di include sama macro, kemudian di compile
urutan compile adalah, macro dievaluasi dulu, baru compile, sampai sini masuk akal. ini macro signature nya
#[macro_export]
macro_rules! include_proto {
($package: tt) => {
include!(concat!(env!("OUT_DIR"), concat!("/", $package, ".rs")));
};
}
tambahan info bisa baca2 sendiri disini: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts, dan jg biasanya ini akan diinclude ke sebuah file handler. kira kira seperti itu
Rust tokio-postgres connection config example
first, this is example from the documentation
let (client, conn_ctx) = tokio_postgres::connect("host=localhost user=postgres", NoTls);
then, we want to convert it into config like ctx. see this
use tokio_postgres::{NoTls, Error};
#[tokio::main]
async fn main() {
let mut config = postgres::config::Config::new();
config.host("localhost");
config.user("fadhil_riyanto");
config.password("1921684338");
let client_ret = config.connect(NoTls);
}
Math
Welcome in this section.
Set operations formula
Union of Two Sets (cardinality)
\[ |A \cup B| = |A| + |B| - |A \cap B| \]
how to read:
whole A
and B
add together, its make a data duplication on center of venn diagram, we remove that duplication using \( |A \cap B| \)
Intersection (steps)
its flip of Union \[ |A \cup B| = |A| + |B| - |A \cap B| \] \[ |A \cap B| = |A| + |B| - |A \cup B| \]
Intersection of three sets
\[ |A \cup B \cup C| = |A| + |B| + |C| - |A \cap B| - |A \cap C| - |B \cap C| + |A \cap B \cap C| \]
how it works, de remove data duplication two times on \( |A \cap B| \), \( |B \cap C| \), and \( |B \cap C| \), then fill the empty section on the center which \( |A \cap B \cap C| \)
This is proof of concept by nice guy on internet: https://www.youtube.com/watch?v=vVZwe3TCJT8.
Difference
\[ |A - B| = |A| - |A \cup B| \]
Symetric difference
1. General formula
\[ A \space \triangle \space B = (A \cup B) - (A \cap B) \] Cardinals version: \[ | A \space \triangle \space B | = |A - B| + |B - A| \] \[ | A \space \triangle \space B | = |A| + |B| - 2|A \cap B| \]
2. Symetric difference properties
-
\( A \space \triangle \space B = B \space \triangle \space A \)
-
\( (A \space \triangle \space B) \space \triangle C = A \space \triangle \space (B \space \triangle C) \)
-
\( (A \space \triangle \space \emptyset) = A \), why?
- \(A \space \triangle \space B = (A \cup B) - (B \cap A) \)
- \(A \space \triangle \space \emptyset = (A \cup \emptyset) - (\emptyset \cap A) \), but
- \( (A \cup \emptyset) = A \) and \( (\emptyset \cap A) = \emptyset \)
- \( (A - \emptyset) = A \)
-
\( (A \space \triangle \space A) = \emptyset \)
Set stuff
there is some intresting question about discrete math
why \( \mathcal{P}(\emptyset) = \lbrace \emptyset \rbrace \)
consider \( \mathcal(S) \) where \( S \) is a set, for example
- if \( S = \lbrace a \rbrace \), then \( \mathcal{P}(S) = \lbrace \emptyset, \lbrace a \rbrace \rbrace \), same as \( \mathcal{P}(a) \)
- if \( S = \lbrace a, b \rbrace \), then \( \mathcal{P}(S) = \lbrace \emptyset, \lbrace a \rbrace, \lbrace b \rbrace, \lbrace a, b \rbrace \rbrace \), same as \( \mathcal{P}(a, b) \)
- if \( S = \lbrace \emptyset \rbrace \), then \( \mathcal{P}(S) = \lbrace \emptyset, \lbrace \emptyset \rbrace \rbrace \), same as \( \mathcal{P}(\emptyset) \)
so, because \( \lbrace \rbrace \) usually hidden, \( \mathcal{P}(\emptyset) = \lbrace \emptyset \rbrace \)
let \( A = \emptyset, B = \emptyset \), how to \( A \times B \)
Consider \( A \times B = \lbrace (a,b) | a \in A, b \in B \rbrace \)
because
- A is empty, no elements can be paired
- B is also empty
conlusion: no paired element = empty
proof by cardinality \( |A| = 0, |B| = 0, \text{so, when } |A \times B| = |A| \times |B| = 0 \times 0 = 0 \)
does \( P(\emptyset) = \lbrace \lbrace \rbrace \rbrace = \lbrace \emptyset \rbrace \) ?
true, this is due \( \lbrace \emptyset \rbrace \) same as \( \lbrace \lbrace \rbrace \rbrace \), then consider example \( P(a) = \lbrace \lbrace \rbrace, \lbrace a \rbrace\rbrace \)
Suppose X and Z are independent of each other
- \( | \mathcal{P}(X \cap Z)| \)
- \( | X - Z | \)
- \( | X \oplus Z | \)
- \( | X \cap Z | \)
- \( | \mathcal{P}(X) \cup \mathcal{P}(Z)| \)
- \( | \overline{\mathcal{P}(X) \cup \mathcal{P}(Z)}| \)
nb: bagian ini belum jadi
Logika
Ringkasan ini dibuat sebagian sebagian dari Kuliah IF1220 Matematika Diskrit ITB oleh bapak Rinaldi Munir. dan berbagai sumber seperti Wikipedia, ChatGPT dsb
Proposisi
adalah pernyataan bahwa suatu dua perbandingan adalah sama besar, contoh
- \( \frac{a}{b}=\frac{c}{d} \)
- \( 4 = 2 * 2 \)
- 13 adalah bilangan ganjil
- Untuk sembarang bilangan bulat \( n >= 0 \), maka \( 2n \) adalah genap
contoh yang bukan
- Isilah gelas tersebut dengan air
- \( x + 3 = 8 \)
- \( x > 3 \)
dan, Proposisi dilambangkan dengan huruf kecil seperti \( p, q, r, ... \)
Bentuk bentuk nya
- Proposisi atomik
bentuk proposisi tunggal, contoh
- 2n selalu genap untuk n=0, 1, 2, …
- Ibukota Maluku Utara adalah Ternate
- proposisi majemuk
diantaranya:
- conjunction (and): \( \wedge \)
- disjunction (or): \( \vee \)
- negation (!n): \( ~ \)
- exclusive disjunction (xor): \( \oplus \)
Table
p | q | r | p ∧ q | ¬q | ¬q ∧ r | (p ∧ q) ∨ (¬q ∧ r) |
---|---|---|---|---|---|---|
T | T | T | T | F | F | T |
T | T | F | T | F | F | T |
T | F | T | F | T | T | T |
T | F | F | F | T | F | F |
F | T | T | F | F | F | F |
F | T | F | F | F | F | F |
F | F | T | F | T | T | T |
F | F | F | F | T | F | F |
nb:
- Tautologi adalah pernyataan logika yang selalu benar, tidak peduli nilai kebenaran dari komponen-komponennya. contoh
p | q | p ∧ q | ¬(p ∧ q) | p ∨ ¬(p ∧ q) |
---|---|---|---|---|
T | T | T | F | T |
T | F | F | T | T |
F | T | F | T | T |
F | F | F | T | T |
- Kontradiksi adalah pernyataan logika yang selalu salah, tidak peduli nilai kebenaran dari komponen-komponennya. contoh
p | q | p ∧ q | p ∨ q | ¬(p ∨ q) | (p ∧ q) ∧ ¬(p ∨ q) |
---|---|---|---|---|---|
T | T | T | T | F | F |
T | F | F | T | F | F |
F | T | F | T | F | F |
F | F | F | F | T | F |
p | q | p ∧ q | ¬(p ∧ q) | ¬p | ¬q | ¬p ∨ ¬q |
---|---|---|---|---|---|---|
T | T | T | F | F | F | F |
T | F | F | T | F | T | T |
F | T | F | T | T | F | T |
F | F | F | T | T | T | T |
Hukum hukum nya
Bahasa Indonesia | Bahasa Inggris | Contoh |
---|---|---|
Hukum Identitas | Identity Law | p ∧ T ≡ p , p ∨ F ≡ p |
Hukum Dominasi | Domination Law | p ∨ T ≡ T , p ∧ F ≡ F |
Hukum Idempotensi | Idempotent Law | p ∨ p ≡ p , p ∧ p ≡ p |
Hukum Negasi | Negation Law | p ∨ ¬p ≡ T , p ∧ ¬p ≡ F |
Hukum Komutatif | Commutative Law | p ∨ q ≡ q ∨ p , p ∧ q ≡ q ∧ p |
Hukum Asosiatif | Associative Law | (p ∨ q) ∨ r ≡ p ∨ (q ∨ r) |
Hukum Distributif | Distributive Law | p ∨ (q ∧ r) ≡ (p ∨ q) ∧ (p ∨ r) |
Hukum De Morgan | De Morgan’s Laws | ¬(p ∧ q) ≡ ¬p ∨ ¬q , ¬(p ∨ q) ≡ ¬p ∧ ¬q |
Hukum Involusi | Double Negation / Involution | ¬(¬p) ≡ p |
Hukum Implikasi | Implication Law | p → q ≡ ¬p ∨ q |
Hukum Biimplikasi | Biconditional Law | p ↔ q ≡ (p → q) ∧ (q → p) |
Implikasi
Disebut juga proposisi bersyarat, seperti jika x maka y, notasinya \( p \rightarrow q\). \( p \) nya adalah condition, \( q \) nya adalah conlusion
p | q | p → q |
---|---|---|
T | T | T |
T | F | F |
F | T | T |
F | F | T |
versi versinya jika dijadikan teks
- Jika p, maka q (if p, then q)
- Jika p, q (if p, q)
- p mengakibatkan q (p implies q)
- q jika p (q if p)
- p hanya jika q (p only if q)
- p syarat cukup untuk q (p is sufficient condition for q)
- q syarat perlu bagi p (q is necessary condition for q)
- q bilamana p (q whenever p)
- q mengikuti dari p (q follows from p)
penjelasan kenapa \( F \rightarrow F = T \)
“If I win the lottery, I’ll buy you a car.”
I didn't win the lottery → (False)
I didn't buy a car → (False)
dan juga \( P \rightarrow Q \) sebenarnya sama dengan \( \sim{P} \vee Q \)
Penjelasan kenapa \( \sim (p \rightarrow q )\) itu sama dengan \( p \space \wedge \sim{q} \)
Kita tahu bahwa \( p \rightarrow q \) itu sebenarnya sama dengan \( \sim{p} \vee p \) , maka steps yang dibutuhkan hanya
- \( \sim(p \rightarrow q) \)
- \( \sim(\sim{p} \vee q) \)
- \( p \space \wedge \sim{q} \)
tabel varian implikasi (Proporsi bersyarat)
- Konvers (kebalikan): \( q \rightarrow p \)
- Invers : \( \sim p \rightarrow \sim q \)
- Kontraposisi : \( \sim q \rightarrow \sim p \)
p | q | ¬p | ¬q | p → q | q → p | ¬p → ¬q | ¬q → ¬p |
---|---|---|---|---|---|---|---|
T | T | F | F | T | T | T | T |
T | F | F | T | F | T | T | F |
F | T | T | F | T | F | F | T |
F | F | T | T | T | T | T | T |
Bi-impication
Intinya, operand kanan kiri harus sama, entah sama sama true, atau sama sama false. notasinya: \( p \leftrightarrow q \)
tabel kebenaran
p | q | p ↔ q |
---|---|---|
T | T | T |
T | F | F |
F | T | F |
F | F | T |
contoh
p | q | p ↔ q | p → q | q → p | (p → q) ∧ (q → p) |
---|---|---|---|---|---|
T | T | T | T | T | T |
T | F | F | F | T | F |
F | T | F | T | F | F |
F | F | T | T | T | T |
analogi simple:
-
Jika suatu bilangan genap, maka habis dibagi 2
: \( \text{true} \leftrightarrow \text{true} = \text{true} \) -
Jika suatu bilangan bukan genap, maka tidak akan habis dibagi 2
: \( \text{false} \leftrightarrow \text{false} = \text{true} \)
kumpulan soal Matematika Diskrit
No. 1
Dalam sebuah survei terhadap 120 orang, diperoleh data sebagai berikut:
- 65 orang suka kopi
- 70 orang suka teh
- 50 orang suka cokelat
- 30 orang suka kopi dan teh
- 28 orang suka kopi dan cokelat
- 26 orang suka teh dan cokelat
- 15 orang suka semua minuman
- Semua orang minimal menyukai satu jenis minuman
Tentukan:
- Banyak orang yang hanya suka kopi
- Banyak orang yang suka teh dan cokelat, tapi tidak suka kopi
- Banyak orang yang suka tepat dua jenis minuman
- Banyak orang yang hanya suka satu jenis minuman
No. 2
Jika diketahui
- S = {1,2,3 …, 15},
- A = { 2,3,5,7},
- B = { 1,3,5,7,9},
- C = {2,4,6,8}
Tentukan :
- A ∪ B ∪ C
- A ∩ C
- B - A
- (A’ ∩ B) - C
- (B - C) ∩ A’
No. 3
Dalam survei terhadap 80 mahasiswa, diperoleh data:
- 45 mahasiswa suka Matematika
- 38 mahasiswa suka Fisika
- 40 mahasiswa suka Kimia
- 20 mahasiswa suka Matematika dan Fisika
- 25 mahasiswa suka Fisika dan Kimia
- 18 mahasiswa suka Matematika dan Kimia
- 10 mahasiswa suka ketiga mata kuliah
- 8 mahasiswa tidak suka semua mata kuliah
tentukan
- Banyak mahasiswa yang suka hanya Matematika
- Banyak mahasiswa yang suka tepat dua mata kuliah
- Banyak mahasiswa yang suka Matematika atau Kimia tapi tidak Fisika
- Banyak mahasiswa yang suka hanya satu mata kuliah
format latex menyusul
asal usul rumus sudut vektor
awal mula dari rumus entah berantah ini. link untuk oprek rumus: https://proofwiki.org/wiki/Cosine_Formula_for_Dot_Product
\[ \vec{A} \cdot \vec{B} = |\vec{A}| |\vec{B}| cos(\theta) \]
lalu \[ \frac{\vec{A} \cdot \vec{B}}{|\vec{A}| |\vec{B}|} = cos(\theta) \]
lalu kita bisa balik, menjadi \[ cos(\theta) = \frac{\vec{A} \cdot \vec{B}}{|\vec{A}| |\vec{B}|} \]
\[ arccos(\frac{\vec{A} \cdot \vec{B}}{|\vec{A}| |\vec{B}|}) = \theta \]
solved!
transformasi elementer
beberapa notasi aneh disini diderive dari PPT kampus.
- \( H_{ij}A \): Swap baris i dengan baris j
- \( H_i^{(k)} \): mengalikan baris i dengan konstanta k
- \( H_{ij}^{(k)} \): hitung dulu konstanta k dikali baris j, lalu hasilnya ditambah baris i, simpan jg hasilnya ke baris i
- \( H_{i \space \space \space \space \space \space \space j}^{\space \space (k) \space \space \space (z)}(A)_i \): intinya, baris ke i dikalikan dgn k, kalau udah lanjut hitung baris j dikalikan z. setelah itu hasilnya tentusaja simpan ke i hasil itung2 an tadi.
Cryptography
Alur konek ke RPC server telegram
step ini dibuat oleh seseorang dari masa lalu sekitar tahun 2020 yang akunnya telah terhapus, credit kepada Butthx
`originals written in telegram chat, but because I want to preserve it. I write it here
step 1:
Bikin koneksi ke server telegram pakai TCP yang tersedia (disini gwa pakai TCPIntermediate)
step 2:
Bikin random nonce dengan value int128
step 3:
Kirim bytes dari ReqPqMulti dengan value bytes dari nonce tadi.
step 4:
pick salah satu dari beberapa publick fingerprints yang diberikan dari results step3.
step 5:
Lakuin faktor bilangan pq yang diberikan dari results step3, dapetin lagi hasil pembagian dari pq tadi dengan hasil faktor, terus urutkan dari yang terkecil. untuk yang kecil di kasih nama p dan yang besar kasih nama g.
step 6:
bikin nonce baru (jangan ubah nonce yang lama) dengan value random int256.
step 7:
bikin hash (sha1) dari bytes PQInnerData ke telegram: bytes[pq,bytes p,bytes q,nonce,nonce baru,server nonce (dapet dari step3)]
step 8:
bikin padding dengan random bytes dengan panjang -(length bytes PQInnerData + length sha1) mod 255
step 9:
encrypt bytes[sha,bytes PQInnerData,padding] dengan RSA (pakai publik fingerprints tadi)
step 10:
kirim bytes ReqDhParams: bytes[nonce,server nonce, bytes p, bytes q, encrypted data (step9) ,fingerprint]
step 11:
bikin temporary aes key: bytes[sha1[bytes nonce baru, bytes server nonce],sha1[bytes server nonce, bytes nonce baru] slice 0 – 12]
step 12:
bikin temporary aes initial vector (IV): bytes[sha1[bytes server nonce, bytes nonce baru] slice 12 – end, sha1[bytes nonce baru,bytes nonce baru], bytes[nonce baru] slice 0 – 4 ]
step 13:
decrypt encryptedAnswer (dapet dari step 10) menggunakan AES-256-IGE pakai key sama iv tadi.
step 14:
parse decrypted answer tadi ke TLSchema/TLObject
step 15:
bikin random int(panjang 256 bytes, bukan int256 ygy) kita beri nama b
step 16:
dapetin g_b dengan (g ** b) mod dh_prime
- g, dh_prime → dapet dari step 14
step 17:
bikin hash sha1 dari bytes[ClientDhInnerData[nonce, server nonce, 0,unsigned big bytes g_b length 256]]
step 18:
bikin padding dengan length -(length bytes ClientDhInnerData + length sha1) mod 16
step 19:
encrypt bytes[bytes step 17,bytes ClientDhInnerData, padding ] dengan AES-256-IGE, key sama iv masih menggunakan yang step 11.
step 20:
kirim bytes[SetClientDhParams[nonce, server nonce, bytes step 19]]
step 21:
Bikin auth key dengan big-unsigned-bytes[big-u-int(g_a) ** b mod dhPrime] length 256
step 22:
Lakuin security check..
notes: Untuk format pengiriman bytes:
bytes[sessionId,messageId,length content,content]
karena belum ada authkey, jadi sessionId = Buffer.alloc(8)
untuk dapetin real data dari telegram, slice bytes yang di terima dari 20 – end
pengiriman content selalu bentuk bytes, jadi semua parameter jadiin bytes :)
/**
* tgsnake - Telegram MTProto framework for nodejs.
* Copyright (C) 2022 butthx <https://github.com/butthx>
*
* THIS FILE IS PART OF TGSNAKE
*
* tgsnake is a free software : you can redistribute it and/or modify
* it under the terms of the MIT License as published.
*/
export const DCTest = {
1: '149.154.175.10',
2: '149.154.167.40',
3: '149.154.175.117',
};
export const DCProd = {
1: '149.154.175.53',
2: '149.154.167.51',
3: '149.154.175.100',
4: '149.154.167.91',
5: '91.108.56.130',
};
export const DCProdMedia = {
2: '149.154.167.151',
4: '149.154.164.250',
};
export const DCTestIPV6 = {
1: '2001:b28:f23d:f001::e',
2: '2001:67c:4e8:f002::e',
3: '2001:b28:f23d:f003::e',
};
export const DCProdIPV6 = {
1: '2001:b28:f23d:f001::a',
2: '2001:67c:4e8:f002::a',
3: '2001:b28:f23d:f003::a',
4: '2001:67c:4e8:f004::a',
5: '2001:b28:f23f:f005::a',
};
export const DCProdMediaIPV6 = {
2: '2001:067c:04e8:f002:0000:0000:0000:000b',
4: '2001:067c:04e8:f004:0000:0000:0000:000b',
};
export function DataCenter(
dcId: number,
testMode: boolean,
ipv6: boolean,
media: boolean
): [ip: string, port: number] {
if (testMode) {
return [ipv6 ? DCTestIPV6[dcId] : DCTest[dcId], 80];
} else {
if (media) {
return [ipv6 ? DCProdMediaIPV6[dcId] : DCProdMedia[dcId], 443];
} else {
return [ipv6 ? DCProdIPV6[dcId] : DCProd[dcId], 443];
}
}
}
ca-certificates
draft: mengoprek kriptografi dibalik HTTPS & konsep public private key pair dan juga peran CA authority, kenapa mereka harus dimasukkan ke package ???
dan juga kenapa MITM (Man in the Middle) bisa melogging jaringan, ketika certificate telah dipasang. kenapa hanya dengan certificate
mitm bisa mendecode data yang lewat.
Server
Cgit setup
Ku mau share pengalaman bikin self hosting git server, pakai cgit, biar engga kalah aja sama git.kernel.org dan kernel.dk wkwk
step satu, include dir nya sites-available spt biasa, contoh config nya https://gist.github.com/fadhil-riyanto/328f2cc0607eb58b713cdeaa473d08ee, lalu config untuk sites-available nya https://gist.github.com/fadhil-riyanto/c2e26de30c97600e4ee9342aefbd6ece
nb: install fcgiwrap dulu
lalu edit /etc/cgitrc, contoh config: https://gist.github.com/fadhil-riyanto/4033e6ce59a35568c31dbd5e5a1d29bd
harusnya sampai sini, cgit dah bisa diakses, cuman empty repository aja.
ok, lalu kita ke permission2 nya, pertama2 pakai akun root, tldr
cd /root
mkdir git
cd git
mkdir user1, misal aja mkdir fadhil_riyanto
cd fadhil_riyanto
clone git apapun disini, misal
git clone https://github.com/fadhil-riyanto/reponame.git --bare
(harus pakai bare)
posisi dir ini di /root/git/fadhil-riyanto/reponame.git
ok, balik ke parent dir, posisi di /root/git
lakukan chown -R fadhil_riyanto fadhil-riyanto
, jika engga nanti error "git submodule update" failed with 'fatal: detected dubious ownership in repository at...' etc...
ok, saatnya push
git remote add cgit fadhil_riyanto@123.123.111.222:/root/git/fadhil-riyanto/reponame.git
config HTTPS nginx
Cara config HTTPS di server pakai certbot (NGINX)
- apt install certbot python3-certbot-nginx
- verify config na pakai nginx -t
- generate cert na pakai certbot --nginx -d namasite.com
ganti namasite.com dengan embel2 di /etc/nginx/sites-enabled/somefile.conf
didalamnya kan ada server_name, nah diganti dgn itu
Setup virtual network interface
cara setup virtual ethernet + assign ip nya
sudo ip link add veth0 type dummy
bisa dicek pakai ip addr
[11:11:35] fadhil_riyanto@integral2 /etc/systemd/network
> ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp2s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
link/ether 2c:4d:54:c6:f2:0c brd ff:ff:ff:ff:ff:ff
altname enx2c4d54c6f20c
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether f0:03:8c:66:9c:21 brd ff:ff:ff:ff:ff:ff
inet 192.168.5.44/24 brd 192.168.5.255 scope global dynamic noprefixroute wlan0
valid_lft 581sec preferred_lft 581sec
inet 192.168.5.197/24 metric 1024 brd 192.168.5.255 scope global secondary dynamic wlan0
valid_lft 582sec preferred_lft 582sec
inet6 fe80::5574:5771:be47:2f7b/64 scope link noprefixroute
valid_lft forever preferred_lft forever
inet6 fe80::f203:8cff:fe66:9c21/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
4: veth0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether 76:4d:3f:3d:11:7f brd ff:ff:ff:ff:ff:ff
inet6 fe80::744d:3fff:fe3d:117f/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
lalu assign ip nya
sudo ip addr add 192.168.100.10/24 dev veth0
sudo ip link set veth0 up
dan bisa diping juga
untuk remove interface nya bisa pakai
sudo ip link delete vnet0
some sorts of equalivalent command
- Create bridge:
brctl addbr br0
ip link add br0 type bridge
- Delete bridge:
brctl delbr br0
ip link delete br0 - Add interface to bridge:
brctl addif br0 eth0
ip link set eth0 master br0 - Remove interface from bridge:
brctl delif br0 eth0
ip link set eth0 nomaster - Show bridge info:
brctl show
orbrctl show br0
bridge link show
orip link show master br0
- Enable/disable STP:
brctl stp br0 on/off
bridge link set dev eth0 guard off/on
(note: STP enable/disable logic is reversed)
ip aliasing
satu interface bisa punya lebih dari 1 IP dinamai sebagai IP aliasing. contoh
eth0
bisa punya 2 ip dengan cara
ip addr add 192.168.1.100/24 dev eth0
ip addr add 192.168.1.101/24 dev eth0
atau bisa juga ada 2 interface, katakanlah eth0
dengan eth1
, masing2 punya ip nya sendiri2 dengan cara
ip addr add 192.168.1.10/24 dev eth0
ip addr add 10.0.0.5/24 dev eth1
tambahan
untuk ngeremove salah satu ip nya, bisa dengan ip addr del <IP NYA>/<CIDR> dev <IFACE>
Setup bridge enp0s16u1
- setup dulu bridgenya pakai
ip link add br0 type bridge
- buat enp0s16u1 sebagai master dari br0, pakai
ip link set enp0s16u1 master br0
- catatan, wlan0 tidak bisa di add. https://bbs.archlinux.org/viewtopic.php?id=264651, https://wiki.archlinux.org/title/Network_bridge#Wireless_interface_on_a_bridge
- lalu enable semua interface nya
sudo ip link set dev enp0s16u1 up
sudo ip link set dev br0 up
- set dhcp
sudo dhclient br0
- nb, ditahap ini, harusnya sudah dapat ip dan bisa ping keluar.
- hapus ip bawaan enp0s16u1 dan pakai br0 sebagai default interface pakai
sudo ip addr flush dev enp0s16u1
bisa di test dengan
- hapus dahulu ip yang tadi diberikan ke br0 pakai
sudo dhclient -r br0
, pastikan ip nya kosong - lalu hapus ip milik enp0s16u1
- test ping
- lalu lakukan lagi
sudo dhclient br0
reverse command
Pakai ini untuk in-case ada kesalahan
hapus ip br0
ip addr show br0
sudo ip addr del 192.168.1.10/24 dev br0
tambahan, kadang tidak bener2 kehapus karna mungkin NetworkManager, systemd-networkd, dhclient aktif.
nb: untuk dhcp kadang NetworkManager sama systemd-networkd bertabrakan, solusinya stop dahulu pakai
sudo systemctl stop systemd-networkd.socket
sudo systemctl stop systemd-networkd
next, buat bridge ke VM. topologi
[Internet]
|
Router
|
eth0 (on host) → br0 (bridge)
|
+--------+--------+--------+
| | | |
VM1 VM2 VM3 etc.
↳ 192.168.12.101 192.168.12.102 ...
mulai dari sini akan utak atik veth
setup veth manual
sudo ip link add veth0 type veth peer name veth0-peer
sudo ip link set veth0 master br0
sudo ip link set veth0 up
sudo ip link set veth0-peer up
sudo dhclient veth0-peer
topologinya kira2 seperti ini
+---------------------------+
| Linux Host |
| |
| +-------------------+ |
| | br0 | | ← bridge acting as a virtual switch
| +--------+----------+ |
| | |
| veth0 ... ← more veths for other containers/VMs
| |
+------------+--------------+
|
| (virtual cable)
|
veth0-peer
|
+------------------+
| Container/VM | ← gets its own IP
+------------------+
lanjut assign veth-peer ke qemu (pakai tap device)
topology:
Linux Host
+------------------+
| br0 | ← acts as switch
+--+-----------+---+
| |
eth0 tap0 ← tap device for QEMU VM
|
QEMU VM
attach
sudo ip tuntap add dev tap0 mode tap
sudo ip link set tap0 up
sudo ip link set tap0 master br0
qemu
sudo qemu-system-x86_64 \
-enable-kvm \
-m 2048 \
-hda ubuntu.qcow2 \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net-pci,netdev=net0
test qemu mikrotik
qemu-system-x86_64 \
-enable-kvm \
-boot order=d \
-drive file=chr.qcow2,format=qcow2 \
-m 4G \
-smp 4 \
-net user,hostfwd=tcp::10022-:22,hostfwd=tcp::8080-:8080 \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net-pci,netdev=net0
untuk test nya, bisa dengan
- cek ip mikrotik pakai
/ip address print
- lalu
ip netns exec namespace_satu ping <IP NYA>
- Bisa juga pakai dummy http server php, caranya
sudo ip netns exec namespace_satu php -S 192.168.12.82:1234
(cek dahulu ip namespace pakai ip addr)
contoh setup pakai namespace
- create dulu pakai
sudo ip netns add namespace_satu
- set
sudo ip link set veth0-peer netns namespace_satu
- cek dahulu, pastikan didalamnnya masih kosong ip nya, pakai
sudo ip netns exec namespace_satu ip addr
- lalu kita nyalakan veth0-peer nya
sudo ip netns exec namespace_satu ip link set dev veth0-peer up
, tapi tetap saja masih belum dapat ip. maka next kita exec dhclient pakaisudo ip netns exec namespace_satu dhclient veth0-peer
- test ping keluar
Setup shadowsocks proxy server
shadowsocks-libev is available in the official repository for Debian 9("Stretch"), unstable, Ubuntu 16.10 and later derivatives:
sudo apt update
sudo apt install shadowsocks-libev
then, create a file config on /etc/shadowsocks-libev/config.json
which has contents something like this
{
"server":["::1", "10.1.1.4"],
"mode":"tcp_and_udp",
"server_port":8388,
"local_port":1080,
"password":"1u21wW3E0bwu",
"timeout":86400,
"method":"chacha20-ietf-poly1305"
}
in this case, I use 10.1.1.4
as local ip, then forwarded through firewall to the public addr.
then, sudo systemctl start shadowsocks-libev
ref: https://shadowsocks.org/doc/configs.html
connect
Alpine htop install on live QEMU
create disk first
qemu-img create -f qcow2 alpine-1.qcow2 1G
start qemu
download iso here https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/x86_64/alpine-virt-3.21.3-x86_64.iso
qemu-system-x86_64 \
-enable-kvm \
-m 256 \
-smp 4 \
-cpu host \
-drive file=pc-1.qcow2,format=qcow2 \
-cdrom alpine-virt-3.21.3-x86_64.iso \
-boot d \
-net nic \
-net user -nographic
default username is root
, password left blank, just enter
set eth0 up & DHCP
ip link set dev eth0 up
udhcpc -i eth0
ping 1.1.1.1
(testing)
for /etc/resolv.conf
, change to nameserver 1.1.1.1
patch apk configuration
cp /etc/apk/repositories /etc/apk/repositories-old
--- repositories-old
+++ repositories
@@ -1 +1,2 @@
-/media/cdrom/apks
+http://dl-cdn.alpinelinux.org/alpine/v3.21/main
+http://dl-cdn.alpinelinux.org/alpine/v3.21/community
update
apk update
apk cache download
apk cache -v sync
setup partition
set it with your needs, I use entire disk in this docs
make sure first your ext4 kernel module is installed & loaded by typing
lsmod | grep ext4
: checkmodprobe ext4
lsmod | grep ext4
: recheck again
the output is should be something like this
then we can move forward to ext4 partition generation
partitioning
install parted first using apk add parted
, check your disk first using fdisk -l
, for example there is /dev/sda
parted section
run parted /dev/sda
, inside of parted is
unit s
mklabel [gpt/msdos]
: I use msdos anywayprint
: identify disk size by see on section something like Disk /dev/sda: 2097152s, there has 2097152s sector, so I use 2097152 - (2948 * 2), which is 2093056smkpart
primary
ext4
2048s
2093056s
q
resulted partition:
setup diskless install
warn: you need to enable ext4 kernel module or you'll get mount: mounting /dev/sda1 on /media/sda1 failed: Invalid argument
when mounting
modprobe ext4
apk add e2fsprogs
formkfs.ext4
commandmkfs.ext4 /dev/sda1
mount /dev/sda1 /media/sda1
: mount location should be located on/media
, not/mnt
then, you can do normal setup-alpine
, except for this thing
- Which disk(s) would you like to use? (or '?' for help or 'none') [none] none
- Enter where to store configs ('floppy', 'sda1', 'usb' or 'none') [sda1] sda1
- Enter apk cache directory (or '?' or 'none') [/media/sda1/cache] /media/sda1/cache
LBU
run lbu commit
Run router-OS on qemu
on normal interface
qemu-system-x86_64 \
-enable-kvm \
-boot order=d \
-cdrom chr-6.49.18.img \
-drive file=chr.qcow2,format=qcow2 \
-m 4G \
-smp 4 \
-net user,hostfwd=tcp::10022-:22,hostfwd=tcp::8291-:8291 \
-net nic
setup linux bridge between RouterOS & Alpine linux hosts
this docs is second part of this
first thing that we need to do is create a copy of qcow2 alpine, so we do not need to re-install again. do not forget to change the hostname & password for easy identification
setup bridge
sudo ip link add br0-lan type bridge
sudo ip link add br1-lan type bridge
setup TAP
tap0 & tap1 connected to br0-lan tap2 & tap3 connected to br1-lan
sudo ip tuntap add dev tap0 mode tap
sudo ip tuntap add dev tap1 mode tap
sudo ip tuntap add dev tap2 mode tap
sudo ip tuntap add dev tap3 mode tap
sudo ip link set tap0 master br0-lan
sudo ip link set tap1 master br0-lan
sudo ip link set tap2 master br1-lan
sudo ip link set tap3 master br1-lan
sudo ip link set tap0 up
sudo ip link set tap1 up
sudo ip link set tap2 up
sudo ip link set tap3 up
launch mikrotik ISO
qemu-system-x86_64 \
-enable-kvm \
-boot order=d \
-drive file=chr.qcow2,format=qcow2 \
-m 256M \
-smp 4 \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net-pci,netdev=net0,mac=02:11:2a:3b:ff:c3 \
-netdev tap,id=net1,ifname=tap2,script=no,downscript=no \
-device virtio-net-pci,netdev=net1,mac=02:1a:f2:f1:21:b5 \
-nographic \
-net user,hostfwd=tcp::10022-:22,hostfwd=tcp::8291-:8291 \
-net nic
based on topology, we know that
02:11:2a:3b:ff:c3
used by tap0 (in routerOS, bridge 0)02:1a:f2:f1:21:b5
used by tap2 (in routerOS, bridge 1)tap1
&tap3
used by alpine virtual machine
now run alpine iso
alpine (as pc-1)
qemu-system-x86_64 \
-enable-kvm \
-m 256 \
-smp 4 \
-cpu host \
-drive file=pc-1.qcow2,format=qcow2 \
-cdrom alpine-virt-3.21.3-x86_64.iso \
-boot d \
-nographic \
-netdev tap,id=net0,ifname=tap1,script=no,downscript=no \
-device virtio-net-pci,netdev=net0
alpine (as pc-3)
qemu-system-x86_64 \
-enable-kvm \
-m 256 \
-smp 4 \
-cpu host \
-drive file=pc-2.qcow2,format=qcow2 \
-cdrom alpine-virt-3.21.3-x86_64.iso \
-boot d \
-nographic \
-netdev tap,id=net0,ifname=tap3,script=no,downscript=no \
-device virtio-net-pci,netdev=net0
WinBox config
first, we need to see the configuration & which etherX by looking to spesific mac-addr, we find out that
[admin@MikroTik] > /interface print
Flags: D - dynamic, X - disabled, R - running, S - slave
# NAME TYPE ACTUAL-MTU L2MTU MAX-L2MTU MAC-ADDRESS
0 R ;;; wan
ether1 ether 1500 52:54:00:12:34:56
1 R ether4 ether 1500 02:11:2A:3B:FF:C3
2 R ether5 ether 1500 02:1A:F2:F1:21:B5
[admin@MikroTik] >
next thing, lets configure our ip using winbox, this is ip configuration
DHCP server section
now, try run udhcpc -i eth0
on each vm
result on pc-1
result on pc-2
Linux iptables preview (try making a nat)
for example, iptables -t nat
the t option from manpage is
filter:
This is the default table (if no -t option is passed). It contains the built-in
chains INPUT (for packets destined to local sockets), FORWARD (for packets being
routed through the box), and OUTPUT (for locally-generated packets).
nat:
This table is consulted when a packet that creates a new connection is encountered.
It consists of four built-ins: PREROUTING (for altering packets as soon as they come
in), INPUT (for altering packets destined for local sockets), OUTPUT (for altering
locally-generated packets before routing), and POSTROUTING (for altering packets as
they are about to go out). IPv6 NAT support is available since kernel 3.7.
mangle:
This table is used for specialized packet alteration. Until kernel 2.4.17 it had two
built-in chains: PREROUTING (for altering incoming packets before routing) and OUTPUT
(for altering locally-generated packets before routing). Since kernel 2.4.18, three
other built-in chains are also supported: INPUT (for packets coming into the box it‐
self), FORWARD (for altering packets being routed through the box), and POSTROUTING
(for altering packets as they are about to go out).
raw:
This table is used mainly for configuring exemptions from connection tracking in com‐
bination with the NOTRACK target. It registers at the netfilter hooks with higher
priority and is thus called before ip_conntrack, or any other IP tables. It provides
the following built-in chains: PREROUTING (for packets arriving via any network in‐
terface) and OUTPUT (for packets generated by local processes).
security:
This table is used for Mandatory Access Control (MAC) networking rules, such as those
enabled by the SECMARK and CONNSECMARK targets. Mandatory Access Control is imple‐
mented by Linux Security Modules such as SELinux. The security table is called after
the filter table, allowing any Discretionary Access Control (DAC) rules in the filter
table to take effect before MAC rules. This table provides the following built-in
chains: INPUT (for packets coming into the box itself), OUTPUT (for altering locally-
generated packets before routing), and FORWARD (for altering packets being routed
through the box).
What kind of tables in iptables
according from archlinux wiki
iptables contains five tables:
- raw is used only for configuring packets so that they are exempt from connection tracking.
- filter is the default table, and is where all the actions typically associated with a firewall take place.
- nat is used for network address translation (e.g. port forwarding).
- mangle is used for specialized packet alterations.
- security is used for Mandatory Access Control networking rules (e.g. SELinux -- see this article for more details).
In most common use cases, you will only use two of these: filter and nat. The other tables are aimed at complex configurations involving multiple routers and routing decisions and are in any case beyond the scope of these introductory remarks.
Tables & chain details
all iptables chain information can be gathered by this command
sudo iptables -t filter -L
sudo iptables -t nat -L
sudo iptables -t mangle -L
sudo iptables -t raw -L
sudo iptables -t security -L
this is list of all chain by corresponding table
table raw
- PREROUTING
- OUTPUT
table nat
- PREROUTING
- INPUT
- OUTPUT
- POSTROUTING
table mangle
- PREROUTING
- INPUT
- FORWARD
- OUTPUT
- POSTROUTING
table filter
- INPUT
- FORWARD
- OUTPUT
table security
- INPUT
- FORWARD
- OUTPUT
we will focus on NAT
section.
machine session
In iptables, packet often categorized as 4 different state, such
- NEW
- ESTABLISHED
- RELATED
- INVALID
this connection tracking is done by a special framework within the kernel called conntrack
command lists
this is some special iptables command collection
iptables --list-rules
: show all ip rulesiptables --table nat --list --line-numbers
: will useful if you want to delete spesific rule, i.e, duplicated rulesudo iptables --table nat -D POSTROUTING 2
example: delete rule 2
create your own chain
iptables -N chain_name
: eq:--new-chain
iptables -A chain_name -p icmp -j accept
(example)
make changes permanent
sudo iptables-save > /etc/iptables/rules.v4
tables explanation
> sudo iptables --table nat --list
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- anywhere anywhere
MASQUERADE all -- anywhere anywhere
MASQUERADE all -- anywhere anywhere
MASQUERADE all -- anywhere anywhere
target: what to do with packet.
prot: abbr of protocol
opt: abbr of options (AI says rarely used)
source: its anywhere
or explicit ip such 192.168.1.0/24
destination: same as source, can be network
show rules from X table
for example, there has
nat
table, which containsPREROUTING
,INPUT
,OUTPUT
,POSTROUTING
filter
table contains main chain that used by iptables for packet filtering, which containsINPUT
,FORWARD
,OUTPUT
MORE deeper on X table
Table | Purpose | Chains it uses |
---|---|---|
filter | Default, handles packet filtering | INPUT , OUTPUT , FORWARD |
nat | Network Address Translation | PREROUTING , POSTROUTING , OUTPUT |
mangle | Packet modification (TTL, TOS, etc.) | All chains |
raw | Pre-connection tracking processing | PREROUTING , OUTPUT |
security | SELinux/LSM-based packet filtering | INPUT , OUTPUT , FORWARD |
Linux QEMU network address translation
first all, set setup our interface
sudo ip tuntap add tap0 mode tap
sudo ip tuntap add tap1 mode tap
(optional, if there has any more vm)sudo ip link add br0-lan type bridge
(our switch)sudo ip addr add 192.168.12.1/24 dev br0-lan
sudo ip link set br0-lan up
sudo ip link set tap0 up
, also with tap1 if needed
Run alpine guest hosts
qemu-system-x86_64 \
-enable-kvm \
-m 256 \
-smp 4 \
-cpu host \
-drive file=pc-2.qcow2,format=qcow2 \
-cdrom alpine-virt-3.21.3-x86_64.iso \
-boot d \
-nographic \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net-pci,netdev=net0
Inside of guest VM
Your ip addr
output might something like this
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state DOWN qlen 1000
link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
inet6 fe80::5054:ff:fe12:3456/64 scope link
valid_lft forever preferred_lft forever
now set eth0 up by typing
ip link set eth0 up
ip addr add 192.168.12.2/24 dev eth0
(I manually setting up IP)
check ip route
pc-2:~# ip r
192.168.12.0/24 dev eth0 scope link src 192.168.12.2
there is no route, run ip route add default via 192.168.12.1
, check again with ip route
pc-2:~# ip r
default via 192.168.12.1 dev eth0
192.168.12.0/24 dev eth0 scope link src 192.168.12.2
setting up firewall
we want everyting from br0-lan is forwarded into wlan0, vice versa. in order to do that, we need NAT (network address translation)
here
check your nat table first
sudo iptables --table nat --list -v
, make sure there is no
2151 499K MASQUERADE all -- any wlan0 anywhere anywhere
now run
sudo iptables --table nat --append POSTROUTING --out-interface wlan0 -j MASQUERADE
sudo iptables -t filter -A FORWARD -i wlan0 -o br0-lan -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -t filter -A FORWARD -i br0-lan -o wlan0 -j ACCEPT
QEMU block 8.8.8.8 from host
after this
I want this rule
- allow other ICMP (i.e 1.1.1.1)
- deny ICMP 8.8.8.8
iptables rule
suppose, vm ip is 192.168.12.2, so the iptables command is
sudo iptables -t filter -A FORWARD -s 192.168.12.2 -d 8.8.8.8 -p icmp -j DROP
note:
- t: explicit table
- a: table FORWARD
- s: source from 192.168.12.2 (OUR VM)
- d: destination: 8.8.8.8
- p: protocol (which is ICMP)
- j: jump
the problem
you may see ping 8.8.8.8 still success, let check iptables rule
sudo iptables -t filter -L FORWARD -n --line-numbers -v
the output
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
3 DROP icmp -- 192.168.12.2 8.8.8.8
see? when ping to 8.8.8.8, its stop at rule 2, which abort 3st rule, in order to fix it, we need re-order this
remote all rule
sudo iptables -t filter -F FORWARD
re-add
sudo iptables -t filter -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -t filter -A FORWARD -s 192.168.12.2 -d 8.8.8.8 -p icmp -j DROP
sudo iptables -t filter -A FORWARD -s 192.168.12.2/24 -j ACCEPT
Try re-run sudo iptables -t filter -L FORWARD -n --line-numbers
the order should be fixed
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2 DROP icmp -- 192.168.12.2 8.8.8.8
3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
two alpine guest VM, block custom ports
logic netfilter linux kernel
Logic NAT
misalkan kita ada virtual interface br0, dengan anggotanya tap0, tap1 lalu ingin forward semua traffic ke wlan0 (karna memang wlan0 tidak bisa di jadikan master dari x y z)
maka solusinya iptables
sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
logic nya
- fill dulu tabel nat
- append ke postrouting, jadi setelah packet di routing oleh linux kernel, ada 2 field, source addr (katakanlah ip tap0) lalu destination addr (misal 8.8.8.8)
- nah, semisal tidak di apa apakan, packet sent ke 8.8.8.8, tapi 8.8.8.8 tidak bisa mengirim back packetnya karna source addr nya invalid (di stage ini, source ip nya adalah IP LAN)
- maka, setelah linux kernel meng-routingkan packet nya, seketika setelah itu (postrouting), kita ganti source addrnya dengan source ip PUBLIK milik firewall, jadi 8.8.8.8 bisa tahu kemana packet harus dikirim kembali
- didalam firewall, packet yang tadi diterima, direverse balik oleh nat, dan dikirim balik ke perangkat aslinya.
- pakai MASQUERADE
logic forward data dari br0 ke wlan
sudo iptables -A FORWARD -i br0 -o wlan0 -j ACCEPT
important notes:
- chain FORWARD: This chain is only used for packets that are not destined for the local machine, but are routed through it (i.e., from one interface to another).
- In this case: a device connected to br0 (e.g., a VM or container) wants to access the internet via wlan0.
analoginya
[Device 192.168.100.2] ──> [br0 (Linux bridge)] ──> Linux router ──> [wlan0] ──> Internet
bisa juga -j diganti drop, maka aliran data akan terputus
logic forward dari wlan0 ke br0 (sebaliknya)
sudo iptables -A FORWARD -i wlan0 -o br0 -m state --state RELATED,ESTABLISHED -j ACCEPT
logic:
- misal vm tap0 buat koneksi keluar, misal ke 8.8.8.8
- dari tap0 -> br0 -> wlan0 di allow oleh rule
sudo iptables -A FORWARD -i br0 -o wlan0 -j ACCEPT
- ketika server mengirim respon balik, maka alurnya dari wlan0 ke br0, nah ini fungsi dari
sudo iptables -A FORWARD -i wlan0 -o br0 -j ACCEPT
KENAPA harus pakai --state RELATED,ESTABLISHED
karna kita butuh packet yg sudah estab duluan yg boleh lewat. ini akan menghindari jaringan luar (wlan0) mengakses br0 -> tap0 & tap1
resep nginx oleh pak hanif
cuplikan config nginx di server, cc @hansputera
server {
listen 80; # tanpa server_default
listen [::]:80;
root /var/www/html/blablabla.fadev.org;
index index.php index.html index.htm index.nginx-debian.html;
server_name blablabla.fadev.org;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php-fpm.sock;
}
}
ip command
ip addr
ip addr is used to display and manage IP addresses assigned to network interfaces.
example:
ip addr
ip addr show
sudo ip addr add 192.168.1.100/24 dev eth0
sudo ip addr del 192.168.1.100/24 dev eth0
anything about ip assigment
ip link
ip link is used to display and manage network interfaces (links), focusing on layer 2 (Ethernet, loopback, etc.), not IP addresses.
example:
ip link
sudo ip link set dev eth0 up
sudo ip link set dev eth0 down
sudo ip link set dev eth0 mtu 1400
anyting about interface
ip tuntap
ip tuntap manages TUN/TAP virtual network interfaces, which provide a way for user-space programs to interact with network packets as if they were network devices.
- TUN: Simulates a point-to-point device (layer 3), used for routing IP packets (e.g., VPN tunnels).
- TAP: Simulates an Ethernet device (layer 2), used for bridging Ethernet frames (e.g., virtual switches, VMs).
example:
sudo ip tuntap add mode tap dev tap0
sudo ip tuntap add mode tun dev tun0
sudo ip tuntap del mode tap dev tap0
ip route
IP routing is the process by which data packets are directed from their source to their destination across interconnected networks using Internet Protocol (IP). This process is fundamental to the operation of the Internet and all IP-based networks.
- https://www.link11.com/en/glossar/ip-routing/
- https://www.cloudflare.com/learning/network-layer/what-is-routing/
- https://info.support.huawei.com/info-finder/encyclopedia/en/IP+routing.html
View routing table:
ip route
add route
ip route add <destination> via <gateway> dev <interface>
example:
pc-1:~# ip route add default via 192.168.15.1 dev eth0
pc-1:~# ip route
default via 192.168.15.1 dev eth0
192.168.15.0/24 dev eth0 scope link src 192.168.15.2
delete route
sudo ip route del <destination> [via <gateway>] [dev <interface>]
example:
pc-1:~# ip route delete default via 192.168.15.1 dev eth0
pc-1:~# ip r
192.168.15.0/24 dev eth0 scope link src 192.168.15.2
pc-1:~#
qemu default network
The default gateway in QEMU when using the default user-mode networking (SLIRP) is typically 10.0.2.2 on the network 10.0.2.0/24. QEMU creates a virtual NAT network where the guest is assigned an IP like 10.0.2.15 by DHCP, and the gateway for the guest to reach outside networks is 10.0.2.2. This gateway is implemented inside QEMU and handles routing and NAT for the guest's traffic.
- Default network: 10.0.2.0/24
- Default gateway: 10.0.2.2
- Default guest IP (DHCP assigned): 10.0.2.15
- Default DNS server in guest: 10.0.2.3
This setup requires no special host configuration or root privileges and is the default networking mode for QEMU user mode networking.
additional
- https://docs.zephyrproject.org/latest/connectivity/networking/qemu_user_setup.html
- https://darnassus.sceen.net/~hurd-web/hurd/running/qemu/networking/
- https://wiki.qemu.org/Documentation/Networking
mikrotik firewall
each firewall module (called as table in iptables) has its own predefined chain
-
raw: dipakai sebelum data dilihat oleh conntrack, NAT, masuk routing, dll. intinya di sinilah proses early sebelum benar2 di proses. karna belum sampai ke conntrack, maka akan sangat fast, dipakai untuk mitigasi ddos
karna statenya ada sebelum conntrack, maka tidak ada status kayak estab, dll, tapi sangat fast + low cpu, only raw matching
Karna raw table melihat packet sebelum NAT, maka
- Destination IPs are still the original IPs from the client
- Source IPs haven't been changed by masquerade or src-nat yet
chain chain nya
- prerouting: packet yang datang dari luar just sebelum masuk conntrack
- output: packet yang digenerate oleh aplikasi, juga statenya sebelum di track oleh conntrack
contoh
/ip firewall raw add chain=prerouting src-address=8.8.8.8 action=drop
tambahan:
letak raw di packet flow
IN → RAW → MANGLE (pre) → CONNECTION TRACKING → NAT (dstnat) → FILTER (input/forward) → MANGLE (post) → NAT (srcnat) → OUT
-
filter
- input
- forward
- output
-
mangle
- prerouting
- input
- forward
- output
- postrouting
-
nat
- srcnat
- dstnat
chains
RouterOS consist of a few default chains. These chains allow you to filter packets at various points:
- The PREROUTING chain: Rules in this chain apply to packets as they just arrive on the network interface. This chain is present in the nat, mangle and raw tables.
- The INPUT chain: Rules in this chain apply to packets just before they’re given to a local process. This chain is present in the mangle and filter tables.
- The OUTPUT chain: The rules here apply to packets just after they’ve been produced by a process. This chain is present in the raw, mangle, nat, and filter tables.
- The FORWARD chain: The rules here apply to any packets that are routed through the current host. This chain is only present in the mangle and filter tables.
- The POSTROUTING chain: The rules in this chain apply to packets as they just leave the network interface. This chain is present in the nat and mangle tables.
bring wlan0 connectivity to the network namespace linux & test routerOS
setup network namespace
sudo ip netns add firefoxns
sudo ip netns exec firefoxns ip link add br0-lan type bridge
sudo ip netns exec firefoxns ip tuntap add tap0 mode tap
sudo ip netns exec firefoxns ip tuntap add tap1 mode tap
sudo ip netns exec firefoxns ip tuntap add tap2 mode tap
sudo ip netns exec firefoxns ip link set dev tap0 master br0-lan
sudo ip netns exec firefoxns ip link set dev tap1 master br0-lan
sudo ip netns exec firefoxns ip link set dev tap2 master br0-lan
enable the network interface (inside netns)
sudo ip netns exec firefoxns ip link set br0-lan up
sudo ip netns exec firefoxns ip link set tap0 up
sudo ip netns exec firefoxns ip link set tap1 up
sudo ip netns exec firefoxns ip link set tap2 up
create virtual eth pair between host & netns
sudo ip link add veth0 type veth peer name veth0-peer
sudo ip link set veth0-peer netns firefoxns
assign ip for virtual eth & virtual eth peer
sudo ip addr add 10.200.1.1/24 dev veth0
sudo ip netns exec firefoxns ip addr add 10.200.1.2/24 dev veth0-peer
sudo ip link set veth0 up
sudo ip netns exec firefoxns ip link set veth0 up
setup routing table
sudo ip netns exec firefoxns ip route add default via 10.200.1.1
setup ip forwarding & network address translation
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -s 10.200.1.0/24 -o wlan0 -j MASQUERADE
test
sudo ip netns exec ping 1.1.1.1
now, run routeros & alpine inside of netns
routeros
sudo ip netns exec firefoxns qemu-system-x86_64 \
-enable-kvm \
-m 256 \
-smp 4 \
-cpu host \
-drive file=chr.qcow2,format=qcow2 \
-boot d \
-nographic \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net-pci,netdev=net0,mac=02:aa:bb:cc:dd:ee \
-net user,hostfwd=tcp::8291-:8291 \
-net nic
alpine
sudo ip netns exec firefoxns qemu-system-x86_64 \
-enable-kvm \
-m 256 \
-smp 4 \
-cpu host \
-drive file=pc-2.qcow2,format=qcow2 \
-cdrom alpine-virt-3.21.3-x86_64.iso \
-boot d \
-nographic \
-netdev tap,id=net0,ifname=tap2,script=no,downscript=no \
-device virtio-net-pci,netdev=net0,mac=$(randommac)
network namespace + NAT notes
ip a
sudo ip link add veth0 type veth peer name veth0-peer
sudo ip addr add 10.200.1.1/24 dev veth0
sudo ip netns add firefoxns
sudo ip link set veth0-peer netns firefoxns
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -s 10.200.1.0/24 -o wlan0 -j MASQUERADE
sudo ip netns exec firefoxns ip addr add 10.200.1.2/24 dev veth0-peer
sudo ip netns exec firefoxns ip addr add 127.0.0.1/8 dev lo
sudo ip netns exec firefoxns ip link set lo up
sudo ip netns exec firefoxns ip link set veth0-peer up
sudo ip netns exec firefoxns ip route add default via 10.200.1.1
sudo ip netns exec firefoxns ip link add br0-lan type bridge
sudo ip netns exec firefoxns ip tuntap add tap0 mode tap
sudo ip netns exec firefoxns ip tuntap add tap1 mode tap
sudo ip netns exec firefoxns ip tuntap add tap2 mode tap
sudo ip netns exec firefoxns ip link set dev tap0 master br0-lan
sudo ip netns exec firefoxns ip link set dev tap1 master br0-lan
sudo ip netns exec firefoxns ip link set dev tap2 master br0-lan
sudo ip netns exec firefoxns ip link set dev tap0 up
sudo ip netns exec firefoxns ip link set dev tap1 up
sudo ip netns exec firefoxns ip link set dev tap2 up
sudo ip netns exec firefoxns ip link set dev br0-lan up
sudo ip netns exec firefoxns qemu-system-x86_64 -enable-kvm -m 256 -smp 4 -cpu host -drive file=chr.qcow2,format=qcow2 -boot d -nographic -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device virtio-net-pci,netdev=net0,mac=02:aa:bb:cc:dd:ee -net user,hostfwd=tcp::8291-:8291 -net nic
sudo ip netns exec firefoxns qemu-system-x86_64 -enable-kvm -m 256 -smp 4 -cpu host -drive file=pc-1.qcow2,format=qcow2 -cdrom alpine-virt-3.21.3-x86_64.iso -boot d -nographic -netdev tap,id=net0,ifname=tap1,script=no,downscript=no -device virtio-net-pci,netdev=net0,mac=$(randommac)
randommac source code
use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
let mac = format!(
"52:54:00:{:02x}:{:02x}:{:02x}",
rng.gen::<u8>(),
rng.gen::<u8>(),
rng.gen::<u8>()
);
println!("{}", mac);
}
deploy Docmost on server
please read this doc first, https://docmost.com/docs/installation
docker compose config
version: "3"
services:
docmost:
image: docmost/docmost:latest
depends_on:
- db
- redis
environment:
APP_URL: "http://localhost:3000"
APP_SECRET: "REPLACE_WITH_LONG_SECRET"
DATABASE_URL: "postgresql://docmost:STRONG_DB_PASSWORD@db:5432/docmost?schema=public"
REDIS_URL: "redis://redis:6379"
ports:
- "3000:3000"
restart: unless-stopped
volumes:
- docmost:/app/data/storage
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: docmost
POSTGRES_USER: docmost
POSTGRES_PASSWORD: STRONG_DB_PASSWORD
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
redis:
image: redis:7.2-alpine
restart: unless-stopped
volumes:
- redis_data:/data
volumes:
docmost:
db_data:
redis_data:
replace your STRONG_DB_PASSWORD
with openssl rand -hex 10
, and REPLACE_WITH_LONG_SECRET
with openssl rand -hex 32
, and APP_URL
, for example, in my case is https://docmost.fadev.org
run docker compose run
setup reverse proxy (nginx)
go to /etc/nginx/sites-enabled
, and create a clone with cp default docmost.fadev.org
fill it like this
server_name docmost.fadev.org;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
#try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:3000;
}
location /socket.io/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
location /collab {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
HTTPS
run
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d docmost.fadev.org
Firewall
allow port 443
fix vthxxxxxxxx is not connected to docker0
consider
> ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp2s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
link/ether 2c:4d:54:c6:f2:0c brd ff:ff:ff:ff:ff:ff
altname enx2c4d54c6f20c
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether f0:03:8c:66:9c:21 brd ff:ff:ff:ff:ff:ff
inet 192.168.105.162/24 metric 1024 brd 192.168.105.255 scope global dynamic wlan0
valid_lft 2920sec preferred_lft 2920sec
inet 192.168.105.163/24 brd 192.168.105.255 scope global secondary dynamic noprefixroute wlan0
valid_lft 2921sec preferred_lft 2921sec
inet6 fe80::ee67:75f9:fa9c:2561/64 scope link noprefixroute
valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 86:1e:e0:72:f4:8d brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::841e:e0ff:fe72:f48d/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
17: veth914db4f@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether d2:02:61:f4:12:d0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::d002:61ff:fef4:12d0/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
you can see, veth914db4f is not connected to br0. let's try hard
- run image (explicitly) as bridge network:
docker run --network bridge -it --rm -p 127.0.0.1:8000:4000 php-test-server
(this is nothing happen) - force connect:
docker network connect bridge 2cf520235e6a
(this is show Error response from daemon: endpoint with name mystifying_yonath already exists in network bridge, butip a
says vethxxxx is not master to anyone). you can trydisconnect
&connect
again
also
docker inspect -f '{{json .NetworkSettings.Networks}}' 2cf520235e6a | jq
{
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"MacAddress": "5a:2d:5d:7c:c1:86",
"DriverOpts": null,
"GwPriority": 0,
"NetworkID": "08f151565c95ba052f682c7560e55199e2d75f3d2348af8f98a9711e9294b3fd",
"EndpointID": "0522c15ad18fbae05071a7d5e09944b7777deaafd3490082cac237fdfcd14f0c",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DNSNames": null
}
}
the medicine: https://forums.docker.com/t/no-connection-to-the-bridge-by-default/134619/8
sudo systemctl stop systemd-networkd.service
sudo systemctl disable systemd-networkd.service
sudo systemctl stop systemd-networkd.socket
sudo systemctl disable systemd-networkd.socket
sudo systemctl start NetworkManager
sudo systemctl enable NetworkManager
php-fpm config
file ini biasanya ada di
/usr/local/etc/php-fpm.d/www.conf
(di docker php-fpm)/etc/php/8.3/fpm/pool.d/www.conf
(di debian bullseye)
intinya, tidak pasti haha.
config structure
general structure nya seperti ini kalau ';' dihilangkan
[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
config global (WIP)
config untuk pool (each)
best read https://www.php.net/manual/en/install.fpm.configuration.php
- [pool_name] intinya ini unique, tidak ada yang sama
- user / group
user
: dimana child process akan di run (as user?)group
: liat /etc/passwd
- listen
-
listen
: dimana daemon akan listen yg nanti akan di reverse proxy oleh nginx, nilai defaultnya biasanya/run/php/php8.3-fpm.sock
atau127.0.0.1:9000
, contoh:ip.add.re.ss:port
[ip:6:addr:ess]:port
port
- /path/to/unix/socket
-
listen.backlog
: jumlah queue pending connection yang bisa di hold -
listen.owner
: configure ke mana kah/run/php/php8.3-fpm.sock
itu ownernya -
listen.group
: same aslisten.owner
-
listen.mode
: nomor permission si/run/php/php8.3-fpm.sock
listen -
listen.acl_users
: WIP -
listen.acl_groups
: WIP -
listen.allowed_clients
: set dari mana FCGI boleh diakses, di kasus nginx, mostly 127.0.0.1, except docker, dia pakai br-xxxxxx yang ip nya pasti bukan 127.0.0.1 -
listen.setfib
: WIP
-
systemd config template
root location: /etc/systemd/system/<YOUR_SERVICE>.service
template
[Unit]
Description=Random service
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=root
ExecStart=/usr/bin/randomprogram -c /etc/randomprogram/other.toml
[Install]
WantedBy=multi-user.target
Database
psql command
General
\bind
[PARAM]... set query parameters\copyright
show PostgreSQL usage and distribution terms\crosstabview
[COLUMNS] execute query and display result in crosstab\errverbose
show most recent error message at maximum verbosity\g
[(OPTIONS)] [FILE] execute query (and send result to file or |pipe);\g
with no arguments is equivalent to a semicolon\gdesc
describe result of query, without executing it\gexec
execute query, then execute each value in its result\gset
[PREFIX] execute query and store result in psql variables\gx
[(OPTIONS)] [FILE] as\g
, but forces expanded output mode\q
quit psql\watch
[[i=]SEC] [c=N] [m=MIN] execute query every SEC seconds, up to N times, stop if less than MIN rows are returned
Help
\?
[commands] show help on backslash commands\?
options show help on psql command-line options\?
variables show help on special variables\h
[NAME] help on syntax of SQL commands, * for all commands
Query Buffer
\e
[FILE] [LINE] edit the query buffer (or file) with external editor\ef
[FUNCNAME [LINE]] edit function definition with external editor\ev
[VIEWNAME [LINE]] edit view definition with external editor\p
show the contents of the query buffer\r
reset (clear) the query buffer\s
[FILE] display history or save it to file\w
FILE write query buffer to file
Input/Output
\copy
... perform SQL COPY with data stream to the client host\echo
[-n] [STRING] write string to standard output (-n for no newline)\i
FILE execute commands from file\ir
FILE as \i, but relative to location of current script\o
[FILE] send all query results to file or |pipe\qecho
[-n] [STRING] write string to \o output stream (-n for no newline)\warn
[-n] [STRING] write string to standard error (-n for no newline)
Conditional
\if
EXPR begin conditional block\elif
EXPR alternative within current conditional block\else
final alternative within current conditional block\endif
end conditional block
Informational
(options: S = show system objects, + = additional detail)
- \d[S+] list tables, views, and sequences
- \d[S+] NAME describe table, view, sequence, or index
- \da[S] [PATTERN] list aggregates
- \dA[+] [PATTERN] list access methods
- \dAc[+] [AMPTRN [TYPEPTRN]] list operator classes
- \dAf[+] [AMPTRN [TYPEPTRN]] list operator families
- \dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families
- \dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families
- \db[+] [PATTERN] list tablespaces
- \dc[S+] [PATTERN] list conversions
- \dconfig[+] [PATTERN] list configuration parameters
- \dC[+] [PATTERN] list casts
- \dd[S] [PATTERN] show object descriptions not displayed elsewhere
- \dD[S+] [PATTERN] list domains
- \ddp [PATTERN] list default privileges
- \dE[S+] [PATTERN] list foreign tables
- \des[+] [PATTERN] list foreign servers
- \det[+] [PATTERN] list foreign tables
- \deu[+] [PATTERN] list user mappings
- \dew[+] [PATTERN] list foreign-data wrappers
- \df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]] list [only agg/normal/procedure/trigger/window] functions
- \dF[+] [PATTERN] list text search configurations
- \dFd[+] [PATTERN] list text search dictionaries
- \dFp[+] [PATTERN] list text search parsers
- \dFt[+] [PATTERN] list text search templates
- \dg[S+] [PATTERN] list roles
- \di[S+] [PATTERN] list indexes
- \dl[+] list large objects, same as \lo_list
- \dL[S+] [PATTERN] list procedural languages
- \dm[S+] [PATTERN] list materialized views
- \dn[S+] [PATTERN] list schemas
- \do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]] list operators
- \dO[S+] [PATTERN] list collations
- \dp[S] [PATTERN] list table, view, and sequence access privileges
- \dP[itn+] [PATTERN] list [only index/table] partitioned relations [n=nested]
- \drds [ROLEPTRN [DBPTRN]] list per-database role settings
- \drg[S] [PATTERN] list role grants
- \dRp[+] [PATTERN] list replication publications
- \dRs[+] [PATTERN] list replication subscriptions
- \ds[S+] [PATTERN] list sequences
- \dt[S+] [PATTERN] list tables
- \dT[S+] [PATTERN] list data types
- \du[S+] [PATTERN] list roles
- \dv[S+] [PATTERN] list views
- \dx[+] [PATTERN] list extensions
- \dX [PATTERN] list extended statistics
- \dy[+] [PATTERN] list event triggers
- \l[+] [PATTERN] list databases
- \sf[+] FUNCNAME show a function's definition
- \sv[+] VIEWNAME show a view's definition
- \z[S] [PATTERN] same as \dp
Large Objects
- \lo_export LOBOID FILE write large object to file
- \lo_import FILE [COMMENT] read large object from file
- \lo_list[+] list large objects
- \lo_unlink LOBOID delete a large object
Formatting
- \a toggle between unaligned and aligned output mode
- \C [STRING] set table title, or unset if none
- \f [STRING] show or set field separator for unaligned query output
- \H toggle HTML output mode (currently off)
- \pset [NAME [VALUE]] set table output option (border|columns|csv_fieldsep|expanded|fieldsep| fieldsep_zero|footer|format|linestyle|null| numericlocale|pager|pager_min_lines|recordsep| recordsep_zero|tableattr|title|tuples_only| unicode_border_linestyle|unicode_column_linestyle| unicode_header_linestyle|xheader_width)
- \t [on|off] show only rows (currently off)
- \T [STRING] set HTML
tag attributes, or unset if none
- \x [on|off|auto] toggle expanded output (currently off)
Connection
- \c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo} connect to new database (currently "fadev_infra")
- \conninfo display information about current connection
- \encoding [ENCODING] show or set client encoding
- \password [USERNAME] securely change the password for a user
Operating System
- \cd [DIR] change the current working directory
- \getenv PSQLVAR ENVVAR fetch environment variable
- \setenv NAME [VALUE] set or unset environment variable
- \timing [on|off] toggle timing of commands (currently off)
- ! [COMMAND] execute command in shell or start interactive shell
Variables
- \prompt [TEXT] NAME prompt user to set internal variable
- \set [NAME [VALUE]] set internal variable, or list all if no parameters
- \unset NAME unset (delete) internal variable
psql snippet
psql
\df *.*
Lists all relations\l
Lists all database
command
DROP TABLE table_name CASCADE;
used when you want to remove all object depend on them.
PostgreSQL database creation flow
in order to create database (for safety, I use postgres account). I use this step.
first, we need to login as
postgres
user, use thissudo -u postgres psql
, then doCREATE DATABASE EXAMPLE_DB;
this is optional
CREATE USER EXAMPLE_USER WITH ENCRYPTED PASSWORD 'Sup3rS3cret';
grant
GRANT ALL PRIVILEGES ON DATABASE EXAMPLE_DB TO EXAMPLE_USER;
now, change the state using
\c EXAMPLE_DB postgres
, execute this commandGRANT ALL ON SCHEMA public TO EXAMPLE_USER;
then, change ownership
ALTER DATABASE my_database OWNER TO my_database_user;
how to use SQLX cli tools for db migration such laravel migrations
let's meet with this crate, https://crates.io/crates/sqlx-cli, this tools allow you to use db migration such as laravel migration tools;
first, let's create env variable
export DATABASE_URL=postgres://fadhil_riyanto:<your_pass>@localhost/<target_db>
then, the things that we do next is only
sqlx migrate add -r <name>
running
sqlx migrate run
Postgresql internal (server)
this thing explain the internal of pgsql system (not the source code I mean)
difference between catalog vs schema
key point:
-
schema is folder like, grouping table together, can be created using
CREATE SCHEMA my_catalog; CREATE TABLE my_catalog.metadata_table (...);
-
catalog is system schema, can't be created manually, part of internal pgsql system
-
view is a resulted table from XYZ queries, example
CREATE VIEW active_users AS SELECT id, name, FROM users WHERE active = true;
then query it
SELECT * FROM active_users;
pg_catalog inside
this is some stuff inside of pg catalog, you can do that using
\dt pg_catalog.*
- pg_aggregate: Stores information about aggregate functions (like
SUM
,AVG
, etc.). - pg_am: Lists access methods for indexes (e.g.,
btree
,hash
). - pg_amop: Defines operators used in access methods.
- pg_amproc: Defines support functions used in access methods.
- pg_attrdef: Stores default values for columns.
- pg_attribute: Contains column definitions for all tables.
- pg_auth_members: Shows role memberships (who is a member of what).
- pg_authid: Stores user/role definitions (superuser access required).
- pg_cast: Contains rules for casting between data types.
- pg_class: Contains all table-like objects (tables, views, indexes, sequences, etc.).
- pg_collation: Defines collations (rules for string comparison).
- pg_constraint: Stores constraints like PRIMARY KEY, UNIQUE, CHECK, and FOREIGN KEY.
- pg_conversion: Defines character set conversions.
- pg_database: Stores information about each database in the cluster.
- pg_db_role_setting: Stores per-user/per-database configuration settings (GUCs).
- pg_default_acl: Defines default privileges for newly created objects.
- pg_depend: Stores dependency relationships between database objects.
- pg_description: Stores comments/descriptions on database objects.
- pg_enum: Stores values for
ENUM
data types. - pg_event_trigger: Stores event trigger definitions (triggers on DDL commands).
- pg_extension: Tracks installed extensions (like
uuid-ossp
,pgcrypto
, etc.). - pg_foreign_data_wrapper: Stores definitions of foreign data wrappers (FDW).
- pg_foreign_server: Stores foreign servers used by FDWs.
- pg_foreign_table: Stores metadata for foreign tables.
- pg_index: Contains metadata about indexes (e.g., indexed columns).
- pg_inherits: Stores table inheritance relationships.
- pg_init_privs: Records original privileges on built-in objects.
- pg_language: Stores information about supported procedural languages.
- pg_largeobject: Stores the actual data of large objects (blobs).
- pg_largeobject_metadata: Stores metadata about large objects.
- pg_namespace: Lists all schemas in the database (IMPORTANT)
- pg_opclass: Stores index operator classes (how a datatype is indexed).
- pg_operator: Stores SQL operators (like
=
,<
,+
, etc.). - pg_opfamily: Groups related operator classes.
- pg_parameter_acl: Stores access control for configuration parameters (PostgreSQL 16+).
- pg_partitioned_table: Stores metadata for partitioned tables.
- pg_policy: Stores row-level security policies.
- pg_proc: Contains all function and procedure definitions.
- pg_publication: Stores logical replication publications.
- pg_publication_namespace: Links publications to schemas.
- pg_publication_rel: Links publications to individual tables.
- pg_range: Stores definitions of range types (e.g.,
int4range
). - pg_replication_origin: Tracks origins for logical replication.
- pg_rewrite: Stores query rewrite rules (used in views, rules).
- pg_seclabel: Stores security labels for database objects.
- pg_sequence: Contains metadata for sequence generators.
- pg_shdepend: Tracks dependencies involving shared objects (like roles, databases).
- pg_shdescription: Stores comments on shared objects.
- pg_shseclabel: Stores security labels on shared objects.
- pg_statistic: Stores planner statistics for columns.
- pg_statistic_ext: Stores extended planner statistics (multi-column, NDV, etc.).
- pg_statistic_ext_data: Contains actual values for extended statistics.
- pg_subscription: Defines logical replication subscriptions.
- pg_subscription_rel: Lists tables included in subscriptions.
- pg_tablespace: Lists all tablespaces (disk locations for data).
- pg_transform: Stores type transformation functions for procedural languages.
- pg_trigger: Stores triggers on tables.
- pg_ts_config: Stores full-text search configurations.
- pg_ts_config_map: Maps text search config tokens to dictionaries.
- pg_ts_dict: Stores text search dictionaries.
- pg_ts_parser: Defines tokenizers for full-text search.
- pg_ts_template: Defines templates for building text search dictionaries.
- pg_type: Stores all data types (built-in, custom, enum, composite). (IMPORTANT)
- pg_user_mapping: Maps users to foreign servers.
pg_catalog.pg_database details
this docs can be found in https://www.postgresql.org/docs/16/catalog-pg-database.html
Column Name Type Description datname
name
The name of the database. datdba
oid
The OID of the role (user) that owns the database. Use pg_get_userbyid(datdba)
to resolve it.encoding
int
The character encoding of the database (e.g., UTF8 = 6). Use pg_encoding_to_char(encoding)
to get the name.datlocprovider
char
Locale provider used ( c
= libc,i
= ICU).datistemplate
bool
If true
, the database can be used as a template forCREATE DATABASE ... TEMPLATE
.datallowconn
bool
If false
, connections to this database are not allowed (except by superusers).datconnlimit
int
The maximum number of concurrent connections allowed (-1 = no limit). datlastsysoid
oid
The last system OID used in this database at creation (mainly historical). datfrozenxid
xid
The transaction ID at which all tuples are known to be frozen (related to VACUUM). datminmxid
xid
The minimum multixact ID that is still considered potentially unfrozen. dattablespace
oid
OID of the default tablespace for the database. Use pg_tablespace
to resolve.datcollate
name
LC_COLLATE setting (how strings are sorted). datctype
name
LC_CTYPE setting (how character classification works). daticulocale
text
ICU locale (used if datlocprovider = 'i'
).datcollversion
text
Version of the collation used (important for collation versioning with ICU). datacl
aclitem[]
Access privileges (GRANTs), stored as an array of ACL items. management script collection
- show all databases (in current user)
SELECT * FROM pg_catalog.pg_database;`:
- show
pg_catalog.pg_tables
definitiongo back on top in order to see what actually view is
SELECT pg_get_viewdef('pg_catalog.pg_tables', true);`:
- show all available pgsql datatype
SELECT * FROM pg_catalog.pg_type;
- lists all schema
SELECT * FROM pg_catalog.pg_namespace;
- show all dbs with owner
SELECT x.oid as object_id, x.datname as db_name, CASE WHEN pg_catalog.pg_get_userbyid(x.datdba) LIKE 'unknown (OID=%)' THEN 'UNKNOWN' ELSE pg_catalog.pg_get_userbyid(x.datdba) END as owner FROM pg_catalog.pg_database as x;
cond: https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-CASE
- RENAME db (as postgres user)
ALTER DATABASE xyz RENAME TO abc;
Postgresql II SQL language docs summary
this is incomplete documentation summary of postgresql (SQL section), see complete docs here
5. Data Definition
5.2. Default values
When a new row is created and no values are specified for some of the columns, those columns will be filled with their respective default values. A data manipulation command can also request explicitly that a column be set to its default value, without having to know what that value is
example
CREATE TABLE state ( uid integer, enable bool DEFAULT false )
5.3. Identity column
system table in pgsql (catalog)
pg_tables | docs
catalog pgsql yang isinya data ttg table (di db saat ini), contoh query nya
SELECT * FROM pg_catalog.pg_tables as x WHERE x.schemaname = 'public';
pg_sequences
yg ini isinya sequence2 semua, mirip kayak serial datatype di pgsql
NOTES:
pg_sequence
adalah versi low levelnya, sedangkanpg_sequences
adalah versi view dari join-anpg_sequence
danpg_class
, buktiSELECT * FROM pg_get_viewdef('pg_catalog.pg_sequences', true)
hasil
SELECT n.nspname AS schemaname, c.relname AS sequencename, pg_get_userbyid(c.relowner) AS sequenceowner, s.seqtypid :: regtype AS data_type, s.seqstart AS start_value, s.seqmin AS min_value, s.seqmax AS max_value, s.seqincrement AS increment_by, s.seqcycle AS cycle, s.seqcache AS cache_size, CASE WHEN has_sequence_privilege(c.oid, 'SELECT,USAGE' :: text) THEN pg_sequence_last_value(c.oid :: regclass) ELSE NULL :: bigint END AS last_value FROM pg_sequence s JOIN pg_class c ON c.oid = s.seqrelid LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE NOT pg_is_other_temp_schema(n.oid) AND c.relkind = 'S' :: "char";
pgsql functions()
pg_get_viewdef
see sql script for particular view, I call this as view reverser
example:
SELECT * FROM pg_get_viewdef('pg_catalog.pg_sequences', true)
ref:
- https://pgpedia.info/p/pg_get_viewdef.html
- https://www.postgresql.org/docs/current/functions-info.html
akan ada kelanjutan disini.
Dockerfile boilerplate
this folder is a set of dockerfile boilerplate that I used to build something.
php-8.3 debian v11 (bullseye) dev-env
CREATED:
Fri Jun 6 06:32:35 PM WIB 2025
FROM debian:bullseye ENV DEBIAN_FRONTEND=noninteractive # initial, refresh repo first RUN apt-get update # this install base package that need in order to download gpg key (curl, and gnupg) RUN apt-get install -y ca-certificates RUN apt-get install -y apt-transport-https RUN apt-get install -y lsb-release RUN apt-get install -y gnupg RUN apt-get install -y curl RUN apt-get install -y git RUN apt-get install -y unzip # add ondrej\PPA RUN curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/php.gpg RUN echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/php.list # install actual package, php-xml & php-mbstring is needed by composer. RUN apt-get update RUN apt-get install -y nginx RUN apt-get install -y php8.3 RUN apt-get install -y php8.3-curl RUN apt-get install -y php8.3-xml RUN apt-get install -y php8.3-mbstring # download composer RUN curl -sS https://getcomposer.org/installer -o composer-setup.php \ && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \ && rm composer-setup.php COPY . /app WORKDIR /app EXPOSE 4444 # install composer RUN composer install CMD [ "php", "-S", "0.0.0.0:4444", "-t", "public" ]
php:8.3.20-fpm-bullseye + nginx
FROM php:8.3.20-fpm-bullseye RUN apt-get update && apt-get install -y libpq-dev RUN docker-php-ext-install pdo pdo_pgsql COPY . /app WORKDIR /app COPY ./docker/fpm/www.conf /usr/local/etc/php-fpm.d/www.conf # karna php-fpm running pakai user www-data RUN chown -R www-data:www-data /app/storage CMD [ "php-fpm" ]
default.conf (nginx)
server { listen 80; server_name localhost; access_log off; root /app/public; location / { try_files $uri $uri/ /index.php?$query_string; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $document_root; include fastcgi_params; } }
www.conf
[www] access.log = /dev/null user = www-data group = www-data listen = 0.0.0.0:9000 pm = dynamic pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3
php:8.3.20-bullseye dev env
this is also works for laravel
FROM php:8.3.20-bullseye RUN apt-get update && apt-get install -y \ curl \ libpq-dev \ git \ unzip RUN docker-php-ext-install pdo pdo_pgsql COPY . /app WORKDIR /app RUN curl -sS https://getcomposer.org/installer -o composer-setup.php \ && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \ && rm composer-setup.php RUN composer install CMD [ "php", "-S", "0.0.0.0:10302", "-t", "public" ]
compose.yml
volumes: storage: db_data: networks: veth_network: driver: bridge services: google_sso: image: php:8.3.20-bullseye build: context: . dockerfile: dev.backend.Dockerfile environment: - docker=true - DB_HOST=pgsql_db - DB_PORT=5432 - DB_USERNAME=postgres - DB_PASSWORD=<PASSWD> - DB_DATABASE=google_sso_dev - G_SSO_NAME=google-sso-login - G_SSO_CLIENT_ID=ABC - G_SSO_CLIENT_SECRET=DEF - G_SSO_REDIRECT_URI=http://localhost:10302/auth/callback ports: - "10302:10302" networks: - veth_network volumes: - .:/app - storage:/app/storage depends_on: - pgsql_db pgsql_db: image: postgres:17.5-bullseye restart: always shm_size: 128mb environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=<PASSWD> - POSTGRES_DB=google_sso_dev networks: - veth_network volumes: - db_data:/var/lib/postgresql/data adminer: image: adminer restart: always ports: - 8080:8080 networks: - veth_network depends_on: - pgsql_db
CATATAN unik: ketika ping
pgsql_db
dari xxx container, ia otomatis resolve dns nya.PHP (web)
laravel service container
date: Sun Jun 8 11:47:02 PM WIB 2025
links
making
untuk membuat service container, katakanlah isi class ctx yang namanya Google\Client. dia mereturn $client. maka kita harus bikin
php artisan make:provider GoogleApis
nama GoogleApis bebas. lalu cek di folder
./app/Providers/GoogleApis.php
harusnya ada, dan di file./bootstrap/providers.php
akan ada<?php return [ App\Providers\AppServiceProvider::class, App\Providers\GoogleApis::class, ];
ada
App\Providers\GoogleApis::class
maksudnya.registering
dari service provider yang baru saja dibuat, akan ada 2 method, yaitu
public function register(): void
: boot ini entry dari service, nilai ctx ctx dsb biasanya diload disinipublic function boot(): void
: func ini dipanggil kalau semua service sudah jalan, misal service route di register, tapi method untuk nambahin route routenya. ada di boot
general structure nya (file
./app/Providers/AppServiceProvider.php
)<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Register any application services. */ public function register(): void { // } /** * Bootstrap any application services. */ public function boot(): void { // } }
the inside of register function
docs tentang
- binding -> https://laravel.com/docs/12.x/container#simple-bindings
- singleton -> https://laravel.com/docs/12.x/container#binding-a-singleton
perbedaanya,
bind
auto buat fresh ctx tiap kali request datang, sedangkansingleton
hanya buat sekali, contoh konkretsingleton
adalah ctx koneksi mongodb, kita cukup pakai sekali saja, untuk semua containerini contoh googleclient
// this code is inside of register() func $this->app->singleton(Client::class, function (Application $app) { $client = new Client(); $client->setApplicationName(env("G_SSO_NAME")); $client->setClientId(env("G_SSO_CLIENT_ID")); $client->setClientSecret(env("G_SSO_CLIENT_SECRET")); $client->setRedirectUri(env("G_SSO_REDIRECT_URI")); $client->addScope([ Service\Oauth2::USERINFO_EMAIL, Service\Oauth2::USERINFO_PROFILE ]); $client->setAccessType('offline'); $client->setLoginHint('your_email@gmail.com'); return $client; });
catatan:
use Illuminate\Contracts\Foundation\Application
itu ctx bawaan laravel buat ngebind.how to use
lokasi: controller
kita tinggal panggil saja class (milik aslinya)
contoh
use Google\Client; class Randomclass extends Controller { /** * Create a new controller instance. */ public function __construct( protected Client $client, ) {} public function use_it() { $this->client->some_google_method(); // $this->client was initialized } }
laravel 12 custom auth guard + tables
Mon Jun 9 05:36:39 AM WIB 2025
di sini saya coba untuk membuat Auth::attempt https://laravel.com/docs/12.x/authentication#authenticating-users, tapi bedanya, ia pakai totally different table. jadi tidak pakai table
users
setup model
untuk setup nya, kita buat model dulu seperti biasa pakai
php artisan make:model Xyz
, disini saya buatnyaphp artisan make:model GuestUser
. lalu cek bagian./app/Models/GuestUser.php
normalnya class akan extends ke
Illuminate\Database\Eloquent\Model
, nah ini kita extends kan keIlluminate\Foundation\Auth\User
, dimana class itu kalau dirunut lagi, pasti juga nge-extends ke class Modelbukti
class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract { use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail; }
ok, sudah. saatnya kita pindah ke model yang baru saja dibuat, isi $fillable seperti column database, jangan lupa ganti extends nya dengan
extends Authenticatable
hasil akhir seperti ini kira2
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\User as Authenticatable; class GuestUser extends Authenticatable { protected $table = "guest_user"; protected $fillable = [ 'name', 'picture', 'email', 'password', 'token', 'g_auth_expires_in' ]; }
registering guard
agar model kita bisa dibaca oleh
Auth
facade, maka kita harus registerkan dia dahulu di./config/auth.php
, isi dahulu bagianproviders
. contoh/* |-------------------------------------------------------------------------- | User Providers |-------------------------------------------------------------------------- | | All authentication guards have a user provider, which defines how the | users are actually retrieved out of your database or other storage | system used by the application. Typically, Eloquent is utilized. | | If you have multiple user tables or models you may configure multiple | providers to represent the model / table. These providers may then | be assigned to any extra authentication guards you have defined. | | Supported: "database", "eloquent" | */ 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => env('AUTH_MODEL', App\Models\User::class), ], 'guest_users' => [ 'driver' => 'eloquent', 'model' => env('AUTH_MODEL', App\Models\GuestUser::class), ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ],
make sense kan?
guest_users
provider, ia memiliki model App\Models\GuestUser::class (note,::class
akan return str),setelah itu, lihat bagian atasnya, ada guards, disini kita akan naming guardsnya dan juga memberi info provider model mana yang akan dikasih, contoh
/* |-------------------------------------------------------------------------- | Authentication Guards |-------------------------------------------------------------------------- | | Next, you may define every authentication guard for your application. | Of course, a great default configuration has been defined for you | which utilizes session storage plus the Eloquent user provider. | | All authentication guards have a user provider, which defines how the | users are actually retrieved out of your database or other storage | system used by the application. Typically, Eloquent is utilized. | | Supported: "session" | */ 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'guest' => [ 'driver' => 'session', 'provider' => 'guest_users', ], ],
JFYI:
Auth::attempt()
secara default pakai guardsweb
, nah kita sekarang juga bisa pakai custom, seperti iniAuth::guard("guest")->attempt()
secara explicit kita tell laravel untuk pakai guardguest
session
general login flow
if (Auth::guard("guest")->attempt($packed_arr)) { $retq = GuestUser::where("email", $packed_arr["email"])->first(); $retq = Auth::guard("guest")->login($retq); return redirect('/dashboard/index'); } else { dd("login failed"); }
Auth::guard("guest")->attempt()
return boolean, true jika auth benar.Auth::guard("guest")->login($retq);
ubah state internalnya bahwa dia sudah login, lalu redirect (penting, jika tidak diredirect, nanti session akan stuck)laravel Socialite setup
Mon Jun 9 05:49:13 AM WIB 2025
setup
lihat
config/services.php
, disana hanya ada slack, maka kita tambahin'google' => [ 'client_id' => env('G_SSO_CLIENT_ID'), 'client_secret' => env('G_SSO_CLIENT_SECRET'), 'redirect' => env('G_SSO_REDIRECT_URI'), 'name' => env('G_SSO_NAME'), ],
usage
dapatkan link permintaan akses, pakai
return Socialite::driver('google')->redirect();
ketika user sudah klik continue & accept share datanya, akan dikirimkan callback, pasang ini ke callback
$user = Socialite::driver('google')->user(); dd($user);
laravel pgsql migration setup
Mon Jun 9 05:56:55 AM WIB 2025
PGSQL datatype to laravel mapping function: https://api.laravel.com/docs/12.x/Illuminate/Database/Schema/Blueprint.html
buat migrationnya dengan
php artisan make:migration create_table_abc
run
php artisan migrate
rollback terbaru
php artisan migrate --rollback 1
Other
bookmarks highly useful link
this section is derived from my original channel @xorriso
https://xenbits.xen.org/docs/4.6-testing/misc/pvh.html
"PVH is to make use of the hardware virtualization extensions present in modern x86 CPUs in order to improve performance."
https://wiki.xenproject.org/wiki/Linux_PVH
Where one will select Processor type and features ---> Linux guest support --->Support for running as a PVH guest
https://github.com/Goldside543/goldspace
https://mongoc.org/libmongoc/current/mongoc_client_new.html
kesimpulan: mongoc_client_new return null on error, but not even the string are correct no connection checked. jangan ngeharap mongoc_client_new ngeluarin null
https://faculty.cs.niu.edu/~hutchins/csci480/signals.htm
daftar exit code
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/syscalls/syscall_64.tbl
list syscall
https://www.bitsinthewind.com/about-dac/publications/unix-systems-programming
system programming
https://lwn.net/Articles/205126/
In recent times, Al's work has resulted in a long series of patches merged into the mainline, almost all of which have been marked as "endianness annotations." These patches mostly change the declared types for various functions, variables, and structure members. The new types may be unfamiliar to many, since they are relatively new - though not that new; they were introduced in 2.6.9. These types are __le16, __le32, __le64, __be16, __be32, and __be64.
https://github.com/AugustTan/documents/blob/master/UNIX%20Network%20Programming(Volume1%2C3rd).pdf
https://ics.uci.edu/~aburtsev/143A/2017fall/lectures/
Gas kuliah online tiada kata untuk tidak belajar, di topik ini Pak aburtsev membahas sistem operasi, sistem locknya, memory managemen, kernel, boot step nya, dll
http://osblog.stephenmarz.com/index.html
https://c-ares.org/docs.html#examples
dokumentasi C-ares (async dns resolver)
https://github.com/torvalds/linux/blob/d683b96b072dc4680fc74964eca77e6a23d1fa6e/drivers/char/random.c#L55
"Computers are very predictable devices. Hence it is extremely hard to produce truly random numbers on a computer"
https://stackoverflow.com/questions/17898989/what-is-global-start-in-assembly-language
If you want to use a different entry point name other than _start (which is the default), you can specify -e parameter to ld like
ld -e my_entry_point -o output_filename object_filename
inline ASM GCC
- https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
- https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#AssemblerTemplate
- https://splichal.eu/gccsphinx-final/html/gcc/extensions-to-the-c-language-family/how-to-use-inline-assembly-language-in-c-code.html#inputoperands
http://www.ucw.cz/~hubicka/papers/amd64/node1.html
movabs is ATT-syntax for mov al/ax/eax/rax, byte/[d|q]word ptr [<64-bit absolute address>] or mov byte/[d|q]word ptr[<64-bit absolute address>], al/ax/eax/rax
tambahan: movabs is used for absolute data moves, to either load an arbitrary 64-bit constant into a register or to load data in a register from a 64-bit address.
https://electronicsreference.com/assembly-language/assembly-language-registers/
bookmark movabs
- http://www.ucw.cz/~hubicka/papers/amd64/node1.html
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82339
- https://cs4157.github.io/www/2024-1/lect/13-x86-assembly.html
memory layout linux
this section is pure form, created when I use mdbook
Resume alpro
flowchart
Apa itu flowchart? simplenya, flowchat itu semacam bentuk gambar atau visual dari suatu langkah langkah algoritma. dan tentunya karna ini algoritma, maka ada step step seperti jika x maka y, lalu panah panah dari atas ke bawah, lalu input, dll. contoh flowchart cara memperbiaki lampu
Class
Apa itu class? class adalah cara kita mengatur kode agar scope nya bisa dipecah, misal func a isinya ada 1000 line, nah agar mudah mendebugnya, kita bisa pecah ke method method yang sangat banyak, dan juga kita tidak perlu lagi pusing dengan banyak variabel, kita cukup memakai satu varlable, lalu gunakan di seluruh class yang dinamai "property" contoh simple, pakai property untuk nyimpan-tampilkan data,
#include <string> #include <iostream> using namespace std; class abc { string nama; public: void set_nama(string nama) { this->nama = nama; } void get_nama() { cout << this->nama << endl; } }; int main() { abc abc; abc.set_nama("fadhil"); abc.get_nama(); }
Enkapsulasi (encapsulation)
Trik atau cara agar kita bisa memberi aturan ke class/property apakah ia bisa terlihat (public)? atau tidak (private/protected) ke class.
Intinya, bagaimana cara kita agar method atau property, tidak bisa secara sembarang diakses oleh kode lain. misal kita ada class trigonometri, dan method hitung sin, tetapi didalam hitung sin tersebut, ada method kecil kecil lagi yang banyak, tetapi fungsinya seperti hanya untuk ngebantu fungsi sin menjalankan tugasnya, nah fungsi2 yang kecil tadi itu nanti dibuat private, sedangkan fungsi sin yg dipakai dimana mana, dibuat public.
contoh kecil
#include <string> #include <iostream> using namespace std; class abc { string nama; private: void print_perkenalan() { cout << "perkenalkan nama saya "; } public: void set_nama(string nama) { this->nama = nama; } void get_nama() { this->print_perkenalan(); cout << this->nama << endl; } }; int main() { abc abc; abc.set_nama("fadhil"); abc.get_nama(); }
terlihat public, private? nah itu adalah contoh encapsulation.
nah,
print_perkenalan
(hanya contoh) bertindak seolah olah dia hanya internal function dari suatu class yg besar. dan yang dipanggil dimana mana adalah get nama, dimana dibaliknya dia manggil banyak func yang lain.dan
print_perkenalan
tidak boleh diakses langsung. termasuk propertynama
juga tidak boleh diakses langsungSorting
Bubble Sort
Konsepnya, dengan cara melempar lempar data array, sampai dia urut, BigO nya
O(n^2)
. cara kerja nya yaitu dengan cara menukar-nukar posisi array sekarang dengan array didepannya, jika array saat ini > dari array didepannya, maka tukar posisinyamisal ada data simple seperti ini
2 3 1 (awal mulanya) 2 1 3 (3 ditukar karna 3 > 1) 1 2 3 (2 ditukar karna 2 > 1) 1 2 3 (selesai)
Selection Sort
TL;DR, menemukan data yg lebih kecil dari nilai minimum saat ini, tunggu loopnya yang didalam selesai baru di swap.
contoh kita akan sorting 2 9 4 1 (belum diapa-apakan) 2 9 4 1 (minimum index ke 0, yaitu 2) 2 9 4 1 (bandingkan 9 dgn index ke 0 yaitu 2, 9 < 2 false) 2 9 4 1 (bandingkan 4 dgn index ke 0, yaitu 2, 4 < 2, false) 2 9 4 1 (bandingkan 1 dgn index ke 0, yaitu 2, 1 < 2, true, maka tukar) 1 9 4 2 (set minimum di index ke 1 sekarang, yaitu 9) 1 9 4 2 (bandingkan 4 dgn index ke 1, 4 < 9, true, maka kita biarkan karna loop belum selesai, tapi set minimum ke 4) 1 9 4 2 (cek apakah 2 < 4, ya, set minimum ke 2) 1 2 4 9 (tukar) 1 2 4 9 (set minimum ke index ke 3, yaitu 4, apakah 9 < 4, tidak) --end---
insertion sort
Konsepnya, misal lagi menyusun kartu dari satu per satu. Jadi kamu ambil satu kartu, terus kamu bandingin ke kiri, kalau dia lebih kecil dari yang di kiri-nya, tukar posisinya. Terus begitu sampai semua kartu (data) urut
contoh
5 3 4 1 (unchanged) 3 5 4 1 (3 dimasukkan ke kiri 5 karena 3 < 5) 3 4 5 1 (4 dimasukkan, dia lebih kecil dari 5, jadi tukar) 1 3 4 5 (1 dimasukkan paling kiri, karena dia lebih kecil dari semuanya)
merge sort
misal ada data, terus di bagi-bagi tumpukan data jadi kecil-kecil dulu sampai tinggal satuan, baru nanti disusun lagi sambil dibandingin dan digabungin pelan-pelan sampai jadi urut. Cara kerjanya pakai prinsip divide and conquer Jadi data dibelah-belah jadi dua terus, sampai tinggal 1-an, lalu disatukan lagi sambil diurutin.
contoh gifnya (google)
sequential search
nah, ini search paling gampang wkwkwk, intinya loop terus array nya, jika ketemu idx nya pakai if else, maka break loopnya & end
binary searching
cara mencarinya data dibagi 2 ditengah tengah, lalu setelah dibagi 2, akan ada low (pojok kiri), mid (tengah tengah), high (pojok kanan). lalu cek saja pastikan data yg dicari == mid
jika tidak, maka cek statusnya dia kurang dari mid atau lebih, jika lebih, cari bagian kanan, jika kurang, cari bagian kiri. proses ini diulang terus dan tiap2 menemukan low dan high baru, maka mid pasti berubah.
single linked list
misal, ini PSEUDOCODE
struct node { data_asli, pointer_ke_struct_node_lain_sebut_saja_n }
misal, kita define struct node sebagai a, maka kita ambil addr nya, lalu define lagi b, dimana b berisi data dan juga pointer ke a, lalu misal define lagi c, isinya pointer ke b.
maka secara harfiah, c -> b -> a nah, untuk pengecekan, loop lalu deference terus saja untuk pointernya, jadi yg awalnya di c, setelah deference pointer milik b, posisi sekarang di b, lalu deference pointer next nya, alhasil kita dapat a, dan agar bisa stop. maka bagian palig akhir harus dikasih tanda, contoh disini tandanya bisa pakai nullptr.
intinya jika pas di deference isinya nullptr, maka sudah selesai
sinle linked list circular
sama saja seperti single linked list, hanya aja dibagian akhir daripada diisi nullptr, kita isi pointer balik ke awal. alhasil dia seperti memutar.
Resume alpro double linkedlists
langsung saja ini kodenya, 3 kode bebas, disini saya wrap di func saja karna agar tidak perlu buat banyak file.
penjelasan kode ADA DIBAGIAN BAWAH SNIPPET KODE ini.
#include <cstddef> #include <iostream> using namespace std; struct Node { int data; Node *prev; Node *next; }; Node *create_node(int data) { Node *newly_created_node = new Node; newly_created_node->data = data; newly_created_node->next = nullptr; newly_created_node->prev = nullptr; return newly_created_node; } void print(Node *head) { Node *current = head; cout << "Informasi tentang setiap node:" << endl; while (current != nullptr) { cout << "Alamat: " << current << endl; cout << "Nilai: " << current->data << endl; cout << "Alamat prev: " << current->prev << endl; cout << "Alamat next: " << current->next << endl << endl; current = current->next; } cout << "---------------------------------------" << endl; } void insert_last(Node *&head, int data) { Node *newly_created_node = create_node(data); if (head == nullptr) { head = newly_created_node; } else { Node *current = head; while (current->next != nullptr) { current = current->next; } current->next = newly_created_node; newly_created_node->prev = current; } } void insertFirst(Node *&head, int data) { Node *newNode = create_node(data); if (head == nullptr) { head = newNode; } else { newNode->next = head; head->prev = newNode; head = newNode; } } void delete_first(Node *&head) { if (head == nullptr) { printf("node kosong\n"); } Node *temp = head; head = head->next; if (head != nullptr) { head->prev = nullptr; } delete temp; } int main() { Node *head = nullptr; head = create_node(7); insert_last(head, 1); insert_last(head, 10); delete_first(head); insertFirst(head, 99); print(head); }
func
create_node
Walau bukan bagian dari tugas, saya sekalian jelaskan saja. intinya func ini membuat node baru, yang isinya prev dan next, diisi nullptr (alias nullpointer), dan datanya.
jadi maksud func ini, kita bikin node yang bener2 kosong tanpa terhubung ke siapapun. lalu return value nya.
func
insert_last
Cara kerjanya spt ini.
- kita buat dulu node nya (node yg tidak terhubung dgn siapapun pakai create_node)
- lalu cek, misalkan head yg dari func
main
itu masih nullptr (karna emang defaultnya nullptr), maka pertanda linked listsnya masih kosong, maka kita bisa timpa saja. - jika tidak? kita simpan dulu node saat ini, anggap saja namanya current
- sudah kesimpan kan? current kita arahkan ke
current->next
, alhasil dia ngakses pointer selanjutnya, lalu cek apakah dia nullptr atau bukan (sbg penanda) - misal iya, maka saatnya berhenti, lalu sambung, intinya karna dibelakang nullptr, maka untuk nyambungnya, nullptr kita ganti saja pakai address node yang barusan dibuat.
- agar bisa nyambung kebelaknng, maka prev (previus miliknya new node) kita timpa pakai current, kenapa? node yg terbaru itu prev nya masih nullptr, agar nyambung, maka kita harus isi dengan node sebelumnya yg sudah disimpan.
nb:
Node *&head
artinya nge-deferensi pointer, sekaligus kalau ada perubahan data, sekalian di update, jadi misal ubah data di func delete_last, maka kalau dibaca oleh insert_first, data yg kita share tetep singkronfunc
insertFirst
nah, ini func paling easy wkwk, karna head guarantee akan selalu point ke depan, maka untuk nyispin data didepan sangatlah easy.
buat node baru, lalu node baru (next nya) diisi head. untuk prev (milik nya node lama) kita addr node baru.
func
delete_first
konsepnya mirip dengan insert first, hanya saja
- karna head selalu point ke depan, maka kita perlu simpan head (yang sekarang), lalu saatnya pindah state ke node sebelahnya (kekanan)
- lalu lanjut mark bahwa head->prev itu nullptr, artinya headnya pindah.
- ok sudah, nah, head yang tadi disimpan, bisa di hapus pakai
delete
Rumus sector disk Linux
rumus sector linux
\( x \times 512 = (n \times 1024 \times 1024 \times 1024) \)
dan untuk \( n \) sesuaikan dengan kebutuhan.
disk sector mulai dari 2048. maka misal, x adalah 3145728, command parted nya parted /dev/sda --script mkpart P1 ext4 2048s 3145728s misal ingin menambah sekitar 500 MB, maka offset terakhir ditambah 1, misal
parted /dev/sda --script mkpart P2 ext4 3145729s 4194304s
link referensi
- https://wiki.archlinux.org/title/Parted#UEFI/GPT_examples
- https://ioflood.com/blog/parted-linux-command/
Regex notes
letter & digits
\D+
: Matching all non digits, then grouping
match any using
.
the
.
match all chars, except \r or \nexample: regexp:
r".+"
It will match anything as long as there is at least one character present. no empty string such ""
template workspace json vscode
{ "folders": [ { "path": "rpc" }, { "path": "scraperlib" }, { "path": "offlinelook" } ] }
Protobuf
protobuf ini intinya format pertukaran data, mirip json, tapi dia pakai schema (mirip graphql), agak kaku, dan ada method2
baca spec: https://protobuf.dev/programming-guides/proto3/
ini termasuk prelude nya
syntax = "proto3"; // this is namefile package grpc.fadhil;
lalu ini anggap saja seperti struct, jika di C biasanya sent data over file pakai struct.
message Message1 {} message Message2 { Message1 foo = 1; }
baru kita define semacam namespace yang didalamnya hold func func yang akan dicall oleh grpc
service SearchService { rpc Search(SearchRequest) returns (SearchResponse); }
Subnetting
pertama tama, range ip dahulu
-
A: 1 - 127
-
B: 128 - 191
-
C: 192 - AKHIR
-
0b00000000
-> 0 (katakanlah octet ke 4, cidr 24) -
0b10000000
-> 0 (cidr 25, 128 hosts) // 2 network -
0b11000000
-> 0 (cidr 26, 128 + 64) // 4 network -
0b11100000
-> 0 (cidr 27, 128 + 64 + 32) // 8 network -
0b11110000
-> 0 (cidr 28, 128 + 64 + 32 + 16) // 16 network -
0b11111000
-> 0 (cidr 29, 128 + 64 + 32 + 16 + 8) // 32 network -
0b11111100
-> 0 (cidr 30, 128 + 64 + 32 + 16 + 8 + 4) // 64 network -
0b11111110
-> 0 (cidr 31, 128 + 64 + 32 + 16 + 8 + 4 + 2) // 128 network -
0b11111111
-> 0 (cidr 32, 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1) // 256 network
seperti yg terlihat, bahwa
128 + 64 + 32 + 16 + 8 + 4 + 2 + 1
=255
contoh 192.168.10.0/24:
ada network 192.168.10.0/24, kita ingin bagi jadi 4 jaringan. maka 256 / 4 = 64 hosts, dan ini akan
- subnet nya: 255.255.255.192
- 64 hosts: 64 hosts usable, 1 untuk broadcast, 1 untuk network
pembagian nya
- network 1: 192.168.10.0, broadcast: 192.168.10.63, range ip yang usable: 192.168.10.1 - 192.168.10.62
- network 2: 192.168.10.64, broadcast: 192.168.10.127, range ip yang usable: 192.168.10.65 - 192.168.10.126
- network 3: 192.168.10.128, broadcast: 192.168.10.191, range ip yang usable: 192.168.10.129 - 192.168.10.190
- network 4: 192.168.10.192, broadcast: 192.168.10.255, range ip yang usable: 192.168.10.193 - 192.168.10.254
oprekan hitung2 an:
origin: pakai acuan ip kelas c
jumlah hosts, misal cidr 24, itu max nya 256 kalau 0b11111111, kenapa 0b10000000 itu 128, dan kenapa 0b11000000 itu 192
ok, lalu kenapa jika cidr /26, itu 255.255.255.192, punya 64 hosts, 4 network. semua ini didapat dari (max int case ini 8 bit) / maxint - pad network
ini start dari /24
0b00000000
-> 0 (katakanlah octet ke 4, cidr 24) // 1 network0b10000000
-> 0 (cidr 25, 128 hosts) // 2 network0b11000000
-> 0 (cidr 26, 128 + 64) // 4 network0b11100000
-> 0 (cidr 27, 128 + 64 + 32) // 8 network0b11110000
-> 0 (cidr 28, 128 + 64 + 32 + 16) // 16 network0b11111000
-> 0 (cidr 29, 128 + 64 + 32 + 16 + 8) // 32 network0b11111100
-> 0 (cidr 30, 128 + 64 + 32 + 16 + 8 + 4) // 64 network0b11111110
-> 0 (cidr 31, 128 + 64 + 32 + 16 + 8 + 4 + 2) // 128 network0b11111111
-> 0 (cidr 32, 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1) // 256 network
start dari /16
0b0000000000000000
-> 0 (cidr 16, 65535) // 1 net, 65535 hosts0b1000000000000000
-> 0 (cidr 17, 65535 + ) // 2 net, 32767 hosts0b1100000000000000
-> 0 (cidr 26, 128 + 64) // 4 net0b1110000000000000
-> 0 (cidr 27, 128 + 64 + 32) // 8 net0b1111000000000000
-> 0 (cidr 28, 128 + 64 + 32 + 16) // 16 net0b1111100000000000
-> 0 (cidr 29, 128 + 64 + 32 + 16 + 8) // 32 net0b1111110000000000
-> 0 (cidr 30, 128 + 64 + 32 + 16 + 8 + 4) // 64 net0b1111111000000000
-> 0 (cidr 31, 128 + 64 + 32 + 16 + 8 + 4 + 2) // 128 net0b1111111100000000
-> 0 (cidr 32, 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1) // 256 net
-- stagging (perhitungan ip cidr 16 keatas) max int 16 bit: 65536
- /16 :
0b0000000000000000
= 0 - /17 :
0b1000000000000000
= 32768, maka 65536 / 32768 = 2, alias 2 network, 32768 hosts - /18 :
0b1100000000000000
= 49152, maka 65536 / (65536 - 49152) = 4 network, 16384 hosts, - /19 :
0b1110000000000000
= 57344, maka 65536 / (65536 - 57344) = 8 network, 8192 hosts, - /20 :
0b1111000000000000
= 61440, maka 65536 / (65536 - 61440) = 16 network, 4096 hosts, - /21 :
0b1111100000000000
= 61440, maka 65536 / (65536 - 61440) = 32 network, 2048 hosts, - /22 :
0b1111110000000000
= 64512, maka 65536 / (65536 - 64512) = 64 network, 1024 hosts, - /23 :
0b1111111000000000
= 64512, maka 65536 / (65536 - 64512) = 128 network, 512 hosts, - /24 :
0b1111111100000000
= 64512, maka 65536 / (65536 - 64512) = 256 network, 256 hosts,
-- stagging cidr 8 keatas max int int 24 bit: 16777216
-
/9 :
0b100000000000000000000000
= 16777216 / (16777216 - 8388608) = 2 network, 8388608 hosts -
/10:
0b110000000000000000000000
= 16777216 / (16777216 - 12582912)= 4 network, 4194304 hosts -
/11:
0b111000000000000000000000
= 16777216 / (16777216 - 14680064)= 8 network, 2097152 hosts -
/12:
0b111100000000000000000000
= 16777216 / (16777216 - 15728640)= 16 network, 1048576 hosts -
/13:
0b111110000000000000000000
= 16777216 / (16777216 - 16252928)= 32 network, 524288 hosts -
/14:
0b111111000000000000000000
= 16777216 / (16777216 - 16515072) = 64 network, 262144 hosts -
/15:
0b111111100000000000000000
= 16777216 / (16777216 - 16646144) = 128 network, 131072 hosts -
/16:
0b111111110000000000000000
= 16777216 / (16777216 - 16711680) = 256 network, 65536 hosts -
/17:
0b111111111000000000000000
= 16777216 / (16777216 - 16744448) = 512 network, 32768 hosts -
/18:
0b111111111100000000000000
= 16777216 / (16777216 - 16760832) = 1024 network, 16384 hosts -
/19:
0b111111111110000000000000
= 16777216 / (16777216 - 16769024) = 2048 network, 8192 hosts -
/20:
0b111111111111000000000000
= 16777216 / (16777216 - 16773120) = 4096 network, 4096 hosts -
/21:
0b111111111111100000000000
= 16777216 / (16777216 - 16775168) = 8192 network, 2048 hosts -
/9 : 0b100000000000000000000000:
kumpulan rumus rumus
subnet
rumusnya: \( 2^{jumlah \space angka \space 1 \space di \space setiap \space padding \space subnet}\)
contoh
- prefix /19, pad terdekatnya /16, maka dari 16 ke 19 ada 3 angka 1 (
0b11100000
), maka jumlah subnet yang akan terbentuk adalah 2^3 = 8 subnet - prefix /26, pad terdekatnya 24, maka dari 24 ke 26 ada 2 angka 1 (
0b11000000
), maka jumlah subnetnya 2^2 = 4
jumlah hosts
rumusnya: \( 2^{jumlah \space angka \space 0 \space dari \space 32} \)
contoh
- prefix /19, 32 - 19 = 13 angka 0, maka \( 2^{13} = 8192 \space hosts \)
- prefix /26, 32 - 26 = 6 angka 0, maka \( 2^{6} = 64 \space hosts \)
- prefix /8, 32 - 8 = 24 angka 0, maka \( 2^{24} = 16777216 \space hosts \)
Inter-VLAN routing
how to config vlan inter-VLAN routing
topology:
- VNET1:192.168.10.0/24 (vlan 10)
- PC1: 192.168.10.2
- PC2: 192.168.10.3
- VNET2:192.168.20.0/24 (vlan 20)
- PC3: 192.168.20.2
- PC4: 192.168.20.3
- ROUTER IP (fa0/0.10): 192.168.10.1
- ROUTER IP (fa0/0.20): 192.168.20.1
SCRIPTS
management
-
show vlan brief
: show all configured vlansetup vlan (tanpa setup ip dulu)
Switch>enable Switch#conf t Enter configuration commands, one per line. End with CNTL/Z. Switch(config)#vlan 10 Switch(config-vlan)#name SALES Switch(config-vlan)#ex Switch(config)#vlan 20 Switch(config-vlan)#name IT
lalu setup mode
- trunk: untuk switch ke router
- access: untuk switch ke PC
setup untuk vlan 10 dan 10, masing2 dengan network 192.168.10.0/24 dan 192.168.20.0/24
script:
Switch#conf t Enter configuration commands, one per line. End with CNTL/Z. Switch(config)#int fa0/1 Switch(config-if)#switchport mode access Switch(config-if)#switchport access vlan 10 Switch(config-if)#ex Switch(config)#int fa0/2 Switch(config-if)#switchport mode access Switch(config-if)#switchport access vlan 10 Switch(config-if)#ex Switch(config)#int fa0/3 Switch(config-if)#switchport mode access Switch(config-if)#switchport access vlan 20 Switch(config-if)#ex Switch(config)#int fa0/4 Switch(config-if)#switchport mode access Switch(config-if)#switchport access vlan 20 Switch(config-if)#ex Switch(config)#
alternative script
Switch(config-if)#int range fa0/1-4 Switch(config-if-range)#switchport mode access
config untuk port fa0/5 ke router (pakai mode trunk)
Switch(config)#int fa0/5 Switch(config-if)#switchport mode trunk Switch(config-if)#
inter-VLAN routing
enable port Fa0/0 (tanpa assign ip dahulu)
Router(config)#int fa0/0 Router(config-if)#no shut Router(config-if)# %LINK-5-CHANGED: Interface FastEthernet0/0, changed state to up %LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/0, changed state to up
assign ip untuk masing2 vlan
Router(config)#interface FastEthernet0/0 Router(config-if)#int fa0/0.10 Router(config-subif)# %LINK-5-CHANGED: Interface FastEthernet0/0.10, changed state to up %LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/0.10, changed state to up Router(config-subif)#encapsulation dot1q 10 Router(config-subif)#ip add 192.168.10.1 255.255.255.0 Router(config-subif)#ex Router(config)#int fa0/0.20 Router(config-subif)# %LINK-5-CHANGED: Interface FastEthernet0/0.20, changed state to up %LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/0.20, changed state to up Router(config-subif)#encapsulation dot1q 20 Router(config-subif)#ip add 192.168.20.1 255.255.255.0 Router(config-subif)#
hasil output
show vlan brief
Switch>show vlan brief VLAN Name Status Ports ---- -------------------------------- --------- ------------------------------- 1 default active Fa0/6, Fa0/7, Fa0/8, Fa0/9 Fa0/10, Fa0/11, Fa0/12, Fa0/13 Fa0/14, Fa0/15, Fa0/16, Fa0/17 Fa0/18, Fa0/19, Fa0/20, Fa0/21 Fa0/22, Fa0/23, Fa0/24, Gig0/1 Gig0/2 10 SALES active Fa0/1, Fa0/2 20 IT active Fa0/3, Fa0/4 1002 fddi-default active 1003 token-ring-default active 1004 fddinet-default active 1005 trnet-default active Switch>
tambahan
- encapsulation dot1q: router on stick routing
Advanced switch cisco command
Tealinux qemu promp & testing
create image
qemu-img create -f qcow2 <NAME>.img 45G
- Change 45G with your desired size
running system on BIOS mode
this will open SSH connection on port 20022
live
qemu-system-x86_64 \ -enable-kvm \ -boot order=d \ -cdrom tealinux-2025.02.16-x86_64.iso \ -drive file=tealinux.img,format=qcow2 \ -m 4G \ -enable-kvm \ -smp 4 \ -net user,hostfwd=tcp::20022-:22 \ -net nic
non-live
qemu-system-x86_64 \ -enable-kvm \ -boot order=d \ -drive file=tealinux.img,format=qcow2 \ -m 4G \ -enable-kvm \ -smp 4 \ -net user,hostfwd=tcp::20022-:22 \ -net nic
running on UEFI mode
in order to running qemu on UEFI mode, we need edk2-ovmf
get your ovmf vars by running
cp /usr/share/edk2/x64/OVMF_VARS.4m.fd .
live
qemu-system-x86_64 \ -enable-kvm \ -cdrom tealinux-2025.02.16-x86_64.iso \ -boot order=d \ -drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2/x64/OVMF_CODE.4m.fd \ -drive if=pflash,format=raw,file=OVMF_VARS.4m.fd \ -drive file=tealinux.img,format=qcow2 \ -m 4G \ -enable-kvm \ -smp 4 \ -net user,hostfwd=tcp::20022-:22 \ -net nic
non-live
qemu-system-x86_64 \ -enable-kvm \ -boot order=d \ -drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2/x64/OVMF_CODE.4m.fd \ -drive if=pflash,format=raw,file=OVMF_VARS.4m.fd \ -drive file=tealinux.img,format=qcow2 \ -m 4G \ -enable-kvm \ -smp 4 \ -net user,hostfwd=tcp::20022-:22 \ -net nic
windows
qemu-system-x86_64 \ -enable-kvm \ -boot order=d \ -cdrom Win10_22H2_English_x64v1.iso \ -drive file=windows-tealinux-mbr.img,format=qcow2 \ -m 4G \ -enable-kvm \ -smp 4 \ -net user,hostfwd=tcp::20022-:22 \ -net nic
uefi version
qemu-system-x86_64 \ -enable-kvm \ -boot order=d \ -cdrom Win10_22H2_English_x64v1.iso \ -drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2/x64/OVMF_CODE.4m.fd \ -drive if=pflash,format=raw,file=OVMF_VARS.4m.fd \ -drive file=tealinux.img,format=qcow2 \ -m 4G \ -enable-kvm \ -smp 4 \ -net user,hostfwd=tcp::20022-:22
note: bug unwrap error
qemu-system-x86_64 \ -enable-kvm \ -boot order=d \ -cdrom tealinux-2025.02.16-x86_64.iso \ -drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2/x64/OVMF_CODE.4m.fd \ -drive if=pflash,format=raw,file=OVMF_VARS.4m.fd \ -drive file=tealinux.img,format=qcow2 \ -m 4G \ -enable-kvm \ -smp 4 \ -net user,hostfwd=tcp::20022-:22 \ -net nic
misc
add more drive
in order add more drive, use this param
-drive file=img1.img,format=qcow2
-drive file=img1.img,format=qcow2
forward more port
imagine you need to forward another port, not only ssh, the correct command is
-net user,hostfwd=tcp::10022-:22,hostfwd=tcp::8080-:8080,hostfwd=tcp::5173-:5173
5173 is our port.
binary operation
catatan subnetting from scratch
origin: pakai acuan ip kelas c
jumlah hosts, misal cidr 24, itu max nya 256 kalau 0b11111111, kenapa 0b10000000 itu 128, dan kenapa 0b11000000 itu 192
ok, lalu kenapa jika cidr /26, itu 255.255.255.192, punya 64 hosts, 4 network. semua ini didapat dari (max int case ini 8 bit) / maxint - pad network
ini start dari /24
0b00000000
-> 0 (katakanlah octet ke 4, cidr 24) // 1 network0b10000000
-> 0 (cidr 25, 128 hosts) // 2 network0b11000000
-> 0 (cidr 26, 128 + 64) // 4 network0b11100000
-> 0 (cidr 27, 128 + 64 + 32) // 8 network0b11110000
-> 0 (cidr 28, 128 + 64 + 32 + 16) // 16 network0b11111000
-> 0 (cidr 29, 128 + 64 + 32 + 16 + 8) // 32 network0b11111100
-> 0 (cidr 30, 128 + 64 + 32 + 16 + 8 + 4) // 64 network0b11111110
-> 0 (cidr 31, 128 + 64 + 32 + 16 + 8 + 4 + 2) // 128 network0b11111111
-> 0 (cidr 32, 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1) // 256 network
start dari /16
0b0000000000000000
-> 0 (cidr 16, 65535) // 1 net, 65535 hosts0b1000000000000000
-> 0 (cidr 17, 65535 + ) // 2 net, 32767 hosts0b1100000000000000
-> 0 (cidr 26, 128 + 64) // 4 net0b1110000000000000
-> 0 (cidr 27, 128 + 64 + 32) // 8 net0b1111000000000000
-> 0 (cidr 28, 128 + 64 + 32 + 16) // 16 net0b1111100000000000
-> 0 (cidr 29, 128 + 64 + 32 + 16 + 8) // 32 net0b1111110000000000
-> 0 (cidr 30, 128 + 64 + 32 + 16 + 8 + 4) // 64 net0b1111111000000000
-> 0 (cidr 31, 128 + 64 + 32 + 16 + 8 + 4 + 2) // 128 net0b1111111100000000
-> 0 (cidr 32, 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1) // 256 net
-- stagging (perhitungan ip cidr 16 keatas) max int 16 bit: 65536
- /16 : 0b0000000000000000 = 0
- /17 : 0b1000000000000000 = 32768, maka 65536 / 32768 = 2, alias 2 network, 32768 hosts
- /18 : 0b1100000000000000 = 49152, maka 65536 / (65536 - 49152) = 4 network, 16384 hosts,
- /19 : 0b1110000000000000 = 57344, maka 65536 / (65536 - 57344) = 8 network, 8192 hosts,
- /20 : 0b1111000000000000 = 61440, maka 65536 / (65536 - 61440) = 16 network, 4096 hosts,
- /21 : 0b1111100000000000 = 61440, maka 65536 / (65536 - 61440) = 32 network, 2048 hosts,
- /22 : 0b1111110000000000 = 64512, maka 65536 / (65536 - 64512) = 64 network, 1024 hosts,
- /23 : 0b1111111000000000 = 64512, maka 65536 / (65536 - 64512) = 128 network, 512 hosts,
- /24 : 0b1111111100000000 = 64512, maka 65536 / (65536 - 64512) = 256 network, 256 hosts,
-- stagging cidr 8 keatas max int int 24 bit: 16777216
-
/9 : 0b100000000000000000000000 = 16777216 / (16777216 - 8388608) = 2 network, 8388608 hosts
-
/10: 0b110000000000000000000000 = 16777216 / (16777216 - 12582912)= 4 network, 4194304 hosts
-
/11: 0b111000000000000000000000 = 16777216 / (16777216 - 14680064)= 8 network, 2097152 hosts
-
/12: 0b111100000000000000000000 = 16777216 / (16777216 - 15728640)= 16 network, 1048576 hosts
-
/13: 0b111110000000000000000000 = 16777216 / (16777216 - 16252928)= 32 network, 524288 hosts
-
/14: 0b111111000000000000000000 = 16777216 / (16777216 - 16515072) = 64 network, 262144 hosts
-
/15: 0b111111100000000000000000 = 16777216 / (16777216 - 16646144) = 128 network, 131072 hosts
-
/16: 0b111111110000000000000000 = 16777216 / (16777216 - 16711680) = 256 network, 65536 hosts
-
/17: 0b111111111000000000000000 = 16777216 / (16777216 - 16744448) = 512 network, 32768 hosts
-
/18: 0b111111111100000000000000 = 16777216 / (16777216 - 16760832) = 1024 network, 16384 hosts
-
/19: 0b111111111110000000000000 = 16777216 / (16777216 - 16769024) = 2048 network, 8192 hosts
-
/20: 0b111111111111000000000000 = 16777216 / (16777216 - 16773120) = 4096 network, 4096 hosts
-
/21: 0b111111111111100000000000 = 16777216 / (16777216 - 16775168) = 8192 network, 2048 hosts
-
/9 : 0b100000000000000000000000:
set PATH fish shell
first, edit this
nvim /home/$(whoami)/.config/fish/config.fish
add this line before
if status is-interactive
set -gx PATH /new/path $PATH