I recently bought a router and 2 switches(L2 and L3) for a studying purpose. Today I tried one of the switches, Catalyst 2960. I connected two of my PC and see if I can ping from one to the other. After connecting two of my PC to the ports Fa0/1-2, I checked if they are really connected.
Switch>show mac address-table
Mac Address Table
-------------------------------------------
Vlan Mac Address Type Ports
---- ----------- -------- -----
All 0100.0ccc.cccc STATIC CPU
All 0100.0ccc.cccd STATIC CPU
All 0180.c200.0000 STATIC CPU
All 0180.c200.0001 STATIC CPU
All 0180.c200.0002 STATIC CPU
All 0180.c200.0003 STATIC CPU
All 0180.c200.0004 STATIC CPU
All 0180.c200.0005 STATIC CPU
All 0180.c200.0006 STATIC CPU
All 0180.c200.0007 STATIC CPU
All 0180.c200.0008 STATIC CPU
All 0180.c200.0009 STATIC CPU
All 0180.c200.000a STATIC CPU
All 0180.c200.000b STATIC CPU
All 0180.c200.000c STATIC CPU
All 0180.c200.000d STATIC CPU
All 0180.c200.000e STATIC CPU
All 0180.c200.000f STATIC CPU
All 0180.c200.0010 STATIC CPU
All ffff.ffff.ffff STATIC CPU
1 902e.169d.b2f1 DYNAMIC Fa0/1
1 e45f.01d3.5bd9 DYNAMIC Fa0/2
Total Mac Addresses for this criterion: 22
You can see the mac address table has the mac address of the each device connected to the port(Fa0/1-2). However, I wasn't able to ping from my Windows PC(Fa0/1) to Raspberry-pi(Fa0/2). I checked the ARP table of my Windows PC and it showed the list with the mac address of raspberry pi.
C:\>arp -a
Interface: 192.168.1.2 --- 0x11
Internet Address Physical Address Type
192.168.1.3 e4-5f-01-d3-5b-d9 dynamic
192.168.1.255 ff-ff-ff-ff-ff-ff static
The problem was my Windows PC's firewall😅. After configuring its firewall rules to allow ICMP traffic, I was able to ping!
C:\Users\Ryo>ping 192.168.1.3
Pinging 192.168.1.3 with 32 bytes of data:
Reply from 192.168.1.3: bytes=32 time=2ms TTL=64
Reply from 192.168.1.3: bytes=32 time=6ms TTL=64
Reply from 192.168.1.3: bytes=32 time=1ms TTL=64
Reply from 192.168.1.3: bytes=32 time<1ms TTL=64
Ping statistics for 192.168.1.3:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 6ms, Average = 2ms
After studying how different devices work at different layers, I got little confused how ping works if its only given ip address to reach the destination pc connected via switch which is a layer 2 device. Here's how it works.
1. We only have the destination's ip and no mac address info.
->ARP request which is broadcasted to all devices connected to the switch.
2. Once your PC has the mac address in its mac address table, the frame is sent to the switch which contains the mac address of the destination pc.
3. Switch needs to know which port is connected to the PC with the destination mac address.
->Flood the frame to all other ports if the destination mac address is not in the mac address table.
4. Once the switch gets the reply form the destination PC, it now knows which port to send the frame to get to the destination PC!
Here are ARP and Mac address tables before and after ping.
Switch#show mac address-table
Mac Address Table
-------------------------------------------
Vlan Mac Address Type Ports
---- ----------- -------- -----
Switch#show mac address-table
Mac Address Table
-------------------------------------------
Vlan Mac Address Type Ports
---- ----------- -------- -----
1 00e0.8fe3.e0b3 DYNAMIC Fa0/2
1 00e0.f7a1.365d DYNAMIC Fa0/1
C:\>arp -a
No ARP Entries Found
C:\>arp -a
Internet Address Physical Address Type
192.168.1.2 00e0.8fe3.e0b3 dynamic
Some stuff I learned about how Nmap SYN scanning works. Below is the captured packets from Wireshark.
10 13.006851 192.168.100.103 192.168.100.101 TCP 60 44276 → 445 [SYN] Seq=0 Win=1024 Len=0 MSS=1460
15 13.007423 192.168.100.101 192.168.100.103 TCP 60 445 → 44276 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460
16 13.007594 192.168.100.103 192.168.100.101 TCP 60 44276 → 445 [RST] Seq=1 Win=0 Len=0
It shows that the the state of port is open as the server's reply to the nmap's SYN is SYN,ACK. You can observe that SYN scan terminates 3 way handshake by RST sent by nmap. Also, here is the source code I found which I thought might be useful for spoofing Nmap OS detection. You can find the source code here. I think the below code is the part where it specifies the window size of a packet.
/* Numbers are taken from RFC3390.
*
* John Heffner states:
*
* The RFC specifies a window of no more than 4380 bytes
* unless 2*MSS > 4380. Reading the pseudocode in the RFC
* is a bit misleading because they use a clamp at 4380 bytes
* rather than use a multiplier in the relevant range.
*/
__u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst)
{
__u32 cwnd = (dst ? dst_metric(dst, RTAX_INITCWND) : 0);
if (!cwnd) {
if (tp->mss_cache > 1460)
cwnd = 2;
else
cwnd = (tp->mss_cache > 1095) ? 3 : 4;
}
return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
}
I am getting used to reading the hexs shown in Wireshark. Here is the summary of what is going with the below packet sent by my TUN program.
0x00, 0x00, 0x08, 0x00, 0x45, 0x00, 0x00, 0x54, 0x89, 0x4b, 0x40, 0x00, 0x40, 0x01, 0x39, 0x59, 0xcb, 0x00, 0x71, 0x02, 0xcb, 0x00, 0x71, 0x01, 0x08, 0x00, 0x2a, 0xc7, 0x00, 0x19, 0x00, 0x07, 0xc8, 0xb6, 0x8c, 0x63, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x2b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
The first 4 bit (4 of 0x45)
・Version: the fist field tells us which IP version we are using, only IPv4 uses this header so you will always find decimal value 4 here.
The first 4 bit (5 of 0x45)
・The length of the ip header. In the case of this example, 5=>5*4(bytes)=>20(bytes)=>20 pair(0x45)s, as each hex is 4 bits.
・Because of the maximum possible value f=>15, the maximum ip header length is 15*4byte=60byte.
Protocol: 0x01
・1 stands for ICMP, 6 stands for tcp, 17 stands for UDP
Source and destination address: 0xcb, 0x00, 0x71, 0x02, 0xcb, 0x00, 0x71, 0x01
・In decimal, 203.0.113.2 and 203.0.113.1 respectively.
Below is the c program for sending receiving packets using TUN device. You should comment out either the dump_packet() or send_packet(). Otherwise, the program will be sending and receiving packets of its own.
void dump_packet(int fd, int count, char* buffer)
{
printf("the fd is %d. read %d bytes!\n", fd, count);
int i;
for (i=0; i
Wireshark shows the packet are exchanged as below. It's working!
1 0.000000000 203.0.113.2 203.0.113.1 ICMP 86 Echo (ping) request id=0x0019, seq=7/1792, ttl=64 (reply in 2)
2 0.000082333 203.0.113.1 203.0.113.2 ICMP 84 Echo (ping) reply id=0x0019, seq=7/1792, ttl=64 (request in 1)
Below is the database file which Nmap uses as a reference to packet info specific to OS. It is at /usr/share/nmap/nmap-os-db in the case of Ubuntu 20.04.4 LTS.
# Linux 2.6.30-ARCH #1 SMP PREEMPT Wed Sep 9 12:37:32 UTC 2009 i686 AMD Athlon(tm) XP 2000+ AuthenticAMD GNU/Linux
Fingerprint Linux 2.6.30
Class Linux | Linux | 2.6.X | general purpose
CPE cpe:/o:linux:linux_kernel:2.6.30
SEQ(SP=C1-CB%GCD=1-6%ISR=C5-CF%TI=Z%II=I%TS=U)
OPS(O1=M5B4NNSNW6%O2=M5B4NNSNW6%O3=M5B4NW6%O4=M5B4NNSNW6%O5=M5B4NNSNW6%O6=M5B4NNS)
WIN(W1=16D0%W2=16D0%W3=16D0%W4=16D0%W5=16D0%W6=16D0)
ECN(R=Y%DF=Y%T=3B-45%TG=40%W=16D0%O=M5B4NNSNW6%CC=N%Q=)
T1(R=Y%DF=Y%T=3B-45%TG=40%S=O%A=S+%F=AS%RD=0%Q=)
T2(R=N)
T3(R=Y%DF=Y%T=3B-45%TG=40%W=16D0%S=O%A=S+%F=AS%O=M5B4NNSNW6%RD=0%Q=)
T4(R=N)
T5(R=Y%DF=Y%T=3B-45%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
T6(R=N)
T7(R=Y%DF=Y%T=3B-45%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
U1(DF=N%T=3B-45%TG=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)
IE(DFI=N%T=3B-45%TG=40%CD=S)
The Nmap source code can be found here.
I'm curious how Nmap OS detection works. Project like below is something that I am interested! https://nmap.org/misc/defeat-nmap-osdetect.html
I created a TUN interface with the below c program.
int main(int argc, char** argv)
{
if (argc != 2)
return 1;
const char* device_name = argv[1];
if (strlen(device_name) + 1 > IFNAMSIZ)
{
return 1;
}
int fd = open("/dev/net/tun", O_RDWR);
if (fd == -1)
{
return 1;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN;
strncpy(ifr.ifr_name, device_name, IFNAMSIZ);
int res = ioctl(fd, TUNSETIFF, &ifr);
if (res == -1)
{
return 1;
}
printf("the created device is only available during this program\n");
while (1) {
}
return 0;
}
The important part in the above code is below. You can provide the name of the interface to "ifr.ifr_name" and spcify whether you want the interface to be TUN or TAP with "ifr.ifr_flags".
int fd = open("/dev/net/tun", O_RDWR);
int res = ioctl(fd, TUNSETIFF, &ifr);
There is another way of creating TUN device using ip command which is shown below.
$ sudo ip tuntap add dev tun0 mode tun
My next attempt is to receive and read packets using read() and send(). I also want to see how packets are being exchanged using Wireshark.
Maybe TUN/TAP is a good place to start understanding how low-level networking works?
You can check the file descriptor and associated device files with the below command.
$ lsof
cat 307 ryo 1w REG 8, 32 0 106248 /home/ryo/ctf/kernel/file1.txt
Above shows that device files have major and minor numbers to identify the associated device drivers. You can see that 8, 32 are the major and minor number in the above case. You can check which device number has 8, 32 by the below command.
/dev$ ls -la
brw------- 1 root root 8, 32 Nov 23 11:51 sdc
Maybe I should start looking into device drivers used for networking?