How do I discover a process that has made an interface promiscuous? - linux

On linux, I'd like to quickly tie a running process to a promiscuous interface it created. For instance, tcpdump will change an interface when it starts and ends, and I'd like to efficiently associate that process to the promiscuous interface while it's running.
For instance, I would want this method to detect rogue malware that is sniffing.
Normally I could ps -ef | grep tcpdump, but in the malware case I may not know the process doing the work.
Also, for bonus points... if the process is no longer running, how would you determine how an interface was made promiscuous? (assuming it's not in .history)

Kernel will printk() a message when an interface is put into promiscuous mode. That message should end up in the system logs (usually in /var/log), though most likely your intruder will be smart enough to censor logs and hide his/her/its trail. The only correct answer to this challenge, in my humble opinion, is to have a remote logging server where at least some of the system messages are redirected in addition to storing them to a local disk.
To get more information into logs you could turn on kernel auditing by adding audit=1 to kernel command line.
An interface can be in promiscuous mode without any process actively "keeping" it as such. Actually, you can just turn on promiscuous mode for an interface with ip link set <interface> promisc on. Try it on your loopback interface with ip link set lo promisc on, see what netstat -i produces on your terminal, then turn promiscuous mode again off with ip link set lo promisc off and check once again with netstat -i how flags for the loopback interface have changed.
To answer your first question: there is no way to know which process keeps an interface in promiscuous mode as there might be such a process in the first place. The kernel doesn't have detailed process information at the point of __dev_set_promiscuity():
if (dev->flags != old_flags) {
pr_info("device %s %s promiscuous mode\n",
dev->name,
dev->flags & IFF_PROMISC ? "entered" : "left");
if (audit_enabled) {
current_uid_gid(&uid, &gid);
audit_log(current->audit_context, GFP_ATOMIC,
AUDIT_ANOM_PROMISCUOUS,
"dev=%s prom=%d old_prom=%d auid=%u uid=%u gid=%u ses=%u",
dev->name, (dev->flags & IFF_PROMISC),
(old_flags & IFF_PROMISC),
from_kuid(&init_user_ns, audit_get_loginuid(current)),
from_kuid(&init_user_ns, uid),
from_kgid(&init_user_ns, gid),
audit_get_sessionid(current));
}
For details, see file net/core/dev.c in the Linux kernel source tree.

Related

Linux Kernel 3.3 not registering missed beacons with connected Access Point

I'm using linux kernel 3.3 (I cannot upgrade my kernel, sorry!) and am trying to use the wpa_cli utility to monitor the status of my WiFi connection. I'm using an Edimax WiFi dongle to connect to a wireless access point.
I expect to see something like this:
# wpa_cli status
Selected interface 'wlan0'
wpa_state=SCANNING
ip_address=XXX.XXX.XXX.XXX
address=XX:XX:XX:XX:XX:XX
Or the same thing but with wpa_state=COMPLETED, depending upon my connection status.
Parsing the this text output allows me to see if my wireless connection is active or scanning. However, I have noticed that after powering off my access point wpa_state=COMPLETED is still being returned. Using the command:
# iwlist wlan0 scanning
Forces a scan and wpa_state will occasionally be correct, but usually (99%) not.
Here is my /etc/wpa_supplicant.conf:
ctrl_interface=/var/run/wpa_supplicant
ap_scan=1
country=US
network={
ssid="myssid"
psk="mypsk"
key_mgmt=WPA-PSK
eap=
}
After some investigation, I believe something weird is happening causing the kernel to return a cached version of the AP list. I am using the RTL8192cu driver. I've already looked at this issue, and it is not the same as mine.
My belief is that the issue may be somewhere in the kernel. In the file net/mac80211/scan.c, at line 214 in function ieee80211_scan_rx, I see a bssid from the BSS of my AP appear (when AP has power) and get put via ieee80211_rx_bss_put (here). At this point, it is returned in scan results and wpa_supplicant causes the MLME layer in the kernel to authenticate and connect with that AP. However, after disconnecting AP power, I never see the MLME layer relinquish it's atomic_t hold on that BSS. This causes the BSS to never to unlinked in the function
cfg80211_bss_expire at the end of a scan (cfg80211_wext_giwscan), in file net/wireless/scan.c, line 205 (here).
Specifically, I would like to know why the atomic used to "hold" a BSS is not decremented on power removal from the AP - causing linux to miss sufficient beacons for a disconnect? Or, is there some configuration with wpa_supplicant I need to add to have the MLME kernel layer decrement it's hold on the BSS, or is this clearly a kernel bug?
I've already tried:
# wpa_cli bss_expire_age 10
# wpa_cli bss_expire_count 2
and have not resolved my issue.
So after a lot of digging, I found that the issue was because of the kernel's rtlwifi driver. To me, it looks like the rtl8192cu driver was suppose to be responsible for handling missed beacons, by calling the function ieee80211_beacon_loss, but that call is nowhere to be found. I removed support for IEEE80211_HW_BEACON_FILTER in the rtlwifi driver and the issue has been fixed.
This patch is essentially the same changes that I made, and the comments in this file are part of what led to me this answer.

Telnet: How to remove NULL (0x00) after every CR (0x0d) on send, using char mode (interactive mode)?

I am using my open source Serial-to-IP converter (Serial Network Interface, SNI) to communicate with headless Slackware server using ttyS0 console. SNI during connection sends back to Telnet command set ff fb 01 ff fb 03. This turns Telnet from Line mode to Char mode. But i notice that Telnet replaces (adds) my CR press (0x0d) to two chars 0x0d 0x00. The Slackware's TTY itself is immune to this, but some commands i run under it, at least cat and mcedit, are not. So i try to do the following:
Insert filter in my SNI so it just throw away NULLs at direction IP->Serial. It works, but it quite ugly, because no binary transfer will be allowed anymore.
Modify Telnet's source code to remove addind NULL to CR:
inetutils-1.9.4/telnet/telnet.c from line 2294:
case '\r':
if (!crlf)
{
NETADD ('\r'); <-- added
// NET2ADD ('\r', '\0'); <-- removed
}
else
{
NET2ADD ('\r', '\n');
}
bol = flushline = 1;
break;
It also work, so i ensure i am on the right way catching the problem.
But it is also ugly due to multiple reasons, include that it is quite not portable, and obligate me to have my own non-standard telnet binary.
So the question is: It is possible to command to Telnet not to modify my CRs? (looking at this source code piece, it is not possible at all with original code, but i am sure i miss something, and this should be possible without modify source code). Note: Replace 0x0d to 0x0d, 0x0a (this is present in code) will not work with Linux TTY: it interprets this as two CRs.
And sub-question is: Where is 0x0d+0x00 used at all? I do not know any hardware device, teletype machine, etc., and any TTY, where NULL after CR used, at all. Thanks.
So i take some investigation to see how this should be solved correctly, in terms of not to abuse the software, and to find the correct tools, or clearly show there are no such tools currently.
First of all, i show why my setup is exactly as it is, and why it uses (or not uses) standard tools.
My goal is very common and essential to Linux world (as i think before). Because Linux is network operating system, Linux box should be fully configurable via network (so can/should be fully useful when headless, i.e. without display monitor). But at time when Lilo/Grub starts, there is no network. Only serial ports are able at this time (and Lilo/Grub supports it). Why it is important to remote control at this time? Just because you can (remotely) compile new custom kernel for your Slackware box, and want to test it, adding as 2nd option in Lilo list, and want to return to original kernel even when remote machine stuck when booting, so no way to remotely edit/agjust Lilo options.
But serial console is really much more powerful tool for Linux machine.
It shows boot messages and shut down messages which impossible to see via ssh, due to network is not initialized at these moments. (And remember, we do not have display).
It lets you to (suddenly or intentionally) drop all network interfaces without a fear to lost your machine, when it is many miles from you.
Note: Serial console will not work out-of-box, but can be configured in quite well known standard ways, and described in many places. Example is http://docs.slackware.com/howtos:general_admin:serial_console
Note: There is problem that serial port should be BIOS-recognized, i.e., fully onboard. USB and PCIE devices will never work at stage when Lilo/Grub boots. Fortunately there is a good news. Hardware serial ports now (slowly) return to motherboards. I test new modern Asus J1900I-C for my server, it have two rs232 ports, and it all work fine.
To use serial console benefits remotely, some sort of SNI, Serial Network Interface, should be used (and it is the only way, AFAIK). SNI typically contains (simplest possible) TCP listening server, and raw IP-to-serial duplex translator. I start study and using SNIs when Lantronix X-Port was invented. It was in 2006, and was working fine with Slackware box. (I can't remember if there was \r\0 problems or not with XPort, but let's continue). XPort was too expensive, and was replaced with my own open source SNI immediately when Wiznet W5100 was issued. (Really, there is other, essential problem, why i need to replace Lantronix. It can't press Reset or Power buttons on motherboard, while my device can, and now server is absolutely under full remote control even after kernel panic; but it is offtopic here). Also nowadays there are many cheap no-named SNIs at online shops; i do not test these.
All these times i was using telnet to connect to SNI. The main reason was that XPort docs have examples of that. And, most times it working; i can't say that \r\0 problem stops my work. Most times it is not noticeable at all (say, mc commander is resistent to NULL 's). But mcedit fear the NULLs. And recently i start to catch the problem, so this question arrives as an result.
(now please re-read from begin of thread).
And now i try to answer to my own question. All these times i was misuse the software. Telnet was not written for human communication; instead, Telnet (suddenly) use Telnet protocol, not Raw protocol; and \r\0s are probably part of protocol. (probably, because RFC says nothing about requirement of NULLs anywhere).
While Telnet and Raw protocols may looks quite close, they are not match, so sometimes should work but sometimes not.
Using bruteforce and recompiling binary, i show that Telnet can be very easily turned to Raw mode; but it is non-standard software after that, and there is no chance that it can be pushed to worldwide repos.
So i search for Raw utilites.
netcat and ncat are not have Char mode, only Line mode, so only pure console possible, no ANSI colors, mc, passwords, etc. Putty is too complex and uses GUI. And... No more utilites i found! This was quite strange and annoying...
Then i try to use initially character-based terminals, minicom and gtkterm. They are both do not allow feed ip:port structure istead of ttyS* name. But there is data translators exist, i try socat. It connects to SNI server and creates virtual serial port; then character terminal software connects to that port.
And that, finally, work. Whoa.
But very many disadvantages in this chain; complex, hard to remember commands, can't be written in one line; when SNI drops TCP connection, it is impossible to see/catch that; a LOT of garbage issued by socat into virtual port at connection time (457 packets i count!). Here are the commands for brave people who may find my work useful.
sudo socat pty,link=/dev/ttyMYPORT,raw tcp:10.1.1.11:10001 &
then
sudo chmod a+rw /dev/ttyMYPORT; gtkterm -p /dev/ttyMYPORT
or
sudo chmod a+rw /dev/ttyMYPORT; minicom -o --color=on -D /dev/ttyMYPORT
And conclusion, i do not found any simple software nowadays, that can be directly used to communicate in human raw character mode with serial port via network bridge. (Please suggest something). Thanks.
I believe the solution you are looking for is a few lines higher:
if (!crlf)
If we set crlf = true, then we would get \r\n instead of \r\0. That's probably going to work for cat and friends.
Looking through the telnet source, it appears crlf is some sort of "toggle" option. Looking an man telnet and a bit of Googling, it appears you can run something like this:
$ telnet
telnet> toggle crlf
...and you'll get \r\n sent from then on.

What is the difference between NETLINK_FIREWALL and NETLINK_NETFILTER?

Both of the Netlink protocols NETLINK_FIREWALL (and NETLINK_IP6_FW) and NETLINK_NETFILTER are used to manupilate the Linux firewall.
So, is there a diffrence? If yes, which Netlink protocol serves which purpose?
A quick grep through the code shows that NETLINK_FIREWALL only occurs twice in the kernel:
include/uapi/linux/netlink.h
11:#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */
security/selinux/hooks.c
1184: case NETLINK_FIREWALL:
1185: return SECCLASS_NETLINK_FIREWALL_SOCKET;
So, it's defined and the comment claims that it's unused, and it's only mentioned once, in type conversion code for selinux. There's never a call to netlink_kernel_create(), so NETLINK_FIREWALL is never hooked up. It won't do anything.
NETLINK_NETFILTER does have a netlink_kernel_create() call associated with it, so that's the interface you want to look at.
It's been a while, but I once implemented (partial) code for configuratin netfilter rules and I remember doing that through a setsockopt() call, rather than through netlink sockets. I'm not sure what NETLINK_NETFILTER actually does.
A quick look through git log seems to suggest that NETLINK_NETFILTER is used to interface with thinks like connection tracking, not actually configuring firewall rules (which the iptables userspace command does).
If you actually want to create firewall rules (i.e. do what iptables does) you should be looking at libiptc (which is part of the iptables source tree). The interface for configuring these rules is complicated and undocumented.

What is the purpose of net_device.uc_promisc field?

why struct net_device has a field uc_promisc? How this field is used?
Thank you all!
When a device that doesn't support unicast filtering has to listen to several unicast addresses, it is put on promiscous mode, according to dev->uc_count and dev->uc_promisc. Check the __dev_set_rx_mode() function.
Many devices implement ndo_set_rx_mode(), and set their unicast (and multicast) filters via ndo_set_rx_mode(). For devices that don't implement that, Linux sets the device to promiscuous mode, and keeps track of that fact with dev->uc_promisc.
So there are several flags for promiscuous mode:
dev->flags & IFF_PROMISC means the device is in promiscuous mode.
dev->gflags & IFF_PROMISC means the user has requested promiscuous mode.
dev->uc_promisc means promiscuous mode has been enabled (actually, its reference count has been incremented) due to the need to listen to additional unicast address in a device that doesn't implement ndo_set_rx_mode().
It sounds like it could be a way of enabling (or tracking the enabled/disabled status of) promiscuous mode on the device.

Controlling a USB power supply (on/off) with Linux

Is it possible to turn on/off power supplies from USB manually with Linux?
There's this external USB cooling fan (the kind you use to cool yourself off, not the PC), and it would be nice to be able to control it from the terminal, because I want to position the fan somewhere far away.
I suppose this could also be useful for a variety of other things as well, because there's a lot of USB toys out there. Maybe air purifiers, etc. (I heard they don't really work though).
According to the docs, there were several changes to the USB power management from kernels 2.6.32, which seem to settle in 2.6.38. Now you'll need to wait for the device to become idle, which is governed by the particular device driver. The driver needs to support it, otherwise the device will never reach this state. Unluckily, now the user has no chance to force this. However, if you're lucky and your device can become idle, then to turn this off you need to:
echo "0" > "/sys/bus/usb/devices/usbX/power/autosuspend"
echo "auto" > "/sys/bus/usb/devices/usbX/power/level"
or, for kernels around 2.6.38 and above:
echo "0" > "/sys/bus/usb/devices/usbX/power/autosuspend_delay_ms"
echo "auto" > "/sys/bus/usb/devices/usbX/power/control"
This literally means, go suspend at the moment the device becomes idle.
So unless your fan is something "intelligent" that can be seen as a device and controlled by a driver, you probably won't have much luck on current kernels.
Note. The information in this answer is relevant for the older kernels (up to 2.6.32). See tlwhitec's answer for the information on the newer kernels.
# disable external wake-up; do this only once
echo disabled > /sys/bus/usb/devices/usb1/power/wakeup
echo on > /sys/bus/usb/devices/usb1/power/level # turn on
echo suspend > /sys/bus/usb/devices/usb1/power/level # turn off
(You may need to change usb1 to usb n)
Source: Documentation/usb/power-management.txt.gz
PowerTOP from Intel allows you to toggle devices such as usb peripherals in real-time. These are called 'tunables'.
sudo apt install powertop
sudo powertop
Tab over to 'tunables'.
Scroll down to your device.
Hit enter to toggle power saving mode (Good/Bad)
Note that Bad means the device is always on. Toggling to Good will turn off the device after the preset inactive saving time (default is 2000ms).
See the PowerTOP docs for details on how to make these changes permanent.It generates the config scripts for you (pretty much as described by other posters on this thread).
NOTE: These scripts do not affect USB pin power (which is always on).
These only send the driver protocol to activate and deactivate a device.
If you want to control pin power, you could use either a supported smart USB hub, or better yet a microcontroller.
I have found these solutions that at least work for properly configured Terminus FE 1.1 USB hub chip:
1.To turn off power on all USB ports of a hub, you may unbind the hub from kernel using:
echo "1-4.4.4" > /sys/bus/usb/drivers/usb/unbind
to turn power back on - you may bind it back using
echo "1-4.4.4" > /sys/bus/usb/drivers/usb/bind
2.Switching power at each port individually is trickier: I was able to use hubpower to control each port - but it comes with a downside: hubpower first disconnects the usbdevfs wich causes all of the USB devices to disconect from system, at least on ubuntu:
usb_ioctl.ioctl_code = USBDEVFS_DISCONNECT;
rc = ioctl(fd, USBDEVFS_IOCTL, &usb_ioctl);
With this ioctl disabled I was able to switch off individual port power without detaching all devices - but the power goes back on immediately (probably due to kernel seeing an uninitialized device) which causes USB device just to do a "cold restart" which is what I generally wanted to do. My patched hubpower is here
You could use my tool uhubctl to control USB power per port for compatible USB hubs.
I wanted to do this, and with my USB hardware I couldn't. I wrote a hacky way how to do it here:
http://pintant.cat/2012/05/12/power-off-usb-device/ .
In a short way: I used a USB relay to open/close the VCC of another USB cable...
echo '2-1' |sudo tee /sys/bus/usb/drivers/usb/unbind
works for ubuntu
The reason why folks post questions such as this is due to the dreaded- indeed "EVIL"- USB Auto-Suspend "feature".
Auto suspend winds-down the power to an "idle" USB device and unless the device's driver supports this feature correctly, the device can become uncontactable. So powering a USB port on/off is a symptom of the problem, not the problem in itself.
I'll show you how to GLOBALLY disable auto-suspend, negating the need to manually toggle the USB ports on & off:
Short Answer:
You do NOT need to edit "autosuspend_delay_ms" individually: USB autosuspend can be disabled globally and PERSISTENTLY using the following commands:
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/&usbcore.autosuspend=-1 /' /etc/default/grub
update-grub
systemctl reboot
An Ubuntu 18.04 screen-grab follows at the end of the "Long Answer" illustrating how my results were achieved.
Long Answer:
It's true that the USB Power Management Kernel Documentation states autosuspend is to be deprecated and in in its' place "autosuspend_delay_ms" used to disable USB autosuspend:
"In 2.6.38 the "autosuspend" file will be deprecated
and replaced by the "autosuspend_delay_ms" file."
HOWEVER my testing reveals that setting usbcore.autosuspend=-1 in /etc/default/grub as below can be used as a GLOBAL toggle for USB autosuspend functionality- you do NOT need to edit individual "autosuspend_delay_ms" files.
The same document linked above states a value of "0" is ENABLED and a negative value is DISABLED:
power/autosuspend_delay_ms
<snip> 0 means to autosuspend
as soon as the device becomes idle, and negative
values mean never to autosuspend. You can write a
number to the file to change the autosuspend
idle-delay time.
In the annotated Ubuntu 18.04 screen-grab below illustrating how my results were achieved (and reproducible), please remark the default is "0" (enabled) in autosuspend_delay_ms.
Then note that after ONLY setting usbcore.autosuspend=-1 in Grub, these values are now negative (disabled) after reboot. This will save me the bother of editing individual values and can now script disabling USB autosuspend.
Hope this makes disabling USB autosuspend a little easier and more scriptable-
I had a problem when connecting my android phone, I couldn't charge my phone because the power switch on and then off ...
PowerTop let me find this setting and was useful to fix the issue ( auto value was causing issue):
echo 'on' | sudo tee /sys/bus/usb/devices/1-1/power/control
USB 5v power is always on (even when the computer is turned off, on some computers and on some ports.) You will probably need to program an Arduino with some sort of switch, and control it via Serial library from USB plugged in to the computer.
In other words, a combination of this switch tutorial and this tutorial on communicating via Serial libary to Arduino plugged in via USB.
So far I came to the conclusion that you cannot control the power of a USB port. The 5V USB is always provided, and it's up to the device to use it or not. You can check this with a 5V fan or light.
I've tried various methods (disconnect/reconnect/bind/unbind/reset signal). Best so far are bind/unbind as it forces a cold restart of the device (but no power cycle).
I came up with a solution to reset USB devices, ports and controllers in a python script, which supports all of the above methods.
You can find the script at my Github page
Usage:
usb_reset.py -d 8086:1001 --reset-hub
The script uses among others the following solution to reset USB hubs/controllers:
Unbindind a USB port / controller works best via:
echo "myhub" > "/sys/bus/usb/drivers/usb/unbind"
echo "myhub" > "/sys/bus/usb/drivers/usb/bind"
Where myhub is found in /sys/bus/usb/devices/*
Or litteral controllers:
echo "mycontroller" > "/sys/bus/pci/drivers/unbind"
echo "mycontroller" > "/sys/bus/pci/drivers/bind"
Where mycontroller is found in /sys/bus/pci/drivers/[uoex]hci_hcd/*:*

Resources