šŸ“œ ā¬†ļø ā¬‡ļø

Distribution of the Internet from a 3G modem to a local network in Linux

This article is a continuation of the Wireless Access Point article using Linux . Here I will describe what needs to be done in order to distribute the Internet from a 3G modem according to the Wi-Fi network already created according to the instructions from the previous topic.

1) First of all, teach Linux to work with a modem
2) Create a NAT to distribute the Internet
3) Push the whole thing into autoload
So, bash, wvdial and iptables under your arm - and let's go!

USB 3G modem connection


It also happens that in some countries there are 3G Internet providers that do not provide settings for connecting using Linux, which, in general, is understandable - the ā€œpopularityā€ of both the provider and Linux makes itself felt. Not all configs are still on sites, especially for individual programs. So, in Latvia, where I live. There are two providers - LMT and Bite. Both of them provide wireless Internet via Huawei modems, locked, of course, on them, but that's not the point. Well, it is necessary to provide the Internet everywhere where there is 3G, using a modem and a server. What to do?

First of all, plug the modem into the laptop. USB modems are defined in Linux as devices under the address / dev / ttyUSB *, where * is the device sequence number, usually the address looks like / dev / ttyUSB0.
root@localhost:/# ls /dev/ttyUSB* ls: cannot access /dev/ttyUSB*: No such file or directory 

Oh. Something he is not determined. And the problem is this (cleared a thousand times already): a modem is a ā€œtwo in oneā€ device. Why? It combines both the modem itself and the built-in drive with the modem drivers for Windows in one flash drive (I’m not talking about the card reader). In Linux, the disk mode is switched on by default, not the modem In order to enable the modem mode as well, you need to install the usb-modeswitch package. After that, you need to restart udev (service udev restart) and reconnect the modem, wait 10 seconds and again execute the command to display the list of modem devices:
 root@localhost:/# ls /dev/ttyUSB* /dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 

When the conclusion is like this, everything is fine and you can move on. We have three devices. We need only one thing - at number 0, the other 2 we do not use - they are not for our purposes. As far as I know, one of them, most likely, is used for sending SMS, and the second - for viewing the signal level of the network and other things.
')
Now it's up to the program that connects us. I will use the wvdial program, in addition to it, I need to install the ppp package if it is not already installed.
 apt-get install ppp wvdial 
Many people advise using the wvdialconf program to configure the connection, but in this case it will not help us. After installation, we need to edit the /etc/wvdial.conf file. We erase from it all the content, then understand in the file format. I will provide working configs for LMT provider with OKarte Internets datorā tariff and Huawei E173 and Bite modem with unknown tariff and Huawei E1550 modem.

 [Dialer lmt] Init1 = AT Init2 = AT&FE0V1X1&D2&C1S0=0 #Init3 = AT+CPIN="1219" Init4 = AT+CGDCONT=1,"IP","internet.lmt.lv" Phone = *99# ISDN = 0 Username = { } Password = { } Ask Password = 0 Modem = /dev/ttyUSB0 PPPD Options = noauth crtcts multilink usepeerdns lock defaultroute nobsdcomp nodeflate refuse-pap refuse-eap refuse-chap refuse-mschap +chap Idle Seconds = 3000 Modem Type = USB Modem Compuserve = 0 Auto DNS = 1 Dial Command = ATD Stupid Mode = 1 FlowControl = NOFLOW [Dialer bite] Init1 = AT Init2 = AT&FE0V1X1&D2&C1S0=0 #Init3 = AT+CPIN="1219" Init4 = AT+CGDCONT=1,"IP","internet" Phone = *99# ISDN = 0 Username = { } Password = { } Ask Password = 0 Modem = /dev/ttyUSB0 PPPD Options = noauth crtcts multilink usepeerdns lock defaultroute nobsdcomp nodeflate refuse-pap refuse-eap refuse-chap refuse-mschap +chap Idle Seconds = 3000 Modem Type = USB Modem Compuserve = 0 Auto DNS = 1 Dial Command = ATD Stupid Mode = 1 FlowControl = NOFLOW 


In short - the file is divided into sections. Each section is responsible for one combination modem provider. The beginning of the section is indicated by the label [Dialer xxx], where xxx is the name of the label, by which we will indicate which settings are needed for the connection. If we need the LMT settings, we will type the wvdial lmt command, and the settings from the [Dialer lmt] section will be used - the gist is clear. From these settings, we need to pay attention to the following:

 InitX = AT-BLABLABLA 

