Pemrograman IP Versi 6 dengan C author: ev1lut10n pola pikir : 60 % teknis , 40 % strategis (bisnis) gopher: gopher://sdf.org/1/users/wisdomc0 (why use gopher? it's because i still love old protocols) blog: http://myw1sd0m.blogspot.com motto: "berhubung pala lagi mumet gara 2 bikin botnet (almost 2 years) jd maen2 dulu bentar buat penyegaran " * Sekilas IP Versi 6 ip versi 6 merupakan metode pengalamatan jaringan terbaru saat ini, setelah ip versi 4. beberapa os modern saat ini sudah support ip versi 6, untuk windows setau ane mulai support sejak vista. ip versi 6 pengalamatanya berbeda dg ip versi 4, coba perhatikan (mesin harus dikonfigurasi untuk support ip versi 6, untuk konfigurasi tdk dibahas di sini krn bukan bagian permainan): ip versi 4 (the kuno model): ----------------- root@mywisdom-Vostro1310:/mnt/sda1/xampp/htdocs/gaharu# ping google.com PING google.com (74.125.235.51) 56(84) bytes of data. 64 bytes from 74.125.235.51: icmp_req=1 ttl=55 time=19.5 ms ------------------- ip versi 6: ------------------------- root@mywisdom-Vostro1310:/mnt/sda1/xampp/htdocs/gaharu# ping6 ipv6.google.com PING ipv6.google.com(2404:6800:800b::68) 56 data bytes 64 bytes from 2404:6800:800b::68: icmp_seq=2 ttl=57 time=216 ms 64 bytes from 2404:6800:800b::68: icmp_seq=3 ttl=57 time=216 ms -------------------------- dari hasil resolve di atas jelas keliatan beda model pengalamatanya. ip versi empat modelnya : xxx.xxx.xxx.xxx di mana xxx adalah angka 0 sampai dengan 255 desimal ip versi 6 contoh model pengalamatanya adalah: 2001:0000:53aa:64c:383a:45ca:8977:b4db setiap blok dipisahkan oleh : (titik dua), dengan jumlah blok 8 setiap blok merupakan angka hexadesimal, alamat di atas bisa dikompress menjadi: 2001:0:53aa:64c:383a:45ca:8977:b4db atau 2001::53aa:64c:383a:45ca:8977:b4db perbedaan2 lain ip versi 4 dan 6 1. tidak ada broadcast karena sudah ditangani oleh multicast 2. ip versi 4 panjangnya 32 bit , ip versi 6 hingga 128 bit (2 ^ 128 alamat unik) 3. gak ada kelas 4. what about loopback?? alamat loopback (localhost yg biasa kita kenal dg 127.0.0.1) di ip versi 6 adl: ::1 ------------------ root@mywisdom-Vostro1310:/mnt/sda1/xampp/htdocs/gaharu# ping6 ::1 PING ::1(::1) 56 data bytes 64 bytes from ::1: icmp_seq=1 ttl=64 time=0.026 ms 64 bytes from ::1: icmp_seq=2 ttl=64 time=0.033 ms root@mywisdom-Vostro1310:/mnt/sda1/xampp/htdocs/gaharu# traceroute6 ::1 traceroute to ::1 (::1) from ::1, 30 hops max, 16 byte packets 1 mywisdom-Vostro1310 (::1) 0.056 ms 0.03 ms 0.021 ms root@mywisdom-Vostro1310:/mnt/sda1/xampp/htdocs/gaharu# --------------------- * ip versi 6 kita ??? root@mywisdom-Vostro1310:/home/mywisdom/asm# ifconfig eth0 Link encap:Ethernet HWaddr 00:1c:23:56:0b:10 inet addr:118.136.75.36 Bcast:118.136.75.255 Mask:255.255.255.0 inet6 addr: fe80::21c:23ff:fe56:b10/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:158525 errors:0 dropped:0 overruns:0 frame:0 TX packets:126790 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:186207641 (186.2 MB) TX bytes:19747224 (19.7 MB) Interrupt:44 Base address:0xc000 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:205839 errors:0 dropped:0 overruns:0 frame:0 TX packets:205839 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:165648554 (165.6 MB) TX bytes:165648554 (165.6 MB) teredo Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 inet6 addr: 2001:0:53aa:64c:383a:45ca:8977:b4db/32 Scope:Global inet6 addr: fe80::ffff:ffff:ffff/64 Scope:Link UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1280 Metric:1 RX packets:32 errors:0 dropped:0 overruns:0 frame:0 TX packets:61 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:500 RX bytes:5936 (5.9 KB) TX bytes:6878 (6.8 KB) ip versi 6 di mesin ini: 2001:0:53aa:64c:383a:45ca:8977:b4db 0010000000000001 0000000000000000 0101001110101010 0110010000001100 0011100000111010 0100010111001010 1000100101110111 1011010011011011 * cara mengakses ip versi 6 via browser ??? misal kita akan mengakses ip versi 6 dari ipv6.google.com via browser: ------------------------ root@mywisdom-Vostro1310:/home/mywisdom/asm# host ipv6.google.com ipv6.google.com is an alias for ipv6.l.google.com. ipv6.l.google.com has IPv6 address 2404:6800:800b::67 ----------------------- via web browser ketikkan url ini: http://[2404:6800:800b::67] untuk lebih mendalami ip versi 6 silahkan pelajari sendiri di http://www.apnic.net/community/ipv6-program *. TCP klien untuk ip versi 6 jika kita lihat sebelumnya kita memrogram socket untuk ip versi 4; http://myw1sd0m.blogspot.com/2011/04/socket-programming-dengan-c-linux.html untuk versi 6 teknik pemrogramanya agak sedikit berbeda. berikut ini contoh untuk meresolve hostname devilzc0de.org utk mendapatkan ip versi 4 ip versi 4 resolve , make stream socket (we talk tcp here) and connect to spesific port by dom dom filename: res4.c --------------------------- #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <string.h> #include <netinet/in.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> int main() { int soket,target; struct sockaddr_in server; if((target=gethostbyname("google.com")) == NULL) { printf("\n[-]fungsi gethostbyname gagal ! keluar dari program ! \n"); exit(1); } else { printf ("\n[+]fungsi gethostbyname berhasil, ip google adalah: %u.%u.%u.%u\n",(unsigned char)target->h_addr[0],(unsigned char)target->h_addr[1],(unsigned char)target->h_addr[2],(unsigned char)target->h_addr[3]); } if((soket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("\ngagal menciptakan socket !! keluar dari program !\n"); exit(1); } else { printf ("\n[+]di sini file deskriptor telah siap !! selanjutnya kita akan melakukan fungsi connect\n"); } //kita isi struktur sockaddr_in, berupa sin_family=AF_INET untuk koneksi TCP/IP. sin_addr data alamat ip,sin_port berisi nomor port server.sin_family=AF_INET; server.sin_addr.s_addr=*(long *)(target->h_addr); server.sin_port=htons(80); //setelah itu kita akan mencoba memanggil fungsi connect() untuk terhubung ke server if(connect(soket, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) { printf("\n[-]koneksi ke google.com via port 80 gagal\n"); exit(1); } else { printf("\n[+]fungsi connect() ke google.com via port 80 berhasil !!! selanjutnya kita akan bermain di send dan recv\n"); } } --------------- kompile dan tes: -------------- oot@mywisdom-Vostro1310:/home/mywisdom/asm# gcc -o res4 res4.c root@mywisdom-Vostro1310:/home/mywisdom/asm# ./res4 [+]fungsi gethostbyname berhasil, ip google adalah: 74.125.235.52 [+]di sini file deskriptor telah siap !! selanjutnya kita akan melakukan fungsi connect [+]fungsi connect() ke google.com via port 80 berhasil !!! selanjutnya kita akan bermain di send dan recv root@mywisdom-Vostro1310:/home/mywisdom/asm# ---------------- struktur ip versi 4 bisa dilihat di: /usr/include/netinet/in.h sbb: /* Structure describing an Internet socket address. */ struct sockaddr_in { __SOCKADDR_COMMON (sin_); in_port_t sin_port; /* Port number. */ struct in_addr sin_addr; /* Internet address. */ /* Pad to size of `struct sockaddr'. */ unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (in_port_t) - sizeof (struct in_addr)]; }; sedangkan struktur ip versi 6 juga bisa dilihat di /usr/include/netinet/in.h : --------------- /* Ditto, for IPv6. */ struct sockaddr_in6 { __SOCKADDR_COMMON (sin6_); in_port_t sin6_port; /* Transport layer port # */ uint32_t sin6_flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ uint32_t sin6_scope_id; /* IPv6 scope-id */ }; --------------- dari header ini kita tidak melihat adanya sin_family,jika kita lihat lebih jauh ke file /usr/include/bits/sockaddr.h kita bisa melihat makro sbb: -------------------- #define __SOCKADDR_COMMON(sa_prefix) \ sa_family_t sa_prefix##family ---------------------- di mana makro tersebut akan mengambil parameter dari sa_prefix dan menggabungkanya sehingga akan tercipta variabel baru sin_family untuk struktur sockaddr_in di ip versi 4 ------------- sa_prefix##family-> sin_family -------------- karena di ip versi 6 prefix adl: sin6_ maka kita pakai: sin6_family untuk protokol family ( domain ) ip versi 6 kita akan pakai : --------------------------------------- root@mywisdom-Vostro1310:/home/mywisdom/asm# cat cat /usr/include/bits/socket.h | grep INET6 cat: cat: No such file or directory #define PF_INET6 10 /* IP version 6. */ #define AF_INET6 PF_INET6 root@mywisdom-Vostro1310:/home/mywisdom/asm# ---------------------------------------- kita akan pakai AF_INET6 atau aliasnya adalah PF_INET6 , untuk membuat socket di ip versi 4, berikut ini perbedaannya untuk pembuatan socket di ip v 4 dan ip v 6: ip versi 4 : socket(AF_INET, SOCK_STREAM, 0) klo di bawah 0 ret val berarti gagal untuk ip versi 6: socket(AF_INET6, SOCK_STREAM, 0) klo di bawah 0 retval berarti gagal struktur untuk ip versi 4 di atas tadi kita pakai struktur (misal untuk mengisi struktur target host (mangsa kita)): server.sin_family=AF_INET; server.sin_port=htons(80); sedangkan untuk ip versi 6 akan kita modifikasi sedikit menjadi: server.sin6_family = AF_INET6; //sin6_family kita gunakan PF_INET6 server.sin6_len = sizeof(struct in6_addr); sedangkan untuk fungsi gethostbyname() bisa kita diganti dengan fungsi: getaddrinfo klo mao tetep paket gethostbyname tambahkan ini : res_init(); _res.options |= RES_USE_INET6; berarti untuk gethostbyname kita pakai opsi ip versi 6 dengan menambah header: #include <resolve.h> contoh untuk resolve: ------------ oot@mywisdom-Vostro1310:/home/mywisdom/asm# cat res6.c #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <string.h> #include <netinet/in.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <resolv.h> int main() { int soket,target; //struktur hostent bisa dilihat di /usr/include/netdb.h , berguna untuk mengirimkan dns query struct sockaddr_in6 addr; //perhatikan di sini kita pakai res_init() dan _res.option kita pakai untuk support ip versi 6 res_init(); _res.options |= RES_USE_INET6; if((target=gethostbyname("ipv6.google.com")) == NULL) { printf("\n[-]fungsi gethostbyname gagal ! keluar dari program ! \n"); exit(1); } else { printf ("\n[+]fungsi gethostbyname berhasil"); } if((soket = socket(AF_INET6, SOCK_STREAM, 0)) == -1) { printf("\ngagal menciptakan socket !! keluar dari program !\n"); exit(1); } else { printf ("\n[+]di sini file deskriptor telah siap !! selanjutnya kita akan melakukan fungsi connect\n"); } } root@mywisdom-Vostro1310:/home/mywisdom/asm# ----------------------------------- berikut ini adl sample klien dari artikel ipv6 socket programming (joonbok lee): ---------------- int main(int argc, char **argv){ char Buffer[BUFFER_SIZE]; char *Server = DEFAULT_SERVER; /* "143.248.226.231" "2001:320:1a10:3:204:76ff:fe2f:cc34" "cosmos.kaist.ac.kr" */ int Family = DEFAULT_FAMILY; /* AF_INET, AF_INET6, AF_UNSPEC */ int SocketType = DEFAULT_SOCKTYPE; /* SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, ... */ char *Port = DEFAULT_PORT; int i, RetVal, AddrLen, AmountToSend; struct addrinfo Hints, *AddrInfo, *AI; socket ConnSocket; struct sockaddr_storage Addr; memset(&Hints, 0, sizeof(Hints)); Hints.ai_family = AF_UNSPEC; /* AF_INET: IPv4 address, AF_INET6: IPv6 address, AF_UNSPEC: IPv4 and IPv6 address */ Hints.ai_socktype = SOCK_STREAM; /* SOCK_STREAM: TCP, SOCK_DGRAM: UDP */ RetVal = getaddrinfo(Server, Port, &Hints, &AddrInfo); if (RetVal != 0) { fprintf(stderr, "Cannot resolve address [%s] and port [%s], error %d: %s\n", Server, Port, RetVal, gai_strerror(RetVal)); return -1; } for (AI = AddrInfo; AI != NULL; AI = AI->ai_next) { // Open a socket with the correct address family for this address. // if( AI->ai_family == AF_INET6 ){ ConnSocket = socket(AI->ai_family, AI->ai_socktype, AI-> ai_protocol); if (ConnSocket == INVALID_SOCKET) continue; if (connect(ConnSocket, AI->ai_addr, AI->ai_addrlen) != SOCKET_ERROR) break; // } } freeaddrinfo(Addrinfo); strcpy(Buffer, "Hello, world"); AmmountToSend = strlen(Buffer); RetVal = send(ConnSocket, Buffer, AmmountToSend, 0); RetVal = recv(ConnSocket, Buffer, Buffer, BUFFER_SIZE, 0); closesocket(ConnSocket); } ------------------------------ jadi untuk konek ke ipv6.google.com via port 80, kurang lebih implementasinya seperti ini : pertama 2 kita tes resolve: ------------------------------- /**ip versi 6 - klien - resolve only resolv_ip_v6.c modif sample klien dari artikel ipv6 socket programming (joonbok lee) **/ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <string.h> #include <netinet/in.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <resolv.h> int main(int argc, char **argv) { int Family = PF_INET6; int SocketType = SOCK_STREAM; int i, RetVal, AddrLen, AmountToSend; struct addrinfo Hints, *AddrInfo, *AI; int ConnSocket; struct sockaddr_storage Addr; memset(&Hints, 0, sizeof(Hints)); Hints.ai_family = AF_INET6; Hints.ai_socktype = SOCK_STREAM; RetVal = getaddrinfo(argv[1], argv[2], &Hints, &AddrInfo); if (RetVal != 0) { fprintf(stderr, "Cannot resolve address [%s] and port [%s], error %d: %s\n", argv[1], argv[2], RetVal, gai_strerror(RetVal)); exit(0); } else { printf("\n[+]getaddrinfo success !!!\n"); } } ------------------------- tes getaddrinfo: ----- root@mywisdom-Vostro1310:/home/mywisdom/asm# gcc -o resolve_ip_v6 resolve_ip_v6.c root@mywisdom-Vostro1310:/home/mywisdom/asm# ./resolve_ip_v6 ipv6.google.com 80 [+]getaddrinfo success !!! root@mywisdom-Vostro1310:/home/mywisdom/asm# --------- ok berikut ini adalah kode selengkapnya untuk konek ke ipv6.google.com : ----------------- /**ip versi 6 - klien - resolve and connect to ipv6.google.com konek_ip_v6.c modif sample klien dari artikel ipv6 socket programming (joonbok lee) **/ #include <stdlib.h> #include <string.h> #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <netdb.h> int main() { const char *target="ipv6.google.com"; const char *port="80"; int soket, retval, retval2, addrlen; struct addrinfo Hints, *AddrInfo, *AI; memset(&Hints,0,sizeof(Hints)); Hints.ai_family = AF_UNSPEC; Hints.ai_socktype = SOCK_STREAM; retval = getaddrinfo(target,port, &Hints, &AddrInfo); if(retval!=0) { printf("Cannot resolve requested address\n"); exit(0); } else { printf("\n[+]getaddrinfo sukses"); } for(AI=AddrInfo;AI!=NULL;AI=AI->ai_next) { if(AI->ai_family==AF_INET6) { if((soket=socket(AI->ai_family,AI->ai_socktype,AI->ai_protocol))<0) { printf("\n[-] sorry seems like no ip v 6 support on tis box !\n"); exit(0); } retval2=connect(soket,AI->ai_addr,AI->ai_addrlen); if(retval2<0) { printf ("\n[-] sorry failed to connect !!!\n"); exit(0); } else { printf("\n[+] ip v 6 connect to %s via port %s success !!!\n",target,port); } freeaddrinfo(AddrInfo); } } } ---------------- selanjutnya persiapkan tcpdump untuk mengetes program ini: ------------------------------------ root@mywisdom-Vostro1310:/home/mywisdom/public_html/.backups# ifconfig eth0 Link encap:Ethernet HWaddr 00:1c:23:56:0b:10 inet addr:118.136.75.36 Bcast:118.136.75.255 Mask:255.255.255.0 inet6 addr: fe80::21c:23ff:fe56:b10/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:327977 errors:0 dropped:0 overruns:0 frame:0 TX packets:247696 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:424522875 (424.5 MB) TX bytes:29671615 (29.6 MB) Interrupt:44 Base address:0xc000 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:262330 errors:0 dropped:0 overruns:0 frame:0 TX packets:262330 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:202463181 (202.4 MB) TX bytes:202463181 (202.4 MB) teredo Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 inet6 addr: 2001:0:53aa:64c:383a:45ca:8977:b4db/32 Scope:Global inet6 addr: fe80::ffff:ffff:ffff/64 Scope:Link UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1280 Metric:1 RX packets:222 errors:0 dropped:0 overruns:0 frame:0 TX packets:283 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:500 RX bytes:182160 (182.1 KB) TX bytes:34097 (34.0 KB) root@mywisdom-Vostro1310:/home/mywisdom/public_html/.backups# tcpdump -n -f -s 0 -X -vvv -i teredo port 80 tcpdump: WARNING: teredo: no IPv4 address assigned tcpdump: listening on teredo, link-type RAW (Raw IP), capture size 65535 bytes --------------------------------------------------------- kompile dan jalankan: ---------------------- root@mywisdom-Vostro1310:/home/mywisdom/asm# gcc -o konek_ip_v6 konek_ip_v6.c root@mywisdom-Vostro1310:/home/mywisdom/asm# ./konek_ip_v6 [+]getaddrinfo sukses [+] ip v 6 connect to ipv6.google.com via port 80 success !!! root@mywisdom-Vostro1310:/home/mywisdom/asm# ----------------------------- ok di jendela tcpdump kita bisa lihat koneksi berhasil: ------------------------------------------- 06:47:42.105853 IP6 (hlim 64, next-header TCP (6) payload length: 40) 2001:0:53aa:64c:383a:45ca:8977:b4db.43693 > 2404:6800:800b::93.80: Flags [S], cksum 0x6aa9 (correct), seq 3170785082, win 4880, options [mss 1220,sackOK,TS val 6342831 ecr 0,nop,wscale 6], length 0 0x0000: 6000 0000 0028 0640 2001 0000 53aa 064c `....(.@....S..L 0x0010: 383a 45ca 8977 b4db 2404 6800 800b 0000 8:E..w..$.h..... 0x0020: 0000 0000 0000 0093 aaad 0050 bcfe 573a ...........P..W: 0x0030: 0000 0000 a002 1310 6aa9 0000 0204 04c4 ........j....... 0x0040: 0402 080a 0060 c8af 0000 0000 0103 0306 .....`.......... --------------------------------------- kita bisa lihat 2001:0:53aa:64c:383a:45ca:8977:b4db.43693 > 2404:6800:800b::93.80 ip v 6 kita: 2001:0:53aa:64c:383a:45ca:8977:b4db via source port 43693 melakukan koneksi ke ip v 6 google: 2404:6800:800b::93 via destiantion port: 80 ok sy lanjutkan lain waktu jika ada kesempatan, see u