@ -11,21 +11,21 @@ This exercise is a part of [Linux servers (ICT4TN021, spring 2018) // Linux-palv
**Answer:**
Virtual server IP address is _174.138.2.190_. The server is hosted on [DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-create-your-first-digitalocean-droplet) which provides hosting services for users. Ubuntu 16.04 LTS (without DE) is used as a server platform.
Virtual server IP address is `174.138.2.190`. The server is hosted on [DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-create-your-first-digitalocean-droplet) which provides hosting services for users. Ubuntu 16.04 LTS (without DE) is used as a server platform.
Ubuntu distribution hosted on DigitalOcean has custom configurations compared to Canonical version of clean Ubuntu environment. For example, DigitalOcean has predefined different repository sources in package manager sources file _/etc/apt/sources.list_ (http://mirrors.digitalocean.com/ubuntu/) and has customized configuration for Apache web server by default. Can you trust these repositories and predefined configurations as a system administrator? Can you be sure the program source codes are "clean" and do not contain malicious code patches? Are the used package repositories updated and which flags have been used to compile the binary software available there? What differences are there between the official Canonical and DigitalOcean repositories?
Ubuntu distribution hosted on DigitalOcean has custom configurations compared to Canonical version of clean Ubuntu environment. For instance, DigitalOcean has predefined different repository sources in package manager sources file `/etc/apt/sources.list` (http://mirrors.digitalocean.com/ubuntu/) and has customized configuration for Apache web server by default. Can you trust these repositories and predefined configurations as a system administrator? Can you be sure the program source codes are "clean" and do not contain malicious code patches? Are the used package repositories updated and which flags have been used to compile the binary software available there? What differences are there between the official Canonical and DigitalOcean repositories?
It is good to stop to think the previous issues before looking for a third party hosting service for your server environment. Do available markets have better virtual hosting service providers and in which criteria? In small business, it can be safer to hold all the aces and set up a minimal self-hosted server using a computer (suited for your needs) such as Raspberry Pi and claim a Domain name for it from a DNS provider. If you do larger business, you need to consider your server capacity again. It can be more profitable and comfortable to buy some server space from a virtual hosting server provider.
Of course, if you ever want to, you can install the server environment from scratch using rolling releases such as Arch Linux, Gentoo or 'Linux from Scratch'. However, this is not recommended approach in server environments requiring system stability over newer software.
Of course, if you ever want to, you can install the server environment from scratch using rolling releases such as Arch Linux, Gentoo or 'Linux from Scratch'. However, this is not recommended approach in server environments requiring system stability over newer software. The downside is that some new features or bug/security fixes may not be implemented in older software, so keep that in mind. Some major project, however, backport security fixes to older software versions, too.
Anyway,
1. Do initial configuration for your server following the guide by Tero Karvinen:
**1.** Do initial configuration for your server following the guide by Tero Karvinen:
[Tero Karvinen - First Steps on a New Virtual Private Server – an Example on DigitalOcean and Ubuntu 16.04 LTS](http://terokarvinen.com/2017/first-steps-on-a-new-virtual-private-server-an-example-on-digitalocean)
2. Connect to your new virtual private server once you have set it up. I use a predefined user name _newuser_ in my server environment:
**2.** Connect to your new virtual private server once you have set it up. I use a predefined user name `newuser` in my server environment:
```
phelenius@my-machine:~$ ssh newuser@174.138.2.190
@ -47,41 +47,41 @@ Last login: Tue Feb 13 14:49:24 2018 from XXX.XXX.XXX.XXX
newuser@goauldhost:~$
```
3. Open default SSH TCP port 22 in your firewall:
**3.** Open default SSH TCP port 22 in your firewall:
**NOTE!** Default policy for Ubuntu firewall is to deny/drop all input connections so we need to allow traffic into protocol/daemon specific ports to open up communication between this server and clients.
**NOTE:** Default policy for Ubuntu firewall is to deny/drop all input connections so we need to allow traffic into protocol/daemon specific ports to open up communication between this server and clients.
5. Some PHP and userdir module related configurations seem to be predefined in packages provided on DigitalOcean server environment (such as # symbols in /etc/apache2/mods-enabled/php7.0.conf in order to enable PHP for user sites), unlike stated in [Exercise 3](https://github.com/Fincer/linux_server_setup/blob/master/exercises/h3.md).
**5.** Some PHP and userdir module related configurations seem to be predefined in packages provided on DigitalOcean server environment (such as `#` symbols in `/etc/apache2/mods-enabled/php7.0.conf` in order to enable PHP for user sites), unlike stated in [Exercise 3](https://github.com/Fincer/linux_server_setup/blob/master/exercises/h3.md).
6. Restart Apache HTTP daemon (HTTPD) after enabling _userdir_ module:
**6.** Restart Apache HTTP daemon (HTTPD) after enabling `userdir` module:
If everything seem to be running and working you can try to establish connection to the HTTP daemon server using _your local computer_ (do not try this in your virtual private server environment but with an external client computer):
If everything seem to be running and working you can try to establish connection to the HTTP daemon server using **your local computer** (do not try this in your virtual private server environment but with an external client computer):
Let's get back to the virtual server environment in our SSH session.
8. We should hide any extra server information which is visible for clients. Add the following lines in _/etc/apache2/apache2.conf_ (with sudoedit):
**8.** We should hide any extra server information which is visible for clients. Add the following lines in `/etc/apache2/apache2.conf` (with sudoedit):
- `/bin/bash` is the default shell for the new user
- `1006` is the UID number for the new user. Feel free to change
- `"Monkey account"` is so called "friendly" name of the account (usual syntax is: `first name surname`)
- `"insert_password_here" is the password for the new user`
- `monkey` is the (system) name for the new user
**NOTE:** Not all Linux distributions ship with executable (wrapper) script `adduser`. In this case, either `adduser` must be installed or more primitive (but default/standard) command `useradd` should be used instead.
Now, change to the default shell of user `monkey` (you can check it by executing: `grep monkey /etc/passwd`):
```
newuser@goauldhost:~$ su monkey
@ -125,13 +145,13 @@ monkey@goauldhost:/home/newuser$ cd
monkey@goauldhost:~$ mkdir public_html
```
Therefore we have created a new home site folder for the user _monkey_. Contents of this folder should be available like shown in the following picture:
Therefore we have created a new home site folder for the user `monkey`. Contents of this folder should be available like shown in the following picture:
**NOTE!** As you can see, Apache doesn't give any server information in the website view, thanks for the configurations done in step 8.
**NOTE:** As you can see, Apache doesn't give any server information in the website view, thanks for the configurations done in step 8 above.
User _monkey_ can add any content to his/her personal site. By default, Apache looks for any of the following files, defined in _/etc/apache2/mods-available/dir.conf_ (symbolic link in folder _/etc/apache2/mods-enabled/dir.conf_):
User `monkey` can add any content to his/her personal site. By default, Apache looks for any of the following files, defined in `/etc/apache2/mods-available/dir.conf` (symbolic link in folder `/etc/apache2/mods-enabled/dir.conf`):
```
newuser@goauldhost:~$ ls -l /etc/apache2/mods-enabled/dir.conf
...symbols 2-4 (rwx) indicate permissions of the user _monkey_ to the folder
...symbols 5-7 (rwx) indicate permissions of the (primary) group where the user _monkey_ belongs to. In this case, the group is _monkey_
...symbols 2-4 (rwx) indicate permissions of the user `monkey` to the folder
...symbols 5-7 (rwx) indicate permissions of the (primary) group where the user `monkey` belongs to. In this case, the group is `monkey`
...symbols 8-10 (r-x) indicate permissions granted for other system users to the folder
Permissions can be written in numeric form but also in symbolic form. For example,
Permissions can be written in numeric form but also in symbolic form. For instance,
775 = rwxrwxr-x (4+2+1, 4+2+1, 4+1)
ug=rwx,o=rx = rwxrwxr-x
ug=rwx,o=rx => rwxrwxr-x
Take a look on the following links to get more information about Unix permissions:
@ -175,40 +202,37 @@ Take a look on the following links to get more information about Unix permission
Changing permissions is recommended to be done in symbolic mode because individual permissions can't be as flexibly be changed in numeric mode.
ls command shows a user (monkey) first after which group (monkey) is shown.
`ls` command shows user (`monkey`) first after which group (`monkey`) is shown.
The folder is accessible in public network via address _http://174.138.2.190:80/~monkey/_
The folder is accessible in public network via address `http://174.138.2.190:80/~monkey/`
You can change permissions with _chmod_ command.
You can change above defined permissions with `chmod` command.
Numeric form:
chmod 775 ~/public_html
- Numeric form: `chmod 775 ~/public_html`
Symbolic form:
chmod ug=rwx,o=rx ~/public_html
Symbolic form: `chmod ug=rwx,o=rx ~/public_html`
You can change permissions recursively using _-R_ parameter (chmod -R ...)
**NOTE:** You can change permissions recursively using `-R` parameter (`chmod -R ...`)
**EXTRA: Deleting Server field from HTTP header by updating Apache source code on Debian-based Linux distributions**
--------------
### EXTRA: Deleting Server field from HTTP header by updating Apache source code on Debian-based Linux distributions
Including Server field in HTTP header by Apache HTTP daemon (web server) is debated. [HTTP/1.1 standard specification](https://tools.ietf.org/html/rfc2616#page-141) states the following:
Including Server field in HTTP header by Apache HTTP daemon (web server) is debated. [HTTP/1.1 standard specification](https://tools.ietf.org/html/rfc2616#page-141) states the following:
> Note: Revealing the specific software version of the server might allow the server machine to become more vulnerable to attacks against software that is known to contain security holes. Server implementors are encouraged to make this field a configurable option.
**NOTE!** Apache is compiled from source code.
**NOTE:** Apache must be compiled from source code.
Removal of Server field from HTTP header is debated in Apache developers' community (The key question here: does removal of the field actually improve any security?). More about this topic: [StackoverFlow (Can't remove Server: Apache header)](https://stackoverflow.com/questions/35360516/cant-remove-server-apache-header).
**NOTE!** The following method does not work with automatic system updates via package repositories (usage of _sudo apt-get update_ and _sudo apt-get upgrade_ commands) because the patches binary files would be replaced by ones available in the official repositories. Therefore, each time you want to update your Apache server, you need to recompile it from source applying the patch file provided in this GitHub repository. _This method can be troublesome for system administration or contain unaccepted policy in your company. Consider using puppet or salt or any relevant automation method here._
**NOTE:** The following method does not work with automatic system updates via package repositories (usage of `sudo apt-get update` and `sudo apt-get upgrade` commands) because the patches binary files would be replaced by ones available in the official repositories. Therefore, each time you want to update your Apache server, you need to recompile it from source applying the patch file provided in this GitHub repository. **This method can be troublesome for system administration or contain unaccepted policy in your company. Consider using Puppet/Ansible/Chef/SaltStack or any relevant management to automate method described here.**
**NOTE!** You must be aware what you are doing each time you compile software from source. Trust the source, trust the patch files (diff or patch) and do not do anything that can lead to unknown or troublesome bugs, malicious code execution or create new security risks.
**NOTE:** You must be aware what you are doing each time you compile software from source. Trust the source, trust the patch files (suffixes `.diff` and `.patch`) and do not do anything that can lead to unknown or troublesome bugs, malicious code execution or create new security risks.
**NOTE!** We are unable to sign the package with the official maintainer key because we update Apache with our specific patch file and compile the software ourselves. Therefore we ignore any signing requirements in _dpkg-buildpackage_ command (or alternatively we can use our own keys).
**NOTE:** We are unable to sign the package with the official maintainer key because we update Apache with our specific patch file and compile the software ourselves. Therefore we ignore any signing requirements in `dpkg-buildpackage` command (or alternatively we can use our own keys).
**NOTE** Consider any policy that determines your production and/or server environment requirements. For example: Am I allowed to install software from source code? Does my method break a (critical) component in working server environment? Etc.
**NOTE** Consider any policy that determines your production and/or server environment requirements. For instance: Am I allowed to install software from source code? Does my method break a (critical) component in working server environment? Etc.
**NOTE!** _Again. Know exactly what you are about to do. As a system administrator you hold responsibility here._
**NOTE: Again. Know exactly what you are about to do. As a system administrator you hold responsibility here. Do not get fired.**
We have already improved security of our Apache web server by removing critical information sent to client. However, the server still gives information about its name as follows:
@ -220,7 +244,7 @@ Server: Apache
Content-Type: text/html;charset=UTF-8
```
We want to remove field _Server: Apache_. Multiple approaches were tested (such as modsecurity2 module and writing line _Header unset Server_ into file _/etc/apache2/apache2.conf_) without success. Therefore I ended up patching the source code of Apache web server so that the wanted field can really be removed.
We want to remove field `Server: Apache`. Multiple approaches were tested (such as `modsecurity2` module and writing line `Header unset Server` into file `/etc/apache2/apache2.conf`) without success. Therefore I ended up patching the source code of Apache web server so that the wanted field can really be removed.
Download Apache source code on your Debian-based Linux distribution:
After which add [source code patch file](https://github.com/Fincer/linux_server_setup/blob/master/patches/patch_apache_servertokens.patch) into created _$HOME/source_codes/apache2_ folder.
After which add [source code patch file](https://github.com/Fincer/linux_server_setup/blob/master/patches/patch_apache_servertokens.patch) into created `$HOME/source_codes/apache2` folder.
**NOTE!** I have personally created the patch file with Unix tool _diff_. The patch file is not downloaded from any suspicious website. You can always check the patch file code yourself if still hesitating.
**NOTE:** I have personally created the patch file with Unix tool `diff`. The patch file is not downloaded from any suspicious website. You can always check& analyse the patch file code yourself if still hesitating.
If you have a working Apache HTTP daemon (web server) environment on your Linux, please check the version of your Apache software version with the following command:
If you have a working Apache HTTP daemon (web server) environment on your Linux, please check the version of your Apache software version with the following command before compiling & installing a custom-patched Apache version:
```
newuser@goauldhost:~$ dpkg -s apache2 |grep -i version
Version: 2.4.18-2ubuntu3.5
```
In that way we can be sure version of the downloaded source code matches with our already-installed Apache environment.
In that way we can be sure version of the downloaded source code matches with our already-installed/existing Apache environment.
Once you have downloaded the source code, go to the following folder (which contains the code):
If everything has succeeded you should have a working, patched Apache web server in your target system. Because the patches web server software supports _ServerTokens None_ option now, we shall add this option into _etc/apache2/apache2.conf_.
If everything has succeeded you should have a working, patched Apache web server in your target system. Because the patches web server software supports `ServerTokens None` option now, we shall add this option into `/etc/apache2/apache2.conf`.
Add the following lines (// just replace ServerTokens Prod with None):
Add the following lines (// just replace `ServerTokens Prod` with `ServerTokens None`):
```
TraceEnable Off
@ -326,9 +350,9 @@ ServerSignature Off
ServerTokens None
```
**NOTE!** Any settings in _/etc/apache2/conf-available/security.conf_ overrides these configuration changes.
**NOTE:** Any settings in `/etc/apache2/conf-available/security.conf` overrides these configuration changes.
Restart Apache2 server (you must apply the patch file before doing this because the default Apache software does not implement 'None' for ServerTokens):
Restart Apache2 server (you must apply the patch file before doing this because the default Apache software does not implement `None` for ServerTokens):
Therefore we have successfully deleted Server field from HTTP header.
You can additionally set and unset HTTP header fields sent to a client as follows:
You can additionally set and unset more HTTP header fields sent to a client as follows:
```
Header unset Last-Modified
@ -359,26 +383,26 @@ Header unset Vary
Header unset ETag
```
You must be careful when unsetting fields because it affects behavior of client programs and efficiency of your server environment (performance, for example). Remember that factors such as field order, formatting and error messages can give hints about the used server environment as well (for example, 404 not found message).
**NOTE:** You must be careful when unsetting fields because it affects behavior of client programs and efficiency of your server environment (performance, for instance). Remember that factors such as field order, formatting and error messages can give hints about the used server environment as well (for instance, 404 not found message).
**NOTE!** The header options mentioned above work only if module 'headers' has been activated (run command _sudo a2enmod headers_ and restart the server)
**NOTE:** The header options mentioned above work only if module `headers` has been activated (run command `sudo a2enmod headers` and restart the Apache server)
More about HTTP header in [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields). More articles in [ETag](https://en.wikipedia.org/wiki/HTTP_ETag), [Vary: Accept-Encoding](https://blog.stackpath.com/accept-encoding-vary-important), etc.
More about HTTP header syntax in [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields). More articles in [ETag](https://en.wikipedia.org/wiki/HTTP_ETag), [Vary: Accept-Encoding](https://blog.stackpath.com/accept-encoding-vary-important), etc.
**s)** Set user default website to be the default website for Apache in your virtual server environment.
--------------
**Answer:**
Let's begin from the final state of the previous answer. We have created a user _monkey_ in our server computer. This user has a website URL 174.138.2.190:80/~monkey
Let's begin from the final state of the previous answer. We have created a user `monkey` in our server computer. This user has a website URL `174.138.2.190:80/~monkey` which is accessible outside the server computer, too.
1. Remove default webpage of Apache web server, and move _DocumentRoot_ to point to directory *$HOME/public_html* of user *monkey*, after which restart Apache service daemon.
**1.** Remove default webpage of Apache web server, and move `DocumentRoot` to point to directory `$HOME/public_html` of user `monkey`, after which restart Apache service daemon.
```
newuser@goauldhost:~$ sudo sed -i 's?DocumentRoot /var/www/html?DocumentRoot /home/monkey/public_html?' /etc/apache2/sites-available/000-default.conf
```
We can disable folder path _/var/www_ commenting out the following lines (inserting # symbols) in file */etc/apache2/apache2.conf* (use command _sudoedit_, for example):
We can disable folder path `/var/www` commenting out the following lines (inserting `#` comment symbols) in file `/etc/apache2/apache2.conf` (use command `sudoedit /etc/apache2/apache2.conf`, for instance):
```
#<Directory/var/www/>
@ -394,7 +418,7 @@ Restart Apache web server daemon:
3. We should redirect all index.html traffic to the folder root _/home/monkey/public_html/. This can be done by creating hidden page-related control file _.htaccess_ file to the directory root.
**3.** We should redirect all `index.html` traffic to the folder root `/home/monkey/public_html/`. This can be achieved by creating hidden page-related control file `.htaccess` file to the directory root.
Your Apache web server should redirect all traffic of _http://174.138.2.190:80/index.html_ to address _http://174.138.2.190:80/_
Your Apache web server should redirect all traffic of `http://174.138.2.190:80/index.html` to address `http://174.138.2.190:80/`
**y)** Find clues of possible penetration attempts to your web server. You can find more information about suspicious IP address without connecting them by using commands ipcalc, geoiplookup and whois, for instance.
--------------
**Answer:**
At the time of writing this answer, the Apache web server was running bit over a week period. However, there were no any webpage deployed during that time, and therefore my web server hadn't created any major log entries. However, I noticed one suspicious connection attempt to setup.php file of phpMyAdmin software, although the software was not installed. The lookup was done by checking web server log file _var/log/apache2/access.log_. The log entry itself was as follows:
At the time of writing this answer, the Apache web server was running bit over a week period. However, there were no any webpage deployed during that time, and therefore my web server hadn't created any major log entries. However, I noticed one suspicious connection attempt to setup.php file of phpMyAdmin software, although the software was not installed. The lookup was done by checking web server log file `/var/log/apache2/access.log`. The log entry itself was as follows:
We shall analyze the logged IP address (+ download a georeferred IP database to determine more specific geolocation of the source by using _wget_ command):
We shall analyze the logged IP address (+ download a georeferred IP database to determine more specific geolocation of the source by using `wget` command):
The log entry tells us that connection to page _http://174.138.2.190:80/phpmyadmin/scripts/setup.php_ was tried to establish. The server responded with code 404 (HTTP_NOT_FOUND), indicating that the address couldn't be found. It is seen that user agent string of _66.118.142.165_ is empty (just a line). It is known that the user agent string can be very easily customized.
The log entry tells us that connection to page `http://174.138.2.190:80/phpmyadmin/scripts/setup.php` was tried to be established. The server responded with code 404 (HTTP_NOT_FOUND), indicating that the address couldn't be found. It is seen that user agent string of `66.118.142.165` is empty (just a line). It is known that the user agent string can very easily be customized.
HTTP [HEAD method](http://condor.depaul.edu/dmumaugh/readings/handouts/SE435/HTTP/node14.html) were used in the connection attempt. The HTTP HEAD method is more suitable for quick file existence look-ups than HTTP GET method because only the file existence is checked, leading to decreased data transfer rates between a server and a client. The HEAD method is usually used for caching documents (data). A client program just tries to download metadata of the request document from a server. [Apache web server does not return the message response body while answering to the client program with the HTTP HEAD method.](https://hc.apache.org/httpclient-3.x/methods/head.html).
the HEAD method can be "disabled" by adding the following lines into 1) file *~/public_html/.htaccess* (in the case of this assignment) 2) or into file */etc/apache2/sites-available/000-default.conf* 3) or any site-specific configuration file in Apache's _sites-available_ folder 4) or any _.htaccess_ file in a website directory root:
the HEAD method can be "disabled" by adding the following lines into 1) file `~/public_html/.htaccess` (in the case of this assignment) 2) or into file `/etc/apache2/sites-available/000-default.conf` 3) or any site-specific configuration file in Apache's `sites-available` folder 4) or any `.htaccess` file in a website directory root:
```
RewriteEngine on
@ -490,15 +514,15 @@ RewriteRule .* - [F,L]
The original answer [here](https://www.linuxquestions.org/questions/linux-security-4/disabling-head-options-http-methods-in-apache-webserver-763347/#post4511023)
It is understandable that line _RewriteEngine on_ doesn't need to be determined twice and adding this code requires re-enabling of Apache rewrite module.
It is understandable that line `RewriteEngine on` doesn't need to be determined twice and adding this code requires re-enabling of Apache rewrite module.
I have had a Debian-based web server (LAMP) environment in the past years. I have included Apache access.log parts of that web server environment here (year 2014):
I have had a Debian-based web server (LAMP) environment in the past years. I have included Apache `/var/log/apache/access.log` parts of that web server environment here (year 2014):
@ -509,7 +533,7 @@ The most memorable log entry from the past years was, however, a penetration att
**Answer:**
1. Let's create the required websites locally, after which the upload is done with user _newuser_. I have used pre-created websites in this assignment. The upload is done with my Arch Linux computer using required SSH protocol:
**1.** Let's create the required websites locally, after which the upload is done with user `newuser`. I have used pre-created websites in this assignment. The upload is done with my Arch Linux computer using required SSH protocol:
3. Because /home/newuser/public_html/ is empty (checked with ls command), we shall extract uploaded _website_1.03_fincer.zip_ to that directory.
**3.** Because `/home/newuser/public_html/` is empty (checked with `ls` command), we shall extract uploaded `website_1.03_fincer.zip` to that directory.
7. In the virtual web server computer terminal, go to _$HOME/public_html/ of user _monkey_, extract _server_site.tar.xz_ and put the extracted files into correct places in the directory hierarchy. Rename old _index.html_ file to _index.html.old_
**7.** In the virtual web server computer terminal, go to `$HOME/public_html/` of user `monkey`, extract `server_site.tar.xz` and put the extracted files into correct places in the directory hierarchy. Rename old `index.html` file to `index.html.old`
(you could have just used one * symbol in the previous rm command because the equal name syntax)
(you could have just used one * symbol in the previous rm command because the equal name syntax, i.e. `rm -Rf ./server_site*`)
The deployed website can be viewed in URL address _http://174.138.2.190:80/~apina_, and they look as follows (this example is a work time // wage calculator):
The deployed website can be viewed in URL address `http://174.138.2.190:80/~monkey`, and they look as follows (this example is a work time // wage calculator):
**NOTE:** There are differences in the URL due to language reasons (`~apina` translates from finnish to english as `~monkey`)
**y)** Set up a simple PHP webpage on your web server. For instance, you can print a remote address of the user ( $_SERVER['REMOTE_ADDR'] ) etc. Be careful if you use input forms of any kind.
--------------
**Answer:**
In this answer, I add a PHP-based BMI calculator (Body Mass Index) to my website. For this purpose, two files were created: _bmicalc.html_ and _bmicalc.php_ which both are uploaded to the virtual web server with the following command, executed at the _local computer_:
In this answer, I add a PHP-based BMI calculator (Body Mass Index) to my website. For this purpose, two files were created: `bmicalc.html` and `bmicalc.php` which both are uploaded to the virtual web server with the following command, executed at the **local computer**:
The following image demonstrates a web browser view of URL address _174.138.2.190/bmicalc.html_. On the left side: the source code of the HTML page. On the right side: server-side "raw" PHP source code which is not seen by the client program, our web browser in this case (PHP code = server-side execution/only web server sees the code, JavaScript code = client-side execution/client can see the code, too):
The following image demonstrates a web browser view of URL address `174.138.2.190/bmicalc.html`.
- On the left side: the source code of the HTML page.
- On the right side: server-side "raw" PHP source code which is not seen by the client program, our web browser in this case (PHP code = server-side execution, i.e. only web server sees the code, JavaScript code = client-side execution, i.e. client can see the code, too)