====== Secure Ubuntu System - Initial Configuration ====== ===== Login ===== Login with your previously created Administrator's username and password (e.g. administrator and adminpass). ===== Login using a SSH Client ===== ssh adminstrator@192.168.1.2 The terminal will show something like: The authenticity of host '69.55.55.20 (69.55.55.20)' can't be established. ECDSA key fingerprint is 79:95:46:1a:ab:37:11:8e:86:54:36:38:bb:3c:fa:c0. Are you sure you want to continue connecting (yes/no)? Go ahead and type **yes**, and then enter the password of the administrator, adminpass. ---- ===== Get root privileges (Optional) ===== Because we must run all the next steps from this document with root privileges, we can either prepend all commands in this tutorial with the string **sudo**, or we become root right now by typing: sudo -i ...and entering the Administrator's password, adminpass. **IMPORTANT**: If this is done, then remember to remove the **sudo** command from the front of any future issued command. **DANGER**: Do __NOT__ use the following command: sudo su and do __NOT__ enable the root login by running: sudo passwd root and giving root a password. With these options one can log in as the root user, but this is frowned upon by the Ubuntu developers and community for various reasons. If for some reason the root account has been enabled then disable it again, issuing the following command: sudo passwd -dl root ---- ===== Update APT Sources ===== Keeping the system updated is vital before starting anything on your system. This will prevent people using known vulnerabilities against your system. Update the Linux Installation. Edit the **/etc/apt/sources.list** file. Comment out or remove the installation CD from the file and make sure that the universe and multiverse repositories are enabled. Issue the following command: sudo vi /etc/apt/sources.list It should look like this: # # deb cdrom:[Ubuntu-Server 15.04 _Vivid Vervet_ - Release amd64 (20150422)]/ vivid main restricted # deb cdrom:[Ubuntu-Server 15.04 _Vivid Vervet_ - Release amd64 (20150422)]/ vivid main restricted # See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to # newer versions of the distribution. deb http://gb.archive.ubuntu.com/ubuntu/ wily main restricted deb-src http://gb.archive.ubuntu.com/ubuntu/ wily main restricted ## Major bug fix updates produced after the final release of the ## distribution. deb http://gb.archive.ubuntu.com/ubuntu/ wily-updates main restricted deb-src http://gb.archive.ubuntu.com/ubuntu/ wily-updates main restricted ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu ## team. Also, please note that software in universe WILL NOT receive any ## review or updates from the Ubuntu security team. deb http://gb.archive.ubuntu.com/ubuntu/ wily universe deb-src http://gb.archive.ubuntu.com/ubuntu/ wily universe deb http://gb.archive.ubuntu.com/ubuntu/ wily-updates universe deb-src http://gb.archive.ubuntu.com/ubuntu/ wily-updates universe ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu ## team, and may not be under a free licence. Please satisfy yourself as to ## your rights to use the software. Also, please note that software in ## multiverse WILL NOT receive any review or updates from the Ubuntu ## security team. deb http://gb.archive.ubuntu.com/ubuntu/ wily multiverse deb-src http://gb.archive.ubuntu.com/ubuntu/ wily multiverse deb http://gb.archive.ubuntu.com/ubuntu/ wily-updates multiverse deb-src http://gb.archive.ubuntu.com/ubuntu/ wily-updates multiverse ## N.B. software from this repository may not have been tested as ## extensively as that contained in the main release, although it includes ## newer versions of some applications which may provide useful features. ## Also, please note that software in backports WILL NOT receive any review ## or updates from the Ubuntu security team. deb http://gb.archive.ubuntu.com/ubuntu/ wily-backports main restricted universe multiverse deb-src http://gb.archive.ubuntu.com/ubuntu/ wily-backports main restricted universe multiverse deb http://security.ubuntu.com/ubuntu wily-security main restricted deb-src http://security.ubuntu.com/ubuntu wily-security main restricted deb http://security.ubuntu.com/ubuntu wily-security universe deb-src http://security.ubuntu.com/ubuntu wily-security universe deb http://security.ubuntu.com/ubuntu wily-security multiverse deb-src http://security.ubuntu.com/ubuntu wily-security multiverse ## Uncomment the following two lines to add software from Canonical's ## 'partner' repository. ## This software is not part of Ubuntu, but is offered by Canonical and the ## respective vendors as a service to Ubuntu users. # deb http://archive.canonical.com/ubuntu vivid partner # deb-src http://archive.canonical.com/ubuntu vivid partner **NOTE**: The Ubuntu version and name may differ in the file, depending on what version of Ubuntu is being used. Save the file, then issue the following command: sudo aptitude update to update the apt package database and... sudo aptitude safe-upgrade to install the latest updates (if there are any). If you see that a new kernel gets installed as part of the updates, you should reboot the system afterwards: sudo reboot **aptitude safe-upgrade** will not upgrade packages if: * relied dependencies have not been updated to the required version. * installing the upgrade means removing dependencies that other packages need. === References === * http://wiki.debian.org/Aptitude ---- ===== Enable Automatic Security Updates (optional) ===== Enable automatic updates can be crucial for your server security. It is very important to stay up to date. If you cannot do the weekly maintenance. This is not a perfect solution because an administrator is not monitoring what is being updated and testing after updates. You can install the unattended-upgrades by using this command: sudo apt-get install unattended-upgrades To enable it, run: sudo dpkg-reconfigure -plow unattended-upgrades This will create the file **/etc/apt/apt.conf.d/20auto-upgrades** with the following contents: APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; ---- ==== Customize automatic updates ==== You can customize the automatic updates if you prefer. For example, you can get notifications when a security update is completed. To enable ONLY security updates, please change the code to look like this: // Automatically upgrade packages from these (origin:archive) pairs Unattended-Upgrade::Allowed-Origins { "${distro_id}:${distro_codename}-security"; // "${distro_id}:${distro_codename}-updates"; // "${distro_id}:${distro_codename}-proposed"; // "${distro_id}:${distro_codename}-backports"; }; To get notification by email, update the following line with your email address: Unattended-Upgrade::Mail "my_user@my_domain.com"; ---- ==== Reference ==== * https://help.ubuntu.com/10.04/serverguide/C/automatic-updates.html ---- ===== Upgrading Ubuntu Server to latest LTS version (optional) ===== Having the system upgraded to the most recent LTS version will help towards ensuring that known vulnerabilities against your system are kept to a minimum. **WARNING**: If possible, don't use SSH when upgrading a server. SSH may get logged out and might be unable to login back into the system using SSH until it is fully upgraded. By logging directly into the server this will not be a problem. ==== Back up the Server First ==== This is a good option. The important thing is knowing for certain that you can restore/recreate the server in case the upgraded server is not left in a bootable, usable condition. ---- ==== Install the Upgrade Manager ==== sudo aptitude -y install update-manager-core ---- ==== Double-check Configuration File ==== Run this command to check whether “**/etc/update-manager/release-upgrades**” has the line “**Prompt=lts**”. [[ `grep Prompt=lts /etc/update-manager/release-upgrades` = 'Prompt=lts' ]] && echo '"/etc/update-manager/release-upgrades" is Ok' || echo 'Edit /etc/update-manager/release-upgrades and add line "Prompt=lts"' If the line is not present edit "/etc/update-manager/release-upgrades" with: sudo vi /etc/update-manager/release-upgrades …and add the line: Prompt=lts ---- ==== Run the Upgrade Manager ==== sudo do-release-upgrade Follow the on-screen instructions. When the upgrade manager encounters a configuration file with custom changes, a decision needs to be taken whether to keep the existing configuration file or to replace it with the new configuration file. Usually it’s okay to retain the existing configuration files if you want the system to continue running as it has before. However, any new functionality may be missed by not having the most recent configuration files. If you do decide to keep the existing files, then you may need to tweak the configuration file for: * MySQL - You may be prompted for a new MySQL root password at times. Just press Enter without entering a new password to keep the existing MySQL password. * phpMyAdmin - Adding a new line to phpMyAdmin's configuration file may be needed for the new phpMyAdmin version. === Reference === * Community documentation: https://help.ubuntu.com/community/PreciseUpgrades ---- ===== Update VIM ===== Issue the following command: sudo aptitude install vim-nox The default vi package installed on Debian and Ubuntu is vim-tiny, which is really restricted and only really appropriate for very small environments. To update to the full vim package, install **vim-nox**. Of course, different text editor such as joe or nano can be installed as well. ---- ===== Add Swap (optional) ===== Some pre-installed Ubuntu Server are not configured with SWAP. Linux swaps allow a system to harness more memory than was originally physically available. ==== Check for SWAP space ==== Check if a SWAP file exists and that it is enabled. sudo swapon -s If there's no SWAP file, you should get a result like this: Filename Type Size Used Priority ---- ==== Create and Enable the Swap File ==== For less then 1GB of physical memory (RAM), it's highly recommended that the swap space should, as a base minimum, be equal to the amount of RAM. Also, it's recommended that the swap space is maximum twice the amount of RAM depending upon the amount of hard disk space available for the system because of diminishing returns. For more modern systems (>1GB), your swap space should be at a minimum minimum be equal to your physical memory (RAM) size "if you use hibernation", otherwise you need a minimum of round(sqrt(RAM)) and a maximum of twice the amount of RAM. The only downside to having more swap space than you will actually use, is the disk space you will be reserving for it. The "diminishing returns" means that if you need more swap space than twice your RAM size, you'd better add more RAM as Hard Disk Drive (HDD) access is about 10³ slower then RAM access, so something that would take 1 second, suddenly takes more then 15 minutes! And still more then a minute on a fast Solid State Drive (SSD)... Before the SWAP file it created, determine how much swap is needed. Here's a quick guide to help you. ^RAM in your Server^Recommended swap space^Recommended swap space if allowing for hibernation^Maximum swap space^ |256MB or less|256MB|512MB|512MB| |512MB|512MB|1024MB|1024MB| |1024MB|1024MB|2048MB|2048MB| |1GB|1GB|2GB|2GB| |2GB|1GB|3GB|4GB| |3GB|2GB|5GB|6GB| |4GB|2GB|6GB|8GB| |5GB|2GB|7GB|10GB| |6GB|2GB|8GB|12GB| |8GB|3GB|11GB|16GB| |12GB|3GB|15GB|24GB| |16GB|4GB|20GB|32GB| |24GB|5GB|29GB|40GB| |32GB|6GB|38GB|64GB| |64GB|8GB|72GB|128GB| |128GB|11GB|139GB|256GB| To create the SWAP file, you will need to use the dd command: sudo dd if=/dev/zero of=/swapfile1 bs=1024 count=512k All of this means: ^RAM in your Server^Recommended swap space^ |if=/dev/zero|Read from the /dev/zero file. /dev/zero is a special file that provides as many null characters to build the storage file called /swapfile1.| |of=/swapfile1|Write to storage file /swapfile1.| |bs=1024|Read and write 1024 BYTES bytes at a time.| |count=512k|Copy only 524288 BLOCKS input blocks. This is the size of the swap file.| ---- ==== Prepare the swap file by creating a Linux swap area ==== sudo mkswap /swapfile1 The results display: Setting up swapspace version 1, size = 524284 KiB no label, UUID=265d3e61-6e2b-4126-baba-6e6185e97b46 ---- ==== Activate the swap file ==== sudo swapon /swapfile1 Confirm that the swap partition exists. sudo swapon -s This will output something like: Filename Type Size Used Priority /swapfile1 file 524284 0 -1 This will last until the server reboots. Before, rebooting the server. Let's create the entry in the fstab: sudo vi /etc/fstab and add the following line: /swapfile1 none swap sw 0 0 ==== Improve performance ==== Swappiness in the file should be set to 0. Skipping this step may cause both poor performance, whereas setting it to 0 will cause swap to act as an emergency buffer, preventing out-of-memory crashes. You can do this with the following commands: echo 0 | sudo tee /proc/sys/vm/swappiness echo vm.swappiness = 0 | sudo tee -a /etc/sysctl.conf A low swappiness value causes the kernel to avoid swapping, a higher value causes the kernel to try to use swap space. ^Swappiness Value^Strategy^ |0|The kernel will swap only to avoid an [[https://en.wikipedia.org/wiki/Out_of_memory|out of memory]] condition, when free memory will be below vm.min_free_kbytes limit. See the [[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/sysctl/vm.txt|VM Sysctl documentation]].| |1|Kernel version 3.5 and over, as well as Red Hat kernel version 2.6.32-303 and over: Minimum amount of swapping without disabling it entirely.| |10|This value is sometimes recommended to improve performance when sufficient memory exists in a system.| |60|The default value.| |100|The kernel will swap aggressively.| ---- ==== Secure SWAP ==== To prevent the file from being world-readable, you should set up the correct permissions on the swap file: sudo chown root:root /swapfile1 sudo chmod 0600 /swapfile1 Reboot to make sure the new swap gets activated properly at start-up. ---- ===== Change the Default Shell ===== Issue the following command: sudo dpkg-reconfigure dash When asked "**Install dash as /bin/sh?**" specify “**No**”. **/bin/sh** is a symlink to /bin/dash, however we need **/bin/bash**, not /bin/dash: The reason that dash was set as the default is that dash provides faster boot times. It does not however have the full feature set offered by bash. On a modern server this speed difference in booting is negligible; and not too important as servers usually are not booted very often. ---- ===== Synchronize the System Clock ===== It is a good idea to synchronize the system clock with an NTP (network time protocol) server over the Internet. Issue the following command: sudo aptitude install ntp ntpdate Configure ntpd as necessary, by issuing the command: sudo vi /etc/ntp.conf Add or remove server lines as required: # Use servers from the NTP Pool Project. Approved by Ubuntu Technical Board # on 2011-02-08 (LP: #104525). See http://www.pool.ntp.org/join.html for # more information. server 0.ubuntu.pool.ntp.org server 1.ubuntu.pool.ntp.org server 2.ubuntu.pool.ntp.org server 3.ubuntu.pool.ntp.org After changing the config file reload ntpd, by issuing the following command: sudo /etc/init.d/ntp restart Check the ntp status, by issuing the following command: sudo ntpq -p which should display something like: remote refid st t when poll reach delay offset jitter ============================================================================== ran.as65342.net 192.36.144.23 2 u 40 64 3 35.756 14.750 3.722 orgin.sorch.inf 91.189.94.4 3 u 39 64 3 15.234 14.823 3.803 portal.kt.kg 89.109.251.23 2 u 37 64 3 139.980 14.118 2.702 i4DF67E84.pool. .PPSb. 1 u 38 64 3 37.265 16.166 91.399 europium.canoni 131.188.3.220 2 u 39 64 3 15.170 14.873 4.720 **ALERT**: Ubuntu offers two ways of updating the time, i.e. **ntpdate** and **ntpd**. ntpdate is a bit of a blunt instrument - it adjusts the time in one big correction. The ntp daemon ntpd is far more subtle. It calculates the drift of your system clock and continuously adjusts it, so there are no large corrections that could lead to inconsistent logs for instance. The cost of using ntpd against ntpdate is a little processing power and memory, but for a modern server this is negligible, however ntpd runs as a //service//. Note that for PCI-DSS compliance, we should not be running NTP as a service, unless this specific server is going to be used as a NTP server. The reason being that PCI-DSS stipulates that each server in the network should only run a single external service, and as NTP could be classified as a service, this same server could not then be used for any other service, such as MySql. If we don't want this to run as a service, we should only use ntpdate. Issue the following commands in this case: sudo aptitude install ntpdate and test by issuing the command: sudo ntpdate pool.ntp.org which should display something like: 22 Jun 00:06:43 ntpdate[3032]: adjust time server 87.106.21.237 offset 0.000174 sec To use a different NTP Server such as pdc.sharewiz.net, modify the configuration file /etc/default/ntpdate if required: NTPDATE_USE_NTP_CONF=no NTPSERVERS="pdc.sharewiz.net" and test again by issuing the command: sudo ntpdate pdc.sharewiz.net Create a cron job to regularly keep the system’s time in sync, by issuing the command: sudo vi /etc/cron.hourly/ntpdate and populate with the following contents: #!/bin/bash # # Calls ntpdate-debian to syncronize the time ntpdate-debian and finally make the cron job executable, by issuing the following command: sudo chmod 755 /etc/cron.hourly/ntpdate and your system time will always be in sync. The cron job calls the ntpdate-debian function instead of simply the ntpdate function. The ntpdate function could be used, but the actual NTP server has to then be passed as a parameter. **ntpdate-debian** does not need a parameter and uses the time-servers recorded within the /etc/default/ntpdate file. ---- ==== Update crontab times ==== Issue the following command: sudo vi /etc/crontab and modify the contents as per the following: # /etc/crontab: system-wide crontab # Unlike any other crontab you don't have to run the `crontab' # command to install the new version when you edit this file # and files in /etc/cron.d. These files also have username fields, # that none of the other crontabs do. SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # m h dom mon dow user command #17 * * * * root cd / && run-parts --report /etc/cron.hourly #25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) #47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) #52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ) # 0 * * * * root cd / && run-parts --report /etc/cron.hourly 0 0 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) 0 0 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) 0 0 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ) # For some strange reason, the default hour when the daily, weekly, and monthly cron jobs are run is around 6am in the morning. The hour is modified to be close to midnight so that we can ensure that jobs are run at the start of a new day. This also helps with log rotation, in that new daily logs are started at the beginning of each day instead of at 6am. **NOTE**: Slight differences between the minutes of each individual cron job could ensure that jobs run by different parts of cron don’t conflict. ---- ====== Add Global Aliases ====== Aliases simplify the running of complex commands. Arguments cannot be used in an alias command. If arguments are needed, a shell function should be used instead of an alias. Global Aliases would normally be added to the **/etc/profile** file, but it’s cleaner to have a separate file for the aliases. **NOTE**: A user can overwrite the global aliases if needed by defining their own aliases within their .bashrc, .bash_aliases, or .profile files within their own home directories. To see what aliases are currently defined use the **alias** command. To disable an alias in your current shell, use **unalias** name. An alias can be temporarily disabled in the current command by prefixing the alias name with a \. For example: \ls. Issue the following command: sudo vi /etc/profile.d/bash_aliases.sh and add the following to the file: # Instruct bash to expand the arguments to aliases. shopt -s expand_aliases #------------------------------------------------------------- # Protection for these commands; which will prompt before overwriting. #------------------------------------------------------------- # Do not delete / and prompt before deleting. alias rm='rm -i --preserve-root' alias cp='cp -i' alias mv='mv -i' alias ln='ln -i' # Preventing changing perms on / alias chown='chown --preserve-root' alias chmod='chmod --preserve-root' alias chgrp='chgrp –preserve-root' alias rmdir='rm -Rf $1' #------------------------------------------------------------- # cd #------------------------------------------------------------- # To pick up when user forgets the space. alias cd..='cd ..' # Uses cd() function = pushd, # b = go backwards (popd), f = go forwards (kind of like "unpopd"). alias d='dirs' alias b='pushd +1' # go backwards (popd). alias f='pushd -0' # go forwards (kind of like "unpopd"). #------------------------------------------------------------- # Disk #------------------------------------------------------------- alias du='du -kh' # Human-readable format. alias dutotal='du -ch 2> /dev/null |tail -1' # Displays only the total. alias dutop10='du -hsx * | sort -rh | head -10' # What is using the most space. alias df='\df -kTh;\df -Thl --total | grep total' # Adds total to the df command. # Shows the individual partition usages without the temporary memory values. alias dfx='\df -kThl --exclude-type=tmpfs --exclude-type=devtmpfs' #------------------------------------------------------------- # Directories. #------------------------------------------------------------- alias mkdir='mkdir -p' # Make parent directories if needed. alias back='cd $OLDPWD' # Return to the last directory you were in. Same as 'cd -'. #------------------------------------------------------------- # Downloading. #------------------------------------------------------------- alias wget='wget -c' # -c flag to continue download in case of problems. alias wgetpage='wget --html-extension --recursive --convert-links --page-requisites --no-parent $1' #------------------------------------------------------------- # Files. #------------------------------------------------------------- alias fcount='ls -l | wc -l' # File count. alias fcounta='ls -la | wc -l' # File count (incl hidden files). alias fcountr='find . -type f | wc -l' # File count recursive. alias lastmodified='find -type f -print0 | xargs -r0 stat -c %y\ %n | sort' alias nocomment='grep -Ev "^(#|$)"' # Show text file without comment (#) lines; or empty lines. alias bigfiles='find . -type f 2>/dev/null | xargs du -a 2>/dev/null | awk "{ if ( \$1 > 5000) print \$0 }" | sort -hr' alias verybigfiles='find . -type f 2>/dev/null | xargs du -a 2>/dev/null | awk "{ if ( \$1 > 500000) print \$0 }" | sort -hr' alias brokenlinks='\find . -xtype l -printf "%p -> %l\n"' # Find broken symlinks. # count files by type - http://www.shell-fu.org/lister.php?id=173 alias ftype="find ${*-.} -type f | xargs file | awk -F, '{print $1}' | awk '{$1=NULL;print $0}' | sort | uniq -c | sort -nr" #------------------------------------------------------------- # File Permissions. #------------------------------------------------------------- alias fperm="find . -type f -exec chmod 0644 '{}' \;" alias dperm="find . -type d -exec chmod 0755 '{}' \;" #------------------------------------------------------------- # Greps. #------------------------------------------------------------- alias grep='grep --color=auto' # alias egrep='egrep --color=auto' # alias fgrep='fgrep --color=auto' # alias grepall='find . -name "*" | xargs grep --color=auto ' #------------------------------------------------------------- # Logs. #------------------------------------------------------------- # alias syslog='sudo tail -10f /var/log/syslog' # Follow syslog. # alias messages='sudo tail -10f /var/log/messages' # Follow messages. # Last 10 items within every log file. alias logs='tail -f /var/log/{dmesg,messages,*{,/*}{log,err}}' #------------------------------------------------------------- # ls. (Assumes you use a recent GNU ls). #------------------------------------------------------------- alias ls='ls -h --color=auto' # Add colors and human-readable sizes by default on 'ls'. alias lsa='ls -A' # Show hidden files. alias lsd='ls -al -d * | egrep "^d"' alias lsdf='ls -v --group-directories-first' # Directories first, with alphanumeric sorting. alias lsdt='ls -h --group-directories-first --time-style=+"%d.%m.%Y %H:%M" --color=auto -F' alias lse='ls -AF | grep \*' # Show executables only. alias lsh='ls -Am' # List files horizontally, comma-separated. alias lsm='ls -Al |more' # Pipe through 'more'. alias lsne='ls -AF | grep -v \*' # Show non executables only. alias lsnx='ls -AF | egrep -v "\.|/"' # Show only file without an extension. alias lsr='ls -lR' # List files recursively. alias lssh='ls -Ax' # Sort by name horizontally. alias lsss='ls -Sr' # Sort by size, biggest last. alias lsssh='ls -shAxSr' # Sort by size, biggest last, horizontally. alias lsst='ls -Atr' # Sort by date, most recent last alias lssta='ls -Atur' # Sort by/show access time,most recent last. alias lsstc='ls -Atcr' # Sort by/show change time,most recent last. alias lssx='ls -AXB' # Sort by extension. alias lsx='ls -AF | egrep "\.|/"' # Show only file with an extension. alias ll='ls -lF' # Long listing, classify. alias lla='ls -lAF' # All files, long listing. alias lld='ls -lFA | grep :*/' # List only directories, if any exist. alias lldf='ls -lv --group-directories-first' # Directories first, with alphanumeric sorting. alias lldt='ls -lh --group-directories-first --time-style=+"%d.%m.%Y %H:%M" --color=auto -F' alias lle='ls -lFA | grep \*' # Show executables only. alias llm='ll |more' # Pipe through 'more' alias llne='ls -lFA | grep -v \*' # Show non executables only. alias llnx='ls -lFA | egrep -v "\.|/"' # Show only file without an extension. alias llr='ll -lAR' # Recursive ls. alias llss='ls -lSr' # Sort by size, biggest last. alias llst='ls -lAtrh' # Sort by date, most recent last, and human readable alias llsta='ls -ltur' # Sort by/show access time,most recent last. alias llstc='ls -ltcr' # Sort by/show change time,most recent last. alias llsx='ls -lXB' # Sort by extension. alias llx='ls -lFA | egrep "\.|/"' # Show only file with an extension. alias tree='find . | sed "s/[^/]*\//| /g;s/| *\([^| ]\)/+--- \1/"' # Simple tree of current dir. #------------------------------------------------------------- # Memory. #------------------------------------------------------------- alias mem='echo -e Memory usage: $(free -h | grep "+" | cut -c26-30)/ $(free -h | grep "Mem:" | cut -c15-18)' #------------------------------------------------------------- # Misc. #------------------------------------------------------------- alias pause='read -n 1 -p "Press any key to continue…"' alias restart='killall -SIGUSR1' alias utf='iconv -f ISO-8859-1 -t UTF-8' alias which='type -a' # Includes aliases. #------------------------------------------------------------- # Networking. #------------------------------------------------------------- alias connections='sudo /usr/bin/lsof -i -P' alias openports='netstat -lntp 2>/dev/null | grep -v " - *$"' # Shows open ports. alias macs='ifconfig | grep HWaddr' # Shows MAC addresses for all nics. alias nics='ifconfig em1 | egrep "[0-9]{1,3}(\.[0-9]{1,3}){3}"' # Shows all nics. alias ping='ping -c 5' # Stop after sending count ECHO_REQUEST packets. alias fastping='sudo ping -c 5 -s.2' # Do not wait interval 1 second, go fast. # Network diagnostic. # Usage: mtr google.com alias trace='mtr --report-wide --curses $1' #------------------------------------------------------------- # Path. #------------------------------------------------------------- # Pretty-print of some PATH variables: alias path='echo -e ${PATH//:/\\n}' # echo $PATH | tr ':' '\n'. alias libpath='echo -e ${LD_LIBRARY_PATH//:/\\n}' #------------------------------------------------------------- # Processes. #------------------------------------------------------------- alias psc='ps h -eo pcpu,pmem,pid,comm,user,cputime | sort -nr | head' # By CPU. alias psm='ps h -eo pmem,pcpu,pid,comm,user,cputime | sort -nr | head' # By Mem. alias pstree='ps -e -o pid,args --forest' alias psfull='ps -auxwww' # ps with wide output so you can see full commands. # usage: psg peter # usage: psg ssh alias psg='ps -Helf | grep -v $$ | grep -i -e WCHAN -e ' # ps grep. # Show only my procs. alias myps='ps -fHu $USER' # if not $USER, try $LOGIN #------------------------------------------------------------- # Programming – C/C++/Java/PHP. #------------------------------------------------------------- # Count lines of php code under the current directory. alias countphp='find . -name "*.php" -print0 | xargs -0 wc' # Count lines of java code under the current directory. alias countjava='find . -name "*.java" -print0 | xargs -0 wc' # Count lines of C or C++ or Obj-C code under the current directory. alias countc='find . \( -name "*.c" -or -name "*.cpp" -or -name "*.h" -or -name "*.m" \) -print0 | xargs -0 wc' # Count lines of C or C++ or Obj-C or Java or PHP code under the current directory. alias countcode='find . \( -name "*.c" -or -name "*.cpp" -or -name "*.h" -or -name "*.m" -or -name "*.java" -or -name "*.php" \) -print0 | xargs -0 wc' #------------------------------------------------------------- # Spelling typos. Highly personal and keyboard-dependent. #------------------------------------------------------------- alias xs='cd' alias vf='cd' alias moer='more' alias moew='more' alias kk='ll' #------------------------------------------------------------- # Text. #------------------------------------------------------------- # Truncate lines longer than 80 characters (for use in pipes). alias cut80='/usr/bin/cut -c 1-80' alias tn='tr -d "\n"' # trim newlines. #------------------------------------------------------------- # Time. #------------------------------------------------------------- alias now='date +"%T"' alias nowtime=now alias nowdate='date +"%Y-%m-%d"' #------------------------------------------------------------- # Web. #------------------------------------------------------------- # Pass it via sudo so whoever is admin can reload it without calling you. alias nginxreload='sudo /usr/sbin/nginx -s reload' alias nginxtest='sudo /usr/sbin/nginx -t' It is important to note that the aliases will only be read when the shell is created. Therefore, you won’t see any changes to the aliases immediately. You need to either create a new shell after saving your modified **/etc/profile.d/bash_aliases** file or to (re)load the file like this: sudo /etc/profile.d/bash_aliases.sh ---- ===== Add Global Functions ===== Bash functions store a series of commands for later execution. If a sequence of commands is run frequently, it would make sense to wrap them up in a function. Functions are a lot like aliases but you can also pass arguments to them. Functions act as a compromise between aliases and scripts. They are usually much simpler than full-blown scripts. Global Functions would normally be added to the **/etc/profile** file, but it’s cleaner to have a separate file for the functions. **NOTE**: A user can overwrite the global functions if needed by define their own functions within their .bashrc, .bash_aliases, or .profile files within their own home directories. Issue the following command: sudo vi /etc/profile.d/bash_functions.sh and add the following to the file: #------------------------------------------------------------- # Archiving functions. #------------------------------------------------------------- # Creates an archive. archive() { if [ "$#" -ne 0 ] ; then FILE="$1" case "$FILE" in *.tar.bz2|*.tbz2) shift && tar cvjf "$FILE" $* ;; *.tar.gz|*.tgz) shift && tar cvzf "$FILE" $* ;; *.tar) shift && tar cvf "$FILE" $* ;; *.rar) shift && rar "$FILE" $* ;; *.zip) shift && zip "$FILE" $* ;; *.7z) shift && 7zr a "$FILE" $* ;; *) echo "'$1' cannot be archived via archive()" ;; esac else echo "usage: archive [file] [contents]" fi } # Extract an archive of any type. extract() { local opt local OPTIND=1 while getopts "hv?" opt; do case "$opt" in h) cat < options: -h show this message and exit -v verbosely list files processed End-Of-Usage return ;; v) local -r verbose='v' ;; ?) extract -h >&2 return 1 ;; ac done shift $((OPTIND-1)) [ $# -eq 0 ] && extract -h && return 1 while [ $# -gt 0 ]; do if [ -f "$1" ]; then case "$1" in *.tar.bz2|*.tbz|*.tbz2) tar "xvjf" "$1" ;; *.tar.gz|*.tgz) tar "xvzf" "$1" ;; *.tar.xz) xz --decompress "$1"; set -- "$@" "${1:0:-3}" ;; *.tar.Z) uncompress "$1"; set -- "$@" "${1:0:-2}" ;; *.bz2) bunzip2 "$1" ;; *.deb) dpkg-deb -xv "$1" "${1:0:-4}" ;; # *.deb) sudo dpkg -i $1 ;; *.exe) cabextract "$1" ;; *.pax.gz) gunzip "$1"; set -- "$@" "${1:0:-3}" ;; *.gz) gunzip "$1" ;; *.lzma) unlzma "$1" ;; *.pax) pax -r -f "$1" ;; *.pkg) pkgutil --expand "$1" "${1:0:-4}" ;; *.rar) unrar x "$1" ;; *.rpm) rpm2cpio "$1" | cpio -idmv ;; # *.rpm) sudo alien -dik $1;; *.tar) tar "xvf" "$1" ;; *.txz) mv "$1" "${1:0:-4}.tar.xz"; set -- "$@" "${1:0:-4}.tar.xz" ;; *.xz) xz --decompress "$1" ;; *.zip|*.war|*.jar) unzip "$1" ;; *.Z) uncompress "$1" ;; *.7z) 7za x "$1" ;; *) echo "'$1' cannot be extracted via extract" >&2;; esac else echo "extract: '$1' is not a valid file" >&2 fi shift done } # ls archives (inspired by `extract`) lsz() { if [ $# -ne 1 ] then echo "lsz filename.[tar,tgz,gz,rar,zip,etc]" return 1 fi if [ -f $1 ] ; then case $1 in *.tar.bz2|*.tar.gz|*.tar|*.tbz2|*.tgz) tar tvf $1;; *.rar) unrar l $1;; *.zip) unzip -l $1;; *) echo "'$1' unrecognized." ;; esac else echo "'$1' is not a valid file" fi } # Creates an archive (*.tar.gz) from given directory. maketar() { tar cvzf "${1%%/}.tar.gz" "${1%%/}/"; } # Create a ZIP archive of a file or folder. makezip() { zip -r "${1%%/}.zip" "$1" ; } #------------------------------------------------------------- # Calculator functions. #------------------------------------------------------------- # Calculate an expression e.g. calc 1+1. calc() { echo "$@"|bc -l; } #------------------------------------------------------------- # cd. #------------------------------------------------------------- # cd = pushd, b = go backwards (popd), f = go forwards (kind of like "unpopd"). #alias d='dirs' #alias b='pushd +1' #alias f='pushd -0' cd() { if [ "$*" = "" ]; then pushd $HOME >/dev/null else pushd "$*" >/dev/null fi } # cd to the directory a symbolically linked file is in. cdlink { if [ "x$1" = "x" ] ; then echo "Missing Arg" elif [ -L "$1" ] ; then link=`/bin/ls -l $1 | tr -s ' ' | cut -d' ' -f10` if [ "x$link" = "x" ] ; then echo "Failed to get link" return fi dirName_=`dirname $link` cd "$dirName_" else echo "$1 is not a symbolic link" fi return } # cd to the dir that a file is found in. cdff { filename=`find . -name $1 | grep -iv "Permission Denied" | head -1` if [ "xx${filename}xx" != "xxxx" ] ; then dirname=${filename%/*} if [ -d $dirname ] ; then cd $dirname fi fi } #------------------------------------------------------------- # Directory functions. #------------------------------------------------------------- # Jumps to a directory at any level below using globstar. jd() { if [ -z $1 ]; then echo "Usage: jd [directory]"; return 1 else cd **/$@ fi } # Go up a specified number of directories. # If you pass no arguments, it just goes up one directory. # If you pass a numeric argument it will go up that number of directories. # If you pass a string argument, it will look for a parent directory with that name and go up to it. up() { dir="" if [ -z "$1" ]; then dir=.. elif [[ $1 =~ ^[0-9]+$ ]]; then x=0 while [ $x -lt ${1:-1} ]; do dir=${dir}../ x=$(($x+1)) done else dir=${PWD%/$1/*}/$1 fi cd "$dir"; } #------------------------------------------------------------- # Disk functions. #------------------------------------------------------------- # Pretty-print of 'df' output. # Inspired by 'dfc' utility. mydf() { for fs ; do if [ ! -d $fs ] then echo -e $fs" :No such file or directory" ; continue fi local info=( $(command df -P $fs | awk 'END{ print $2,$3,$5 }') ) local free=( $(command df -Pkh $fs | awk 'END{ print $4 }') ) local nbstars=$(( 20 * ${info[1]} / ${info[0]} )) local out="[" for ((j=0;j<20;j++)); do if [ ${j} -lt ${nbstars} ]; then out=$out"*" else out=$out"-" fi done out=${info[2]}" "$out"] ("$free" free on "$fs")" echo -e $out done } #------------------------------------------------------------- # Downloading functions. #------------------------------------------------------------- # More persistent wget for fetching files to a specific filename. wgettofile() { [ $# -ne 2 ] && echo "usage: wgettofile " && return 1 urltofetch=$1 fname="$2" wget -O "$fname" $urltofetch } #------------------------------------------------------------- # Email functions. #------------------------------------------------------------- # Email me a short note. emailme() { if [ $# -eq 0 ] then echo Usage: emailme text return 1 fi echo "$*" | mailx -s "$*" administrator echo "Sent email" } #------------------------------------------------------------- # File functions. #------------------------------------------------------------- # Backup file(s) filebackup() { if [ $# -lt 1 ] then echo Please supply a file to backup return 1 fi date=`date +%Y%m%d-%H%M%S` for i in "$@" do echo Backed up $i to $i.$date cp "$i" "$i".$date done } # Output a text file with line numbers # # Overriding the newline-to-tab conversion (with the -d flag) and # replacing newlines with TAB-newline, maintaining the newline # but indenting it. sed = will number the lines in the output, # and the -s switch on paste will restore our whitespace keeping # the line number justified to the left. filecatno() { if [ $# == 0 ]; then echo "No filename provided." else sed = "$1" | paste -s -d '\t\n' - - fi } # Show all strings (ASCII & Unicode) in a file. filecatstr() { cat "$1" | tr -d "\0" | strings ; } # Changes the extension of all of the specified files in a directory. # It takes two arguments, first the original extension, # then the extension to replace it with. # For example # filechgext html php filechgext() { for file in *.$1 ; do mv "$file" "${file%.$1}.$2" ; done } # Find a file with pattern $1 in name and Execute $2 on it: fileexec() { find . -type f -iname '*'"${1:-}"'*' \ -exec ${2:-file} {} \; ; } # Fast find, using globstar. filefind() { ls -ltr **/$@ } # Swap 2 filenames around, if they exist. fileswap() { local TMPFILE=tmp.$$ [ $# -ne 2 ] && echo "Usage: fileswap file1 file2" && return 1 # [ $# -ne 2 ] && echo "fileswap: 2 arguments needed" && return 1 [ ! -e $1 ] && echo "fileswap: $1 does not exist" && return 1 [ ! -e $2 ] && echo "fileswap: $2 does not exist" && return 1 mv "$1" $TMPFILE mv "$2" "$1" mv $TMPFILE "$2" } # Moves file to ~/.Trash (use instead of rm). filetrash() { if [ $# -eq 0 ] then echo Usage: filetrash FILE... return 1 fi local DATE=$(date +%Y%m%d) [ -d "${HOME}/.Trash/${DATE}" ] || mkdir -p ${HOME}/.Trash/${DATE} for FILE in "$@" do mv "${FILE}" "${HOME}/.Trash/${DATE}" echo "${FILE} trashed!" done } # Overwrite a file with zeroes - http://www.shell-fu.org/lister.php?id=94 filezero() { case "$1" in "") echo "Usage: filezero " return -1; esac filesize=`wc -c "$1" | awk '{print $1}'` dd if=/dev/zero of=$1 count=$filesize bs=1 } #------------------------------------------------------------- # Firewall functions. #------------------------------------------------------------- # Ban IP ban() { if [ "`id -u`" == "0" ] ; then iptables -A INPUT -s $1 -j DROP else sudo iptables -A INPUT -s $1 -j DROP fi } #------------------------------------------------------------- # Grep Find Search functions. #------------------------------------------------------------- # Find a file with a pattern in name: # Examples: # ff ash ff() { find . -type f -iname '*'"$*"'*' -ls ; } # Find a file whose name starts with a given string. ffs() { /usr/bin/find . -name "$@"'*' ; } # Find a file whose name ends with a given string. ffe() { /usr/bin/find . -name '*'"$@" ; } # Find files larger than a certain size (in bytes). ffbigger() { find . -type f 2>/dev/null | xargs \du -a -b 2>/dev/null | awk "{ if ( \$1 > $@) print \$0 }" | sort -hr; } # Find a pattern in a set of files and highlight them: #+ (needs a recent version of egrep). findstr() { OPTIND=1 local mycase="" local usage="findstr: find string in files. Usage: grepstr [-i] \"pattern\" [\"filename pattern\"] " while getopts :it opt do case "$opt" in i) mycase="-i " ;; *) echo "$usage"; return ;; esac done shift $(( $OPTIND - 1 )) if [ "$#" -lt 1 ]; then echo "$usage" return; fi find . -type f -name "${2:-*}" -print0 | \ xargs -0 egrep --color=always -sn ${case} "$1" 2>&- | more } # Search for a word in the Unix word list. word() { /bin/grep ^"$@"$ /usr/share/dict/words ; } # Search for a word in the Unix word list that ends with the chars. wordstarts() { /bin/grep ^"$@" /usr/share/dict/words ; } # Search for a word in the Unix word list that ends with the chars. wordends() { /bin/grep "$@"$ /usr/share/dict/words ; } #------------------------------------------------------------- # Info functions. #------------------------------------------------------------- # Get current host related info. ii() { echo -e "\nYou are logged on ${BRed}$HOST" echo -e "\n${BRed}Additionnal information:$NC " ; uname -a echo -e "\n${BRed}Users logged on:$NC " ; w -hs | cut -d " " -f1 | sort | uniq echo -e "\n${BRed}Current date :$NC " ; date echo -e "\n${BRed}Machine stats :$NC " ; uptime echo -e "\n${BRed}Memory stats :$NC " ; free echo -e "\n${BRed}Diskspace :$NC " ; mydf / $HOME echo -e "\n${BRed}Local IP Address :$NC" ; my_ip echo -e "\n${BRed}Open connections :$NC "; netstat -pan --inet; echo } #------------------------------------------------------------- # Misc functions. #------------------------------------------------------------- # Waits for the user to press a y or n. # # Example: # if ask "Kill process $pid <$pname> with signal $sig?" # then kill $sig $pid # fi ask() { echo -n "$@" '[y/n] ' ; read ans case "$ans" in y*|Y*) return 0 ;; *) return 1 ;; esac } # Repeat n times command. # # Example: # repeat 10 ls repeat() { local i max max=$1; shift; for ((i=1; i <= max ; i++)); do # --> C-like syntax eval "$@"; done } # Do something very quietly. runquiet() { ( $@ ) >/dev/null 2>/dev/null } #------------------------------------------------------------- # Network functions. #------------------------------------------------------------- # myIP address ipall() { ifconfig lo | grep 'inet ' | sed -e 's/:/ /' | awk '{print "lo: " $2 " " $3 " " $4 " " $5 " " $6}' ifconfig em1 | grep 'inet ' | sed -e 's/:/ /' | awk '{print "em1 (IPv4): " $2 " " $3 " " $4 " " $5 " " $6}' ifconfig em1 | grep 'inet6 ' | sed -e 's/ / /' | awk '{print "em1 (IPv6): " $2 " " $3 " " $4 " " $5 " " $6}' ifconfig em2 | grep 'inet ' | sed -e 's/:/ /' | awk '{print "em2 (IPv4): " $2 " " $3 " " $4 " " $5 " " $6}' ifconfig em2 | grep 'inet6 ' | sed -e 's/ / /' | awk '{print "em2 (IPv6): " $2 " " $3 " " $4 " " $5 " " $6}' } # Get IP adress on ethernet. myip() { MY_IP=$(/sbin/ifconfig em1 | awk '/inet/ { print $2 } ' | sed -e s/addr://) echo ${MY_IP:-"Not connected"} } getip() { for each in $@; do echo $each echo "nslookup:" nslookup $each | grep Address: | grep -v '#' | egrep -o '([0-9]+\.){3}[0-9]+' echo "ping:" ping -c1 -t1 $each | egrep -o '([0-9]+\.){3}[0-9]+' | head -n1 done } #------------------------------------------------------------- # Process functions. #------------------------------------------------------------- psnice() { if ! [ -z "$1" ] then # Take a parameter pid. ionice -c3 -p$1 ; renice -n 19 -p $1 else # If no parameter is nice the current pid (bash). ionice -c3 -p$$ ; renice -n 19 -p $$ fi } #------------------------------------------------------------- # String functions. #------------------------------------------------------------- # substring word start [length] substring() { if [ $# -lt 2 ]; then echo "Usage: substring word start [length]" return 1 fi if [ -z $3 ] then echo ${1:$2} else echo ${1:$2:$3} fi } # Get length of string. strlen() { if [ $# -ne 1 ]; then echo "Usage: length word" return 1 fi echo ${#1} } # Convert string to upper-case. strupper() { if [ $# -lt 1 ]; then echo "Usage: upper word" return 1 fi echo ${@^^} } # Convert string to lower-case. strlower() { if [ $# -lt 1 ]; then echo "Usage: lower word" return 1 fi echo ${@,,} } # Replace part of string with another. strreplace() { if [ $# -ne 3 ]; then echo "Usage: replace string substring replacement" return 1 fi echo ${1/$2/$3} } # Replace all parts of a string with another. strreplaceall() { if [ $# -ne 3 ]; then echo "Usage: replace string substring replacement" return 1 fi echo ${1//$2/$3} } # Find index of specified string. strindex() { if [ $# -ne 2 ]; then echo "Usage: index string substring" return 1 fi expr index $1 $2 } # Surround lines with quotes (useful in pipes). strquote() { echo "$@" | /bin/sed 's/^/"/;s/$/"/' ; } # Surround string with whatever is given as 2nd param. # # Example: # strsurround abc 123 # strsurround abc \" # strsurround abc \\\\ strsurround() { if [ $# -ne 2 ] then echo Usage: surround string surround-with e.g. surround hello \\\\ return 1 fi echo $1 | sed "s/^/$2/;s/$/$2/" ; } #------------------------------------------------------------- # USB functions. #------------------------------------------------------------- # Need to figure out which drive your usb is assigned? Functions work the same way as an alias. Simply copy the line into your .profile/.bashrc file. Then type: myusb myusb() { usb_array=();while read -r -d $'\n'; do usb_array+=("$REPLY"); done < <(find /dev/disk/by-path/ -type l -iname \*usb\*scsi\* -not -iname \*usb\*scsi\*part* -print0 | xargs -0 -iD readlink -f D | cut -c 8) && for usb in "${usb_array[@]}"; do echo "USB drive assigned to sd$usb"; done; } It is important to note that the functions will only be read when the shell is created. Therefore, you won’t see any changes to the functions immediately. You need to either create a new shell after saving your modified **/etc/profile.d/bash_functions** file or to (re)load the file like this: sudo . /etc/profile.d/bash_functions.sh Allow colour prompts for the root and sudo users (highly recommended) Issue the following command: sudo vi /root/.bashrc and remove the hash from the begin of the **force_color_prompt** line: force_color_prompt=yes This functionality is not required, but does makes it a lot easier to see what’s going on, so recommended. ---- ===== Allow colour prompts for the administrator (highly recommended) ===== Issue the following command: sudo vi /home/administrator/.bashrc and remove the hash from the begin of the **force_color_prompt** line: force_color_prompt=yes This functionality is not required, but does makes it a lot easier to see what’s going on, so recommended. ---- ===== Restart the System ===== To enable the changes to be recognized, restart the system. Issue the following command: sudo reboot ...and log back in using a SSH client, such as Putty. ---- ===== Login using a SSH Client ===== ssh adminstrator@192.168.1.2 The terminal will show something like: The authenticity of host '69.55.55.20 (69.55.55.20)' can't be established. ECDSA key fingerprint is 79:95:46:1a:ab:37:11:8e:86:54:36:38:bb:3c:fa:c0. Are you sure you want to continue connecting (yes/no)? Go ahead and type **yes**, and then enter the password of the administrator, adminpass. ---- ===== Continue ===== Continue to [[Secure Ubuntu System:Base Security]]