- AT commands after InitX - those commands that wvdial sends to the modem before raising the connection.

 #Init3 = AT+CPIN="1219" 

- This setting, if you remove # at the beginning, will send a pin code command to the modem. To be honest, it is advisable to turn it off - this command for some unknown reason did not work correctly for me. It is easier to simply connect the modem once to a Windows computer and disable the input of a PIN code when connecting using the program that came with the modem.

 Init4 = AT+CGDCONT=1,"IP","internet" 

- This is the address of the APN that the provider provides. It is necessary to pay attention to the last two parts separated by quotes. The first one - IP - indicates the IP address for the connection, if the provider settings imply that the APN IP address is used. If the letter address of the type ā€œinternetā€ or ā€œinternet.lmt.lvā€ is used, in the first part you need to leave ā€œIPā€, and in the second part you must enter the letter address, as in the example.

 Phone = *99# 

- Well, everything is standard here - almost all providers use this phone number, and in most cases you will not need to change it.

 Username = { } Password = { } 

Username and password to connect to the Internet. If they need to be left empty, leave brackets like {} there. If not, just put the name and password there, without brackets.

 Modem = /dev/ttyUSB0 

The name of the device that we need to use. In 99% of cases it will be exactly like that.

The remaining parameters may be different in the case of other modems, but for the above two combinations the modem provider everything works without problems.

Once again I will talk about how to correctly start the connection manually. One command is enough - wvdial xxx, where xxx is the name of the provider from the configuration file (for me, this is either lmt or bite.) However, when you start wvdial, it ā€œtakes itselfā€ the entire console, preventing it from running anything else. In addition - if you run wvdial in the SSH window and immediately break the session, then wvdial will end. It is necessary either to keep the session open all the time, or to use screen, which in this case solves two problems at once rather effectively - which is what I advise.
What is the ideal need? Also learn how to simply and easily run these programs. There are some nuances in my use of the described scheme:

1) The connection must be manually started each time.
- It is enough to change the system configuration files a little, namely the same / etc / network / interfaces:
 auto ppp0 iface ppp0 inet wvdial provider lmt #  ppp0  #    wvdial   lmt. ,   . 

For me, this method is not suitable - it is designed for the fact that the provider does not change, but it is highly likely that it will be needed by someone else. And it doesn't really work very well, in my experience, it's better to configure udev. For myself, I did not find the appropriate solutions - for this I would have to determine the identity of the inserted SIM card to one or another provider, and the solution using this becomes very difficult.
Well, if you still need to be constantly connected, even if something is buggy and the modem is disconnected from the network? Well, then the following script will help. It looks to see if wvdial is in the process list, and if not, it does ifup ppp0, which, in conjunction with the above settings in interfaces, should call wvdial again:
Shove yourself in cron
 #!/bin/bash # (c)2009 John de Graaff, rewritten by CRImier # This script checks if wvdial is running. # If it's not, it brings ppp0 up and down. # It is assumed that ifup ppp0 starts wvdial if test "$(pidof wvdial)" != "" ; then exit 0 else logger "wvdial not running. Better restart ppp0." /sbin/ifdown ppp0 sleep 2 /sbin/ifup ppp0 logger "ppp0 restarted." exit 0 


2) When you turn on the laptop, if the modem was connected at boot time, sometimes there are hangs, which are expressed in the following - when you try to connect, using wvdial, the lines like
 --> Cannot open /dev/ttyUSB0: Device or resource busy 

and can not connect. It is treated at one time simply - you just need to remove and plug in the modem, and then start the connection manually, but you understand that in the absence of physical access to the computer, this task becomes even more difficult.
- So far I can not provide a normal solution, because I myself have not yet engaged in this. It is assumed that this is due to the fact that the usb-modeswitch program does not work correctly if a modem is inserted into the computer at system startup. Apparently, you need to rummage with udev or specify any special parameters for usb-modeswitch.

