Changes

Jump to: navigation, search

Shared webhosting

6,021 bytes added, 06:31, 23 October 2011
m
Protected "Shared webhosting": Excessive spamming ([edit=autoconfirmed] (indefinite) [move=autoconfirmed] (indefinite))
This document describes creating a "secure shared web hosting service" on [[HN]] (Hardware Node). It is '''NOT''' about per container shared web hosting.
 
{{roughstub}}
 
== The problem ==
One of the problems with shared webhosting web hosting (i.e. different people with each his/her own webpages) is that modern script languages such as PHP, Python , or Perl are to powerfulltoo powerful. For example take the following PHP script:
<pre>
</pre>
With PHP you could use open_basedir to prevent this, but there are more ways. For example [http://mgeisler.net/php-shell/ PHP Shell], a script that is [http://mgeisler.net/downloads/phpshell/SECURITY often mis-used] by people with not-so-good intentions. Or think about the [http://www.f-secure.com/v-descs/santy_a.shtml Santy-worm] which mis-used phpBB. Again there is a solution in the form of safe_mode, but lots of PHP scripts break if you enable this. For Python, Perl , or CGI-scripts there are no easy ways and you have to use wrappers or other tricks to chroot these.
== The solution ==
=== Minimal server ===
Create an VEx CTx with your favorite distro. Give it an internal IP-address in one of the ranges 10.0.0.0/8, 172.16.0.0/12 or 192.168.0.0/16. Then strip away all unnecessary init.d scripts so only the bare minimum is started. That means as a minimum syslogd and ssh so the account holder can upload his/her files through SCP/SFTP in his/her own minimal server. For this to work you need to set up [[Using NAT for VE container with private IPs|destination NAT on VE0CT0]] from high numbered ports to port 22 on the given private IP address:
<pre>
=== MySQL server ===
Most webhosting accounts use MySQL, but if you prefer another database server, go ahead. Create a new VEx CTx with a lot more resources and again an internal IP-address. Now configure the accounts. As an extra security measure you can use the internal IP-address as well. ==== MySQL socket sharing ==== You can also share the socket of an CTx running MySQL, which is alot faster than TCP/IP.e.g.:<pre>ln /var/lib/vz/private/101/var/run/mysqld/mysqld.sock /var/lib/vz/private/102/var/run/mysqld/mysqld.sock</pre>Inside of 102:<pre>$ mysql -u root -p -S /var/run/mysqld/mysqld.sockEnter password:Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 9 to server version: 5.0.32-Debian_7etch1-log</pre> ==== Refreshing links to MySQL socket ==== Sharing the MySQL socket works really well until the MySQL database is restarted or the container running MySQL is restarted. When this happens, the socket file is removed and recreated. In most cases, a different inode will be used, causing existing hard links to the mysql.sock file to no longer work. The solution is to relink these sockets.  There are more elegant solutions to this problem, but the following script is a decent hack that can be run via a cron job every minute or two. It will loop through all containers between START_CTID and STOP_CTID and make sure that the links point to the correct socket. If they do not, the link will be recreated. <pre>#!/bin/sh # Created by Tauren Mills (tauren at tauren dot com) 2007-11-15 #################################### Start of Configuration settings #################################### # Location of private containers:PRIVATE=/vz/private # Starting CT ID. CTIDs with this ID or greater will have mysql.sock link createdSTART_CTID=1001 # Stopping CT ID. CTIDs with this ID or less will have mysql.sock link createdSTOP_CTID=2000 # Shared Mysql CT ID:MYSQL_CTID=201 # Location of mysql socket fileMYSQL_SOCK_DIR=/var/lib/mysql # Mysql socket file nameMYSQL_SOCK=mysql.sock ################################## End of Configuration settings ################################## # Display output if quiet is 0QUIET=0 if [ $# -eq 1 -a "$1" = "--quiet" ]; then QUIET=1fi # Full path to socketMYSQL_SOCK_FILE=${PRIVATE}/${MYSQL_CTID}${MYSQL_SOCK_DIR}/${MYSQL_SOCK} [ $QUIET -eq 0 ] && echo[ $QUIET -eq 0 ] && echo "Relinking process starting..." # Get current location so we can set it back lateroldDirectory=`pwd` # Check to see if MySQL container socket existsif [ -S "${MYSQL_SOCK_FILE}" ]; then  # Get inode of MySQL container socket mysql_inode=`ls -i ${MYSQL_SOCK_FILE} | awk '{ print $1;}'`  # Search through containers cd $PRIVATE for i in * ; do # The current container to process veid=$i  # Check if container should be processed if [ $veid -ne $MYSQL_CTID -a $veid -ge $START_CTID -a $veid -le $STOP_CTID ]; then  # Get this container's socket vesock=${PRIVATE}/${veid}${MYSQL_SOCK_DIR}/${MYSQL_SOCK}  # Make sure folder exists mkdir -p ${PRIVATE}/${veid}${MYSQL_SOCK_DIR}  # Check to see if this container has a socket already if [ -S "${vesock}" ]; then # Get inode of this container socket ve_inode=`ls -i ${vesock} | awk '{ print $1;}'`  # Test if sockets are the same if [ $mysql_inode -eq $ve_inode ]; then # No action required [ $QUIET -eq 0 ] && echo "$veid VALID: socket ${vesock}" else # Remove existing file if any if [ -a "${vesock}" ]; then rm ${vesock} fi  # Create hardlink to mysql socket file ln ${MYSQL_SOCK_FILE} ${vesock}  [ $QUIET -eq 0 ] && echo "$veid FIXED: socket ${vesock}" fi else # Socket didn't exist or file wasn't a socket  # Remove existing file if any if [ -a "${vesock}" ]; then rm ${vesock} fi  # Create hardlink to mysql socket file ln ${MYSQL_SOCK_FILE} ${vesock}  [ $QUIET -eq 0 ] && echo "$veid FIXED: socket ${vesock}" fi else [ $QUIET -eq 0 ] && echo "$veid SKIPPED" fi doneelse [ $QUIET -eq 0 ] && echo "${MYSQL_SOCK_FILE} does not exist. Is MySQL running?"fi cd $oldDirectory [ $QUIET -eq 0 ] && echo "Relinking process complete."[ $QUIET -eq 0 ] && echo </pre> The following post on the OpenVZ forum has some other suggestions on how to deal with this issue:[http://forum.openvz.org/index.php?t=rview&goto=23305#msg_23305 Shared webhosting - problem with mysql socket]
=== Proxy webserver ===
Because we have only one public IP-address, we need an trick to access every minimal server based on the hostname in the HTTP request. For SSH we used different ports, but that is not an option for websites. Again we create an VEx CTx with an internal IP-address. On this server we install Lighttpd as well, because the proxying is very simple. If someone has an working example with Apache, please add. First we must forward port 80 to this server:
<pre>
You can map more names to the same IP-address if needed. The last step is to add mod_proxy to the server.modules section.
 
For apache add a VirtualHost directive
 
<pre>
<VirtualHost external-IP-address:80>
ServerName mydomainnameishere.com
RewriteEngine On
RewriteRule ^(.*)$ http://192.168.2.101$1 [P]
RewriteRule ^(.*)$ http://mydomainnameishere.com$1 [P]
</VirtualHost>
 
<VirtualHost external-IP-address:80>
ServerName mydomainnameishere.com
RewriteEngine On
RewriteRule ^(.*)$ http://192.168.2.101$1 [P]
RewriteRule ^(.*)$ http://www.mydomainnameishere.com$1 [P]
</VirtualHost>
</pre>
=== Other applications ===
Create for other applications as mail, make sure that the minimal servers use this one for sending mail from webpages, DNS etc. VEx CTx as needed. The resulting server is shown in the figure above. OpenVZ can easily be installed on most Dedicated Server Hosting Services
[[Category:HOWTO]]

Navigation menu