Comparasion of OS network activity using wireshark and R (Linux, Windows, OpenBSD)
I used the sqldf library to make things quite a bit easier on myself. This data was in no way normal so I made graphs instead of doing any real statistical analysis. The full CSV files and RMarkdown can be downloaded here. Every code block in this post is R with the exception of the first which is a combination of shell and windows cmd.
library("sqldf");
Capturing Packets
I ran wireshark for 1 hour and captured packets from 3 separate operating systems to see what kinds of network traffic they do by default. These systems were installed as virtual machines. I waited approximately one minute after booting the systems before logging in. The log in is important because “what is this system doing in the background that the user is unaware of?” was the primary question. It is typical for a system to spawn new processes upon login which can optionally do something on the network.
Specific version information (they are all the ‘default installation’): There are a few quirks. Fedora is the official workstation edition. Windows is reporting that it is windows 10 when it is actually windows 11 Home edition. OpenBSD 7.4 is not being deceptive about what it actually is.
fedora:~$ uname -a
Linux fedora 6.6-13-200.fc39.x86_64 #1 SMP PREEMPT_DYNAMIC x86_64 GNU/Linux
openbsd# uname -a
OpenBSD openbsd.localdomain 7.4 GENERIC.MP#1379 amd64
C:\Users\user>ver
Microsoft Windows [Version 10.0.22621.3007]
Loading data, counting packets
Packet count is the number of packets the system both received and sent.
fedora = read.csv("fedora/fedora.csv");
obsd = read.csv("obsd/obsd.csv");
win = read.csv("win/win.csv");
sqldf("select count(*) from fedora");
## count(*)
## 1 1047
sqldf("select count(*) from obsd");
## count(*)
## 1 1481
sqldf("select count(*) from win");
## count(*)
## 1 6960
Traffic graphs
The traffic graphs are a simple way to crudely illustrate “network load” which is very similar to bytes per second.
plot(win$Length~win$Time, type='l', lwd=1, col="blue", xlab="time in seconds", ylab="packet size in bytes", main="Traffic Graph by time");
lines(fedora$Length~fedora$Time, lwd=1, type="l", col="red");
lines(obsd$Length~obsd$Time, type='l', lwd=1, col="orange");
legend(x='topright', legend=c("Windows", "Fedora", "OpenBSD"), col=c("blue", "red", "orange"), lwd=2)
Because it is hard to see the finer points, individual graphs are useful.
plot(obsd$Length~obsd$Time, type='l', lwd=1, col="orange", xlab="time in seconds", ylab="packet size in bytes", main="Traffic Graph by time (OpenBSD)");
legend(x='topright', legend=c("OpenBSD"), col=c("orange"), lwd=2)
The major spikes in the OpenBSD graph are the HTTPS connections which are caused by OpenNTPD.
plot(fedora$Length~fedora$Time, type='l', lwd=1, col="red", xlab="time in seconds", ylab="packet size in bytes", main="Traffic Graph by time (Fedora)");
legend(x='topright', legend=c("Fedora"), col=c("red"), lwd=2)
The major spike in the fedora graph is a series of connections to github.com. This is because of gnome-software and PackageKit which automatically check for updates when a user logs in. If the user uninstalls PackageKit and gnome-software these connections to github don’t happen.
plot(win$Length~win$Time, type='l', lwd=1, col="blue", xlab="time in seconds", ylab="packet size in bytes", main="Traffic Graph by time (Windows)");
legend(x='topright', legend=c("Windows"), col=c("blue"), lwd=2)
Windows is sending and receiving a lot of data with multiple CDNs.
Calculating total size of all transmissions
The wireshark Length
field is a record of the packet size in bytes. We can use this field to graph the sum of data transmitted by time.
sqldf("select sum(Length) as sum_bytes from fedora")/1024 # conversion to KB for easy reading
## sum_bytes
## 1 169.3242
sqldf("select sum(Length) as sum_bytes from obsd")/1024 # conversion to KB for easy reading
## sum_bytes
## 1 140.3525
sqldf("select sum(Length) as sum_bytes from win")/1024/1024 # conversion to MB for easy reading
## sum_bytes
## 1 5.525936
Some loops to get a running total:
fedora_rtotal = vector();
fedora_x = vector();
n = 0;
for(i in fedora$No.){
if(!is.na(fedora$Length[i])){
n = fedora$Length[i] + n;
fedora_rtotal = c(fedora_rtotal, n);
fedora_x = c(fedora_x, fedora$Time[i]);
}
}
obsd_rtotal = vector();
obsd_x = vector();
n = 0;
for(i in obsd$No.){
if(!is.na(obsd$Length[i])){
n = obsd$Length[i] + n;
obsd_rtotal = c(obsd_rtotal, n);
obsd_x = c(obsd_x, obsd$Time[i]);
}
}
win_rtotal = vector();
win_x = vector();
n = 0;
for(i in win$No.){
if(!is.na(win$Length[i])){
n = win$Length[i] + n;
win_rtotal = c(win_rtotal, n);
win_x = c(win_x, win$Time[i]);
}
}
plot(win_x, win_rtotal, type='l', col='blue', ylab='sum of packet sizes in bytes', xlab='time', main='Plot of running totals in bytes');
lines(fedora_x, fedora_rtotal, type='l', col='red');
lines(obsd_x, obsd_rtotal, type='l', col='orange');
legend(x = "right", legend = c("Windows", "Fedora", "OpenBSD"), col=c("blue", "red", "orange"), lwd=2);
Because it is hard to see the finer points, a secondary graph is helpful.
plot(fedora_x, fedora_rtotal, type='l', col='red', ylab='sum of packet sizes in bytes', xlab='time', main='Plot of running totals in bytes (fedora vs openbsd)');
lines(obsd_x, obsd_rtotal, type='l', col='orange');
legend(x = "right", legend = c("Fedora", "OpenBSD"), col=c("red", "orange"), lwd=2);
Protocol analysis
Dplyr boys are laughing at me upon reading this utter nonsense.
# select data
fdf = sqldf("select Protocol, count(Protocol) as c from fedora group by Protocol order by Protocol ASC");
odf = sqldf("select Protocol, count(Protocol) as c from obsd group by Protocol order by Protocol ASC");
wdf = sqldf("select Protocol, count(Protocol) as c from win group by Protocol order by Protocol ASC");
# set row names
rownames(fdf) = fdf$Protocol;
rownames(wdf) = wdf$Protocol;
rownames(odf) = odf$Protocol;
protocols = c( "ARP", "DHCP", "DNS", "HTTP", "HTTP/XML", "IGMPv3", "LLMNR", "MDNS", "NBNS", "NTP", "OCSP", "QUIC", "SSDP", "TCP", "TLSv1.2", "TLSv1.3")
# insert missing rows
for(i in protocols){
if(is.na(fdf[i,2])){
fdf = rbind.data.frame(fdf, c(i, 0));
}
if(is.na(wdf[i,2])){
wdf = rbind.data.frame(wdf, c(i, 0));
}
if(is.na(odf[i,2])){
odf = rbind.data.frame(odf, c(i, 0));
}
}
# re set row names
rownames(fdf) = fdf$Protocol;
rownames(wdf) = wdf$Protocol;
rownames(odf) = odf$Protocol;
# alphabetic sort
fdf = fdf[order(row.names(fdf)), ];
wdf = wdf[order(row.names(wdf)), ];
odf = odf[order(row.names(odf)), ];
# merge into a single dataframe
all = data.frame(Windows=c(as.numeric(t(wdf$c))), Fedora=c(as.numeric(t(fdf$c))), OpenBSD=c(as.numeric(t(odf$c))));
# set row names again
rownames(all) = c(t(wdf$Protocol));
# plot
barplot(t(all), beside=TRUE, las=2, col=c("blue", "red", "orange"), ylab="number of packets", main="Frequency of packets by OS, grouped by protocol")
legend(x = "topleft", legend=colnames(all), col=c("blue", "red", "orange"), fill=c("Blue", "red", "orange"));
Domains Accessed
Fedora
Fedora workstation accessed a couple of domains. It is using the hypervisor for DHCP and DNS resolution. It is accessing an ntp server, fedoraproject.org (this is for detecting captive portals), and it is accessing github.com. github.com access is due to packagekit or gnome-software checking for updates.
sqldf("select Destination, count(Destination) as c from fedora group by Destination order by Destination ASC")
## Destination c
## 1 2.fedora.pool.ntp.org 132
## 2 Broadcast 4
## 3 fedora.local 513
## 4 fedoraproject.org 64
## 5 github.com 38
## 6 hypervisor 271
## 7 igmp.mcast.net 2
## 8 mdns.mcast.net 23
sqldf("select Source, count(Source) as c from fedora group by Source order by Source ASC")
## Source c
## 1 2.fedora.pool.ntp.org 131
## 2 fedora.local 534
## 3 fedoraproject.org 61
## 4 github.com 37
## 5 hypervisor 284
OpenBSD
OpenBSD does a lot less. It is using the hypervisor for DHCP but it is doing it’s own DNS resolution. It’s doing NTP. OpenNTPD has an interesting feature where it sends an https request to google.com and reads the timestamp from the HTTP header in order to prevent NTP poisoning.
sqldf("select Destination, count(Destination) as c from obsd group by Destination order by Destination ASC")
## Destination c
## 1 Broadcast 2
## 2 dns9.quad9.net 22
## 3 hypervisor.local 110
## 4 openbsd.local 740
## 5 pool.ntp.org 475
## 6 time.cloudflare.com 110
## 7 www.google.com 22
sqldf("select Source, count(Source) as c from obsd group by Source order by Source ASC")
## Source c
## 1 dns9.quad9.net 25
## 2 hypervisor.local 112
## 3 openbsd.local 741
## 4 pool.ntp.org 472
## 5 time.cloudflare.com 109
## 6 www.google.com 22
Windows
Windows is doing a lot and none of it seems to make any sense at first glance. It is doing the standard DHCP and DNS queries to the hypervisor but after that it’s not making much sense. Below is a table of domains the system accessed. It is mostly CDNs, advertisements, and windows account authentication (because God forbid we log into a system without sending credentials to the OS manufacturer).
Domain | What it does |
---|---|
.*msedge.net | Azure Front Door, a CDN |
akadns.net | Akami, a CDN |
dscg2.akamai.net | Akami, a CDN |
dscg.akamaiedge.net | Akami, a CDN |
trafficmanager.net | Azure load balancer |
bingadsedgeextension-prod.azurewebsites.net | probably advertisements, I cannot find much about it |
commerce.microsoft.com | endpoint for your “windows user login” since they did away with local accounts |
mdns.mcast.net | multicast, not a real server |
sb.scorecardresearch.com | a data aggregator and advertising company |
wpc.epsiloncdn.net | Edigo, A CDN |
wpc.phicdn.net | Edigo, a CDN |
cloudapp.azure.com | Azure cloud services |
sqldf("select Destination, count(Destination) as c from win group by Destination order by Destination ASC")
## Destination c
## 1 192.168.124.255 12
## 2 224.0.0.252 6
## 3 239.255.255.250 135
## 4 Broadcast 7
## 5 a-0003.a-msedge.net 91
## 6 a-0019.standard.a-msedge.net 37
## 7 a-9999.a-dc-msedge.net 18
## 8 a-9999.a-msedge.net 17
## 9 a1834.dscg2.akamai.net 22
## 10 a1847.dscd.akamai.net 11
## 11 a1858.dscd.akamai.net 12
## 12 a1943.g2.akamai.net 173
## 13 a1961.g2.akamai.net 5
## 14 a767.dspw65.akamai.net 7
## 15 arc-9999.arc-dc-msedge.net 16
## 16 arm-9999.arm-msedge.net 16
## 17 array601.prod.do.dsp.mp.microsoft.com 12
## 18 array603.prod.do.dsp.mp.microsoft.com 55
## 19 array614.prod.do.dsp.mp.microsoft.com 110
## 20 b-0008.b-msedge.net 16
## 21 c-msn-com-nsatc.trafficmanager.net 9
## 22 cs11.wpc.v0cdn.net 44
## 23 cs1404.wpc.epsiloncdn.net 27
## 24 cs9.wpc.v0cdn.net 21
## 25 dual-a-0001.a-msedge.net 31
## 26 dual-a-0036.a-msedge.net 97
## 27 dual-s-9999.dual-s-msedge.net 17
## 28 e11290.dspg.akamaiedge.net 76
## 29 e12358.d.akamaiedge.net 357
## 30 e16646.dscg.akamaiedge.net 38
## 31 e28578.d.akamaiedge.net 164
## 32 e86303.dscx.akamaiedge.net 306
## 33 e8652.dscx.akamaiedge.net 6
## 34 e9659.dspg.akamaiedge.net 15
## 35 fe2cr.update.msft.com.trafficmanager.net 89
## 36 fp2e7a.wpc.phicdn.net 5
## 37 g-msn-com-nsatc.trafficmanager.net 10
## 38 glb.cws.prod.dcat.dsp.trafficmanager.net 60
## 39 glb.sls.prod.dcat.dsp.trafficmanager.net 34
## 40 hypervisor.local 210
## 41 igmp.mcast.net 20
## 42 inference-orion-eastus.eastus.cloudapp.azure.com 14
## 43 iris-de-prod-azsc-v2-wus2-b.westus2.cloudapp.azure.com 74
## 44 mdns.mcast.net 33
## 45 onedscolprdcus03.centralus.cloudapp.azure.com 26
## 46 onedscolprdcus09.centralus.cloudapp.azure.com 57
## 47 onedscolprdcus10.centralus.cloudapp.azure.com 36
## 48 onedscolprdcus15.centralus.cloudapp.azure.com 39
## 49 onedscolprdcus16.centralus.cloudapp.azure.com 15
## 50 onedscolprdeus01.eastus.cloudapp.azure.com 14
## 51 onedscolprdeus04.eastus.cloudapp.azure.com 14
## 52 onedscolprdeus08.eastus.cloudapp.azure.com 20
## 53 onedscolprdeus10.eastus.cloudapp.azure.com 25
## 54 onedscolprdeus16.eastus.cloudapp.azure.com 15
## 55 onedscolprdjpe02.japaneast.cloudapp.azure.com 14
## 56 onedscolprdjpw01.japanwest.cloudapp.azure.com 15
## 57 onedscolprdjpw02.japanwest.cloudapp.azure.com 28
## 58 onedscolprdneu04.northeurope.cloudapp.azure.com 25
## 59 onedscolprduks05.uksouth.cloudapp.azure.com 33
## 60 onedscolprdweu06.westeurope.cloudapp.azure.com 15
## 61 onedscolprdwus00.westus.cloudapp.azure.com 28
## 62 onedscolprdwus09.westus.cloudapp.azure.com 63
## 63 s-0005.s-msedge.net 37
## 64 sb.scorecardresearch.com 9
## 65 settings-prod-eus2-2.eastus2.cloudapp.azure.com 12
## 66 settings-prod-scus-2.southcentralus.cloudapp.azure.com 24
## 67 settings-prod-uks-2.uksouth.cloudapp.azure.com 12
## 68 settings-prod-wus2-2.westus2.cloudapp.azure.com 12
## 69 ssl.bingadsedgeextension-prod.azurewebsites.net 11
## 70 us.configsvc1.live.com.akadns.net 15
## 71 us2.odcsm1.live.com.akadns.net 11
## 72 vmss-prod-eus.eastus.cloudapp.azure.com 25
## 73 vmss-prod-weu.westeurope.cloudapp.azure.com 19
## 74 vmss-prod-wus.westus.cloudapp.azure.com 26
## 75 waws-prod-usw3-011-3570.westus3.cloudapp.azure.com 9
## 76 wd-prod-cp-us-east-3-fe.eastus.cloudapp.azure.com 23
## 77 wd-prod-cp-us-west-2-fe.westus.cloudapp.azure.com 22
## 78 windows.local 3581
## 79 wns.notify.trafficmanager.net 56
## 80 wus2.frontdoor.licensing.commerce.microsoft.com 15
## 81 www.tm.v4.a.prd.aadg.akadns.net 11
## 82 www.tm.v4.a.prd.aadg.trafficmanager.net 13
sqldf("select Source, count(Source) as c from win group by Source order by Source ASC")
## Source c
## 1 40.83.247.108 8
## 2 a-0003.a-msedge.net 111
## 3 a-0019.standard.a-msedge.net 39
## 4 a-9999.a-dc-msedge.net 18
## 5 a-9999.a-msedge.net 15
## 6 a1834.dscg2.akamai.net 28
## 7 a1847.dscd.akamai.net 14
## 8 a1858.dscd.akamai.net 17
## 9 a1943.g2.akamai.net 456
## 10 a1961.g2.akamai.net 5
## 11 a767.dspw65.akamai.net 6
## 12 arc-9999.arc-dc-msedge.net 16
## 13 arm-9999.arm-msedge.net 15
## 14 array601.prod.do.dsp.mp.microsoft.com 9
## 15 array603.prod.do.dsp.mp.microsoft.com 42
## 16 array614.prod.do.dsp.mp.microsoft.com 80
## 17 b-0008.b-msedge.net 17
## 18 c-msn-com-nsatc.trafficmanager.net 9
## 19 cs11.wpc.v0cdn.net 60
## 20 cs1404.wpc.epsiloncdn.net 18
## 21 cs9.wpc.v0cdn.net 20
## 22 dual-a-0001.a-msedge.net 35
## 23 dual-a-0036.a-msedge.net 118
## 24 dual-s-9999.dual-s-msedge.net 15
## 25 e11290.dspg.akamaiedge.net 82
## 26 e12358.d.akamaiedge.net 479
## 27 e16646.dscg.akamaiedge.net 35
## 28 e28578.d.akamaiedge.net 222
## 29 e86303.dscx.akamaiedge.net 318
## 30 e8652.dscx.akamaiedge.net 4
## 31 e9659.dspg.akamaiedge.net 15
## 32 fe2cr.update.msft.com.trafficmanager.net 128
## 33 fp2e7a.wpc.phicdn.net 3
## 34 g-msn-com-nsatc.trafficmanager.net 7
## 35 glb.cws.prod.dcat.dsp.trafficmanager.net 70
## 36 glb.sls.prod.dcat.dsp.trafficmanager.net 31
## 37 hypervisor.local 212
## 38 inference-orion-eastus.eastus.cloudapp.azure.com 14
## 39 iris-de-prod-azsc-v2-wus2-b.westus2.cloudapp.azure.com 52
## 40 onedscolprdcus03.centralus.cloudapp.azure.com 29
## 41 onedscolprdcus09.centralus.cloudapp.azure.com 55
## 42 onedscolprdcus10.centralus.cloudapp.azure.com 42
## 43 onedscolprdcus15.centralus.cloudapp.azure.com 23
## 44 onedscolprdcus16.centralus.cloudapp.azure.com 15
## 45 onedscolprdeus01.eastus.cloudapp.azure.com 9
## 46 onedscolprdeus04.eastus.cloudapp.azure.com 13
## 47 onedscolprdeus08.eastus.cloudapp.azure.com 29
## 48 onedscolprdeus10.eastus.cloudapp.azure.com 17
## 49 onedscolprdeus16.eastus.cloudapp.azure.com 15
## 50 onedscolprdjpe02.japaneast.cloudapp.azure.com 11
## 51 onedscolprdjpw01.japanwest.cloudapp.azure.com 11
## 52 onedscolprdjpw02.japanwest.cloudapp.azure.com 21
## 53 onedscolprdneu04.northeurope.cloudapp.azure.com 26
## 54 onedscolprduks05.uksouth.cloudapp.azure.com 22
## 55 onedscolprdweu06.westeurope.cloudapp.azure.com 11
## 56 onedscolprdwus00.westus.cloudapp.azure.com 24
## 57 onedscolprdwus09.westus.cloudapp.azure.com 84
## 58 s-0005.s-msedge.net 43
## 59 sb.scorecardresearch.com 11
## 60 settings-prod-eus2-2.eastus2.cloudapp.azure.com 10
## 61 settings-prod-scus-2.southcentralus.cloudapp.azure.com 17
## 62 settings-prod-uks-2.uksouth.cloudapp.azure.com 10
## 63 settings-prod-wus2-2.westus2.cloudapp.azure.com 11
## 64 ssl.bingadsedgeextension-prod.azurewebsites.net 9
## 65 us.configsvc1.live.com.akadns.net 12
## 66 us2.odcsm1.live.com.akadns.net 9
## 67 vmss-prod-eus.eastus.cloudapp.azure.com 2
## 68 vmss-prod-weu.westeurope.cloudapp.azure.com 2
## 69 vmss-prod-wus.westus.cloudapp.azure.com 8
## 70 waws-prod-usw3-011-3570.westus3.cloudapp.azure.com 7
## 71 wd-prod-cp-us-east-3-fe.eastus.cloudapp.azure.com 21
## 72 wd-prod-cp-us-west-2-fe.westus.cloudapp.azure.com 22
## 73 windows.local 3379
## 74 wns.notify.trafficmanager.net 49
## 75 wus2.frontdoor.licensing.commerce.microsoft.com 15
## 76 www.tm.v4.a.prd.aadg.akadns.net 10
## 77 www.tm.v4.a.prd.aadg.trafficmanager.net 13
Conclusion
How much should an operating system really be doing automatically? NTP is a standard; modern networked operating systems need correct time for HTTPS certificates to work. Automatically checking for updates can be nice and in the case of Fedora it’s trivial to disable this functionality. The concerning part is when an operating system is loudly broadcasting to the entire world that the machine is online before proceeding to automatically download and upload data that is encrypted (invisible to the user) without any logical reason for doing so.