3) In a bad reception environment, the connection is often chopped off.
- It's pretty simple. The fact is that YUSB ports have a limitation on the current given, above which, as I recall, the port is chopped off. Apparently, in the conditions of bad reception of a network signal, the modem tries to increase the power of the receiver and transmitter, and it happens that the modem starts to consume more current than the port can withstand - the port is turned off, the modem is turned off, the connection is cut off for good. I can only advise, for example, simply take an external-powered USB hub or buy a separate power adapter for the modem and solder it to the cable.

4) The ability to change the port on which you want to access the device.
As I have already mentioned, usually one device is used during configuration - / dev / ttyUSB0. But, as noted by freuser , there are situations where the port is changing. For example:When debugging a non-working connection, you cannot forget about this possibility. If, for example. When wvdial starts, pppd does not start, then this is a reason to think - is the port itself working and is this the port? Then you have to experiment with the numbers in the config until the modem finally connects.

After the Internet has appeared on our server, it remains only to configure the distribution of the Internet from a modem via a Wi-Fi network.

NAT


If the computer has two network interfaces, this does not mean that out of the box you can safely distribute the Internet from one to another. However - not everything is so difficult, most often only a couple of settings are required. Of course, these settings are difficult to remember, without delving into the essence of each line, but this article is for that! I found the best-fit script for this situation, I can’t help but give a link to it, because the script found on it is the shortest and clearest of those I’ve met - the rest manage to stretch a couple of iptables rules into several pages ... First of all, I’ll see what needs to be changed in it for my needs:

Found script
Spoiler:
 #!/bin/sh PATH=/usr/sbin:/sbin:/bin:/usr/bin # # delete all existing rules. # iptables -F iptables -t nat -F iptables -t mangle -F iptables -X # Always accept loopback traffic iptables -A INPUT -i lo -j ACCEPT # Allow established connections, and those not coming from the outside iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -m state --state NEW -i ! eth1 -j ACCEPT iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow outgoing connections from the LAN side. iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT # Masquerade. iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE # Don't forward from the outside to the inside. iptables -A FORWARD -i eth1 -o eth1 -j REJECT # Enable routing. echo 1 > /proc/sys/net/ipv4/ip_forward 

Hmm hmm This script is already old - iptables swears at one of the commands and does not want to execute, and the way in which the article tries to put the script into the autoload also does not always work in my practice. Moreover, there is a problem - this script is great for a situation when nothing is going to change. If it were, I would put iptables-persistent and end up with an article. But sometimes I’m going to get the Internet through the ppp0 interface, sometimes through eth0, and sometimes through wlan1, and I want to change the interface with a single console command. So, eth1 in the example is the external interface, and eth0 is the internal one. Replace them with variables so that, if necessary, you can change one line and not edit the entire text. I also want to save the last selected external interface when the computer is restarted. What then? Need to change everything!
Tasks:
  1. Accept the first command line argument as the name of the external interface, verifying the authenticity of the name using the ifconfig command;
  2. Add the preservation of the selected interface to some file in / etc and make the key to select the last interface, or better, if there is no interface name as an argument.
  3. To push it all beautifully in autoload and in $ PATH.

What happened in the end?

 #!/bin/bash #NAT script from www.debian-administration.org, modified by CRImier # Exit status 0 if operation is correct # Exit status 1 if trying to use last interface used when running for the first time # Exit status 2 if interface doesn't exist EIF='' IIF='wlan0' PATH=/usr/sbin:/sbin:/bin:/usr/bin LOGFILE=/etc/nat-if.conf touch $LOGFILE # #Checking command-line arguments and setting $EIF variable according to them # if [[ $1 == "" ]] #If there's no arguments, just use previous settings. then EIF=`cat $LOGFILE` if [[ $EIF == "" ]] #Just check for an empty file! then echo "Please, specify interface name for first usage using 'firewall interface', eg 'firewall eth0'" exit 1 fi elif [ $1 == "help" ] #Output help message then echo "NAT script" echo "(c) www.debian-administration.org, modified by CRImier" echo "Usage: 'firewall interface', 'firewall info' or simply 'firewall' to use last interface firewall was set on." echo "Argument is external interface name, internal interface name is hard-coded in the script" exit 0 elif [ $1 == "info" ] #Print interface firewall is set on then cat $LOGFILE exit 0 else ifconfig $1 &>/dev/null if [ $? == 0 ] then #Interface name must be correct as ifconfig gives 0 exit code EIF=$1 echo $EIF > $LOGFILE else echo "Incorrect interface name" exit 2 fi fi # #$EIF is set correctly, let's apply the rules: # iptables -F iptables -t nat -F iptables -t mangle -F iptables -X iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -i $EIF -o $IIF -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -i $IIF -o $EIF -j ACCEPT iptables -t nat -A POSTROUTING -o $EIF -j MASQUERADE iptables -A FORWARD -i $EIF -o $IIF -j REJECT echo 1 > /proc/sys/net/ipv4/ip_forward echo "Firewall started." 

Comments are written in English - so familiar. If there are requests, I can translate.

Well, do not forget the mandatory part:
 chmod +x /etc/init.d/user-autorun 
Okay, the script is ready. As you can understand, there are four call options - firewall (the last interface is used), firewall is our_interface, firewall info (displays the current interface on which NAT is configured) or firewall help. There is only autoload and $ PATH.

 echo $PATH >/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 

In order to call the script with the firewall command, without specifying the location, you need to shove it into one of the folders specified in the PATH. I prefer / usr / local / bin for religious reasons. The full path to the script will be / usr / local / bin / firewall, but you can always call it from the console simply with the firewall command.

Autoload


And now - autoload, it's more complicated with it. I will immediately describe the creation of an autoload script in which you can shove anything. It will start with the system, but ...

You can not just take and create a startup file. There is one problem - Debian has revised its startup file requirements for some time. It is not enough just to create the file, you need to format it in a special way:
  1. The first problem is LSB headers. This is the autoload file header. It is needed because the autoload components must be executed in a specific order, since some of them depend on each other. Suppose you have two scripts in autoload - one of them will have to mount a network folder, and the second will make a backup copy of the files in it. Naturally, you first need to perform the first and then the second, since the second depends on the first. To specify such dependencies and use the headers of the boot file. However, the title I’ll post in the sample startup file will suffice.
  2. The second problem is that any script in autoload at startup is called by the /etc/init.d/script start command, and when the computer is turned off - by the /etc/init.d/script stop command. It is necessary to add conditions for handling these cases.
I made it simple - I took the script from the existing in /etc/init.d/ as a basis - they should be created according to the rules, then I studied this script and cut out all the unnecessary from it. There are two places that need to be changed - a place for commands that are executed during system startup, and a place for commands that are executed when the computer is turned off. However, now everything will see:

 #!/bin/sh ### BEGIN INIT INFO # Provides: firewall # Required-Start: $network $local_fs $remote_fs # Required-Stop: $network $local_fs $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # X-Interactive: false # Short-Description: Start user autorun events ### END INIT INFO case "$1" in start) echo "Starting user autorun events" /usr/local/bin/firewall #  ,       ;; stop) echo "Stopping user autorun events" #  ,        # NAT   ;; *) echo "Usage: /etc/init.d/user-autorun {start|stop}" exit 1 ;; esac exit 0 

Again, grant execution rights:
 chmod +x /etc/init.d/user-autorun 
In the startup file, it is better to specify the full path to the executable file, because otherwise, when loading, there are sometimes problems like ā€œfirewall: command not foundā€.

We put this file in the /etc/init.d/ folder. The full path to our startup file is /etc/init.d/user-autorun. It remains only to indicate to the system that it is necessary to execute this file at boot:
 update-rc.d user-autorun defaults 
This command at the same time and checks whether the script header is right, so - if there are problems with this, nothing is set up in autoload and you have to deal with errors. Everything, the autoload script is ready to work and will be executed every time the system is started, launching the routing script. Of course, this solution has its drawbacks, such as the inability to control user access to the Internet, except for disabling and enabling the script itself, but for the case of a portable server, plus one and huge - it just works, without intervention and stable, and alternative systems with needs I still have time to consider.
Successful setting!

The next article will most likely be about writing a simple Python web interface using web.py. Through this interface, you can manage NAT (though not exceeding the capabilities of the written script), enable / disable wvdial, send SMS and view the modem status ... And also do everything your hands can reach. So far, I am writing a script for interacting with a modem and thinking through the interface in such a way that it can be easily used even on mobile devices. Also in the stock there is an almost finished article on setting up the parameters for saving the laptop using cpufreqd. Should I post it, will it be relevant?
Reasoned criticism and additions to the article are strongly encouraged.

Source: https://habr.com/ru/post/188886/


All Articles