PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Subdomain-Service: Wie erstelle ich dynamisch viele Subdomains?

with 9 comments

Was eine Subdomain ist brauche ich ja wahrscheinlich nicht zu erzählen, dass es manchmal mehr Sinn machen kann lieber eine neue Subdomain als einen Unterordner anzulegen und wie das geht möchte ich hier zeigen.

Die Länge der folgenden Domains ist gleich, es ist also egal ob ich

http://domain.de/forum

oder

http://forum.domain.de

anlege. Es gibt jedoch einige technische Unterschiede. Sollte ich beispielsweise später das Forum auf einen eigenen Server umziehen wollen ist das mit der zweiten Möglichkeit einfacher. Des weiteren sind die Sessions durch die Subdomain getrennt, ich kann also im Forum nicht auf die Session-Daten der Hauptdomain zugreifen und andersrum. Sollte ich das doch wollen müßte ich

ini_set("session.cookie_domain", ".domain.de");

die Einstellung ändern, dann teilen sich alle Subdomains die Session-Daten.

Solange wir nur einige wenige Subdomains für Forum, Blog und Webseite erstellen möchten tun wir das normalerweise manuell direkt in den DNS-Einstellungen, und wir fügen im Apache einen entsprechenden VirtualHost Eintrag hinzu, beispielsweise

NameVirtualHost *:80

<VirtualHost *:80>
    DocumentRoot /www/forum
    ServerName forum.domain.de
    ...
</VirtualHost>

<VirtualHost *:80>
    DocumentRoot /www/blog
    ServerName blog.domain.de
    ...
</VirtualHost>

Ich habe nun die Domain ipv6only.de, unter der ich einen Subdomain-Dienst anbieten möchte für Webseiten, die nur via IPv6 zu erreichen sind. Dabei gibt es verschiedene Möglichkeiten, wobei ich vorerst mit einer Weiterleitung anfangen möchte und eventuell einer „Frameweiterleitung“. Jemand kann sich also registrieren, beispielsweise die Subdomain simon.ipv6only.de , und dann diese Subdomain weiterleiten auf die nicht so gut merkbare IPv6-Adresse http://[2001:0db8:85a3:08d3:1319:8a2e:0370]/ oder zum Beispiel auf http://hosterxy.com/user/simon245/

Wie geht das nun? Wir richten als erstes einen Wildcard-Eintrag im DNS ein, hier die 6. Zeile mit dem Sternchen (für IPv6 wäre es dann ein AAAA Eintrag):

Dadurch werden schonmal alle Subdomains auf meinen Webserver 85.214.28.26 geleitet. Dort erstelle ich dann auch einen entsprechenden Wildcard-Eintrag im Apache:

<VirtualHost 85.214.28.26:80>
    ServerName ipv6only.de
    ServerAlias *.ipv6only.de
    DocumentRoot /www/ipv6only
 </VirtualHost>

Nun landen also alle Subdomains im Verzeichnis /www/ipv6only . Soweit so gut, nun können wir mit Hilfe von PHP  für jede Subdomain die entsprechende Weiterleitung herausfinden, beispielsweise aus einer Datenbank.

<?
$domain = strtolower($_SERVER['SERVER_NAME']);

// in $subdomain we want to have "simon" or "forum.simon"
$position = strrpos($domain, '.ipv6only.de');
$subdomain = substr($domain, 0, $position);

// get the target url for the subdomain
$row = $dbmodel->fetchRow(array('subdomain' => $subdomain));

header("Location: ".$row['TargetUrl'], true, 301); ?>
You are being redirected to <a href="<?=$row['TargetUrl']?>"><?=$row['TargetUrl']?></a>

Bei einer Frameweiterleitung bleibt die *.ipv6only.de Adresse in der URL stehen, da die Zielseite nur in einem Frame angezeigt wird. Das geht beispielsweise so:

<?
$domain = strtolower($_SERVER['SERVER_NAME']);

// in $subdomain we want to have "simon" or "forum.simon"
$position = strrpos($domain, '.ipv6only.de');
$subdomain = substr($domain, 0, $position);

// get the target url for the subdomain
$row = $dbmodel->fetchRow(array('subdomain' => $subdomain));

if ($row['Type'] == 'Frame') { ?>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
    <html>
        <head>
            <title><?=$domain ?></title>
        </head>
        <frameset>
          <frame src="<?=$row['TargetUrl']?>">
        </frameset>
    </html>
<?
} elseif ($row['Type'] == 'Forward') {
    header("Location: ".$row['TargetUrl'], true, 301); ?>
    You are being redirected to <a href="<?=$row['TargetUrl']?>"><?=$row['TargetUrl']?></a>
<?
}

Anstatt dies alles mit PHP zu machen könnte man sich auch eine Umsetzung mit mod_rewrite vorstellen, allerdings ist man damit nicht so flexibel. Für jede Weiterleitung würde also eine entsprechende Regel in der .htaccess stehen:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^simon\.ipv6only\.de$ [NC]
RewriteRule ^(.*) http://hosterxy.com/user/simon245 [R=301,L]

Die .htaccess-Datei würde auch recht groß bei vielen Tausend Einträgen, das Editieren würde komplexer (wenn jemand die Ziel-URL ändert müßte die .htaccess Datei neu generiert werden), und spätestens bei der „Frameweiterleitung“ wäre PHP auf jeden Fall nötig.

Wie hättet ihr es gemacht, hat jemand bereits Erfahrungen mit solchen Diensten? Bei der Recherche bin ich auch auf einige „Subdomain-Service-Scripte“ gestossen, die man für 19€ oder 99€ kaufen kann. Weiß jemand was genau diese Scripte bieten außer ein paar Formulare zum Administrieren der Datenbank (Registrierung, Weiterleitungstyp, Ziel-URL etc.) und der oben gezeigten Funktionalität?

Written by Michael Kliewe

Januar 4th, 2011 at 10:09 am

9 Responses to 'Subdomain-Service: Wie erstelle ich dynamisch viele Subdomains?'

Subscribe to comments with RSS or TrackBack to 'Subdomain-Service: Wie erstelle ich dynamisch viele Subdomains?'.

  1. Hallo
    geht das nicht einfacher?

    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www.ipv6only.de [NC]
    RewriteCond %{HTTP_HOST} ^(www.)?([^.]+).ipv6only.de [NC]
    RewriteRule ^$ /user/%2/ [L]

    so irgendwie sollte es mit einem Eintrag möglich sein eifnach alle subdomains an /user/username weiterzuleiten.

    Kadir

    4 Jan 11 at 10:23

  2. upps,
    an unterschiedliche adressen kann so natürlich nicht weitergeleitet werden.

    Kadir

    4 Jan 11 at 10:28

  3. Wir bieten einen Service-Bereich an, in dem ein ähnlicher Mechanismus genutzt wird. Alle Subdomains werden über den von Dir beschriebenen CatchAll-Mechanismus auf ein PHP-Skript geleitet, dieses liefert dann die unterschiedlichen Inhalte aus. Die Inhalte selbst sind in unserem Fall in einem extra Verzeichnis in Unterverzeichnissen organisiert. Für eine neue Subdomain ist so nur das Anlegen eines Verzeichnisses notwendig. Erkennung und Fehlerbehandlung laufen über das PHP-Skript und kommen Deiner Datenbank recht nahe.

    Sebastian

    4 Jan 11 at 11:53

  4. ich mag mich irren, aber ist das nicht nur für Leute von Vorteil, die keine eigene Domain, oder zumindest keine wirkliche Kontrolle darüber haben?

    Für den eigenen gebrauch halte ich ein Script, dass die einträge in Apache automatisch hinzufügt/streicht für sinnvoller.

    Flyingmana

    4 Jan 11 at 13:07

  5. @Flyingmana:

    Für uns ist es sehr praktisch, eine neue Subdomain einfach mit dem Anlegen eines Verzeichnisses zu erzeugen. Das geht z.B. auch per FTP mit eingeschränkten Rechten, das PHP-Skript macht den Rest.
    Ursprünglich hatte ich auch an eine Modifikation der Apache-Konfiguration gedacht, das ist aber imho wesentlich aufwendiger ohne einen wirklichen Mehrwert zu bieten. In unserem Anwendungsfall stehen Einfachheit und Sicherheit im Vordergrund.

    Sebastian

    4 Jan 11 at 13:15

  6. Achso, mein Fehler.

    Ich vergesse immer die FTP nutzer. (die ihr Passwort im Klartext durch die Leitung schicken.^^ Der Seitenhieb musste jetzt sein, nachdem du „Sicherheit“ erwähnt hast)

    Größere Projekte stehen sowieso in nem VCS bei mir.
    Und kleinere Dinge zum ausprobieren kommen auf die Testmaschine, auf die auch nur via SSH/SFTP zugegriffen wird.
    Ja gut, mit nem kleinen cron job würde sich das auch leicht bewerkstelligen lassen, dass auf neue ordner in nem bestimmten verzeichnis ausschau gehalten wird, und mit deren auftauchen/verschwinden neue Seiten in der Apache.conf hinzugefügt/entfernt werden.

    Das mit der Sicherheit wurmt mich immernoch. Hört sich ja fast wie so eine typische Werbephrase an.
    Sicherheit wo für bzw. wo vor braucht ihr denn in eurem Anwendungsfall?
    Und das selbe mit der Einfachheit. Einfachheit in der Anwendung? In der Umsetzung wohl eher nicht, da ein „proxy“ ja dann eher eine zu vermeidende zusätzliche Fehlerquelle darstellt.
    Ich stell mir grad vor, was passieren könnte, wenn jemand schafft über den subdomain string unerwartete Verzeichnisse aufzurufen in dem er zb. ../ oder ~ verwendet.
    Das ist natürlich nur phantasterei und zu simple, um das zu vergessen. Es ist aber trotzdem eine weitere mögliche Angriffsstelle, wenn man das versucht dynamisch zu behandeln.

    Flyingmana

    5 Jan 11 at 01:32

  7. @Flyingmana:

    Ich stimme Dir fast total zu, das was ich geschrieben hatte war nur eine Vereinfachung. Genaugenommen sind unsere Projekte auch in einem SVN-Repository abgelegt und werden per SSH auf dem Server ausgecheckt. Die Sicherheit wird durch das PHP Skript in der Form hergestellt, als dass die Zugriffsprüfung nur an dieser einen Stelle erfolgt und dort auch bestimmte Einstellungen gesetzt werden. Das muss dann nicht für jede Subdomain getan werden.

    Die Einfachheit ergibt sich dann, wenn eine neue Subdomain gebraucht wird. Das ist super einfach. Das PHP Skript zu erstellen und vor allem abzusichern ist kompliziert, dass muss aber nur einmal gemacht werden und kann in einem Team von denjenigen übernommen werden, die sich mit sowas auskennen und auch die von Dir beschriebenen Fehlerquellen prüfen.

    Ich bin sehr zufrieden mit der Lösung, und bekomme jetzt auch keine Bauchschmerzen, wenn der neue Kollege eine neue Subdomain anlegt – er kann einfach nicht viel falsch machen.

    Sebastian

    6 Jan 11 at 14:40

  8. […] Subdomain-Service: Wie erstelle ich dynamisch viele Subdomains? […]

  9. Vielen Dank für den Beitrag!

    Christian Hünniger

    15 Jan 11 at 23:45

Leave a Reply

You can add images to your comment by clicking here.