I am compiling a kernel for a router. I know a way to enable IP forwarding in an existing Linux system. At compile time, CONFIG_IP_FORWARD is said to do the same task.

I am configuring version 3.12.14 of the vanilla kernel using the GTK-based kernel configuration tool (gconfig). However, I can't see this option anywhere. Is there an alternate configuration option in recent kernels or am I missing something?

  • Simple question: why? – user55518 Apr 9 '14 at 20:36
  • Simple answer: I need it for a project, A kernel, that is installed on a machine, does a lot other things than plain forwarding that I am configuring in my kernel. Forwarding seems to be a pain. Very little documentation is available for a lot of linux kernel features. – JuliandotNut Apr 9 '14 at 20:44
  • I meant why do you need it compiled into the kernel? To forward packets forwarding is not enough, you need also some iptables-rules. – user55518 Apr 9 '14 at 21:12
  • 2
    iptables has nothing to do with that. All you need are appropriate routing table entries. – countermode Apr 9 '14 at 22:18
  • iptables has to do with ip_forward setting, perhaps here is meant device/forwarding. However it is still not clear why it needs to be compiled into kernel. Is there a need to run a standalone kernel w/o any file system? – user55518 Apr 9 '14 at 22:48

The Linux kernel source hasn't had the CONFIG_IP_FORWARDING option since the 2.0.x kernel series. As far as I know, there is no compile time option anymore to enable IP forwarding by default for the built kernel.

Since the 2.1.x series, the correct way to enable IP forwarding for IPv4 has been with the net.ipv4.ip_forward sysctl option.

Add the following line to sysctl.conf (or a file in /etc/sysctl.d):

net.ipv4.ip_forward = 1

Then, have sysctl reload the configuration:

sysctl -p /etc/sysctl.conf

That said, if for some reason you need to configure the kernel so that setting the sysctl option (or the /proc equivalent) at boot time isn't needed, you could change the default value for the sysctl option directly in the kernel source tree*.

The sysctl table entry for /proc/sys/net/ipv4/ip_forward is initialized from a static structure defined in net/ipv4/devinet.c:

static struct ctl_table ctl_forward_entry[] = {
                .procname       = "ip_forward",
                .data           = &ipv4_devconf.data[
                                        IPV4_DEVCONF_FORWARDING - 1],
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = devinet_sysctl_forward,
                .extra1         = &ipv4_devconf,
                .extra2         = &init_net,
        { },

The data field is initialized to point to a entry in the integer array data, which is a field in the static ipv4_devconf structure. The entry is identified by the IPV4_DEVCONF_FORWARDING enumerated value defined in include/uapi/linux/ip.h. The data array contained in the structure is only partially initialized, omitting the IPV4_DEVCONF_FORWARDING entry. Since the structure has static storage, all integral type members are initialized to zero. Hence, to set the data field for the ip_forward sysctl table entry, and the recorded default value, we need to initialize ipv4_devconf.data[IPV4_DEVCONF_FORWARD - 1] and the corresponding field in the ipv4_devconf_dflt structure to 1. This can be achieved with the following patch:

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index bdbf68b..91fe073 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -69,6 +69,7 @@

 static struct ipv4_devconf ipv4_devconf = {
        .data = {
+               [IPV4_DEVCONF_FORWARDING - 1] = 1,
                [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1,
                [IPV4_DEVCONF_SEND_REDIRECTS - 1] = 1,
                [IPV4_DEVCONF_SECURE_REDIRECTS - 1] = 1,
@@ -80,6 +81,7 @@ static struct ipv4_devconf ipv4_devconf = {

 static struct ipv4_devconf ipv4_devconf_dflt = {
        .data = {
+               [IPV4_DEVCONF_FORWARDING - 1] = 1,
                [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1,
                [IPV4_DEVCONF_SEND_REDIRECTS - 1] = 1,
                [IPV4_DEVCONF_SECURE_REDIRECTS - 1] = 1,

* Disclaimer: I'm no expert in Linux networking internals, so it's entirely possible that the method described here misses some initializations normally performed by the devinet_sysctl_forward() when forwarding is normally enabled via sysctl, so proceed with care. The above patch seems to work against kernel version 3.14 to the extent that /proc/sys/net/ipv4/ip_forward indeed indicates forwarding to be enabled by default, without configuration via sysctl. As far as I see, 3.12.14 does not seem to differ with regards to the sysctl entry initialization. I included the patch in the hope that it will be useful, but WITHOUT ANY WARRANTY.

| improve this answer | |
  • So it changed since 2.1.x.... OK thanks :) And yes I know sysctl.conf method already. – JuliandotNut Apr 10 '14 at 10:16
  • That doesn't answer the question: how to configure the kernel so that running sysctl net.ipv4.ip_forward=1 at boot time (or the /proc equivalent) isn't needed. – Gilles 'SO- stop being evil' Apr 11 '14 at 0:29
  • @Gilles Fair enough, although it seemed to me that "there is no such compile time option anymore" would be an acceptable answer. As far as I know, the only way to achieve this would be to modify the kernel source. I updated to answer with information about how the particular sysctl option is initialized, if someone would want to IP forwarding enabled by default. – Thomas Nyman Apr 11 '14 at 10:50

I don't know of any solution for enabling it statically (and in at least recent kernels there's no CONFIG_IP_FORWARD - just greped the source).

From a security perspective this doesn't seem to be a good idea anyways, since in many cases you might to configure some other things before enabling forwarding (filtering rules, QoS rules, [more exact] routing rules, for example).

| improve this answer | |
  • I know there is no CONFIG_IP_FORWARD now, that's what I said. Question is if this feature is enabled by some other parameter at compile time or it is not possible at all now. – JuliandotNut Apr 9 '14 at 20:51
  • 1
    What I wanted to say was: As far as I can see, there's not. – Andreas Wiese Apr 9 '14 at 21:15

IP forwarding is a core functionality of the network code in Linux. That's why there is no configuration variable for it.

| improve this answer | |
  • There used to be a variable for that, anyway, probably a start-up script has to be written instead. Do you know of a way/interface/API to insert routing table entries? Not static, but dynamic ones. – JuliandotNut Apr 10 '14 at 0:19
  • "ip" from the iproute2 package does what you need, i.e. "ip -6 route add 2001:db8:0:cafe::/64 dev enp1s2" etc. policyrouting.org/iproute2.doc.html has a very readable guide to "ip". – countermode Apr 10 '14 at 5:43
  • 1
    You didn't get the question. Of course it's core functionality, but it's disabled after startup, so your computer does not act as a router if not excplicitly told to. – Andreas Wiese Apr 10 '14 at 8:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.