SSL-Version testen

Das verwenden einer SSL-Version kleiner als SSLv3 wird heutzutage oft als Sicherheitsrisiko angesehen und ein administrator würde manchmal gerne prüfen ob seine server per SSLv2 noch erreichbar sind.

Dies geht unter Linux relativ einfach mit dem OpenSSL-Kommando:

openssl s_client -connect www.domain.tld:443 -ssl2

Kommt dann dabei so was raus wie:

CONNECTED(00000003)
7623:error:1407F0E5:SSL routines:SSL2_WRITE:ssl handshake failure:s2_pkt.c:428:

Kann davon ausgegangen werden, dass SSLv2 vom server nicht akzeptiert wird.

Script-Pfad ermitteln

Um in einem script den Pfad zum Verzeichnis von dem das Script aufgerufen wird gibt es diese Funktion:

<span class="keys"> ${BASH_VERSINFO[0]} -le 2 </span> && echo 'The BASH_SOURCE array variable is only available for Bash 3.0 and higher!' && exit 1
if [ "${BASH_SOURCE[0]}" != "${0}" ]; then
  # echo "script ${BASH_SOURCE[0]} is running sourced ..."
 
  SCRIPT_PATH="$(cd $(dirname "${BASH_SOURCE[0]}"); pwd -P)"
else
 
  # echo "script ${0} is NOT running sourced ..."
  SCRIPT_PATH="$(cd $(dirname "${0}"); pwd -P)"
fi

Falls man nun Beispielsweise ein script in /home/user/bin/test.sh hat und die obige Funktion in diesem Script aufruft zeigt $SCRIPT_PATH immer auf: /home/user/bin, egal ob man dieses Script im bin-Verzeichnis aufruft (./test.sh) oder absolut (/home/user/bin/test.sh).

Dies ist besonders nützlich, wenn man innerhalb des scriptes weitere scripts im selben Verzeichnis wie das script aufruft und dies nicht mit absoluter Pfadangabe machen will (da sich das script-Verzeichnis verschieben könnte).

RAID/LVM nachträglich hinzufügen

Situation

Man hat bereits einen Linux Server aufgesetzt der gut läuft. Nun hat man dem eine zweite Platte hinzugefügt und möchte ein RAID/LVM System daraus machen, aber ohne das aufwändige neu installieren/konfigurieren des Systems.

Dies ist mit etwas know how relativ leicht möglich, indem man zuerst die zweite (unbenutzte) Festplatte entsprechend als sog. "degraded raid1 array" definiert, dann die Files von der ersten Platte rüber kopiert, von dieser bootet und letztendlich diese dann dem RAID wieder dazu fügt.

[stextbox id=“note“ caption=“Hinweis“]Der folgende Artikel zeigt wie es mit einem CentOS System geht; der Vorgang dürfte sich aber auch für andere Systeme nahezu nicht unterscheiden.[/stextbox]

Installieren der Komponenten

Als erstes sollte man in der Kernel-Konfiguration überprüfen ob RAID einkompilliert ist, dies dürfte aber bei fast allen neueren Kernels der Fall sein:

-> Device Drivers
   -> Multi-device support (RAID and LVM)
      -> Multiple devices driver support (RAID and LVM) (MD [=y])
         -> RAID support (BLK_DEV_MD [=y])
            -> RAID-1 (mirroring) mode

Dann installieren wir mdadm und lvm2:

yum install mdadm lvm2 rsync

Konfiguration

Vorbereiten der neuen Disk

Nun kann die neue Disk (von der aktuell laufenden sollte man noch die Finger lassen!) mit fdisk gemäss den eigenen wünschen partitioniert werden; in diesem Beispiel haben wir folgende aufteilung:

Device          Flags       Part Type   FS Type                   Label     Size (MB)
/dev/sdb1       boot      Primary     Linux raid autodetect               128
/dev/sdb2                   Primary     Linux raid autodetect               (rest)

Ist alles erledigt erstellen wir daraus ein degraded array mit den oben definierten Partitionen:

mdadm --create /dev/md1 --level=1 --raid-devices=2 missing /dev/sdb1
mdadm --create /dev/md2 --level=1 --raid-devices=2 missing /dev/sdb2
mdadm --detail --scan >> /etc/mdadm.conf

Und optional nun noch der LVM drüber:

vgscan
vgchange -a y
pvcreate /dev/md2
vgcreate rootvg /dev/md2
lvcreate -L1G -nroot_lv rootvg
lvcreate -L5G -nusr_lv rootvg
lvcreate -L5G -nhome_lv rootvg
lvcreate -L7G -nvar_lv rootvg
lvcreate -L2G -ntmp_lv rootvg
lvcreate -L512M -nswap_lv rootvg

Darauf können nun die filesysteme erstellt werden:

mke2fs /dev/md1
mke2fs -j /dev/rootvg/root_lv
mke2fs -j /dev/rootvg/home_lv
mke2fs /dev/rootvg/tmp_lv
mke2fs -j /dev/rootvg/usr_lv
mke2fs -j /dev/rootvg/var_lv
mkswap /dev/rootvg/swap_lv

Das ganze können wir jetzt mounten…

mkdir -p /mnt/new
mount /dev/rootvg/root_lv /mnt/new
cd /mnt/new
mkdir boot home usr opt var tmp
mount /dev/md1 /mnt/new/boot
mount /dev/rootvg/usr_lv /mnt/new/usr
mount /dev/rootvg/home_lv /mnt/new/home
mount /dev/rootvg/tmp_lv /mnt/new/tmp
mount /dev/rootvg/var_lv /mnt/new/var
chmod 1777 /mnt/new/tmp

…und die Daten rüber kopieren:

rsync -ahvx / /mnt/new/
rsync -ahv /dev/* /mnt/new/dev/
rsync -ahv /boot/ /mnt/new/boot/

Als nächster Schritt muss noch die Datei: /mnt/new/etc/fstab angepasst werden:

# <fs>                   <mountpoint>            <type> <opts>          <dump/pass>
/dev/md1                 /boot                   ext2   noauto,noatime  1 2
/dev/rootvg/root_lv   /                       ext3   noatime         0 1
/dev/rootvg/swap_lv  none                    swap   sw,pri=1        0 0
/dev/rootvg/usr_lv       /usr                    ext3   noatime         1 2
/dev/rootvg/home_lv      /home                   ext3   noatime         1 2
/dev/rootvg/tmp_lv       /tmp                    ext2   noatime         1 2
/dev/rootvg/var_lv       /var                    ext3   noatime         1 2
shm                      /dev/shm               tmpfs   nodev,nosuid,noexec    0

Als letztes noch die Datei /mnt/new/boot/grub/menu.lst bearbeiten, den ersten (standard) Eintrag nach zuoberst kopieren und "root=/dev/sda2" in: "root=/dev/rootvg/root_lv" ändern.
Dies müsste dann etwa so aussehen:

title CentOS RAID
root (hd0,0)
kernel /vmlinuz ro root=/dev/rootvg/root_lv

Testen

Nun gehts ans testen, ob die Maschine vom RAID booten- und LVM Partitionen mounten kann, bevor wir die Daten auf /dev/sda endgültig zerstören. – Bisher haben wir noch gar nichts "zerstört".

Dazu erstellen wir die folgenden Verzeichnisse: /mnt/md1 und /mnt/tmp_lv}:

mkdir -p /mnt/{md1,tmp_lv}

Und fügen den folgenden Eintrag in /etc/fstab:

/dev/md1                 /mnt/md1                       ext2   noatime         0 1
/dev/rootvg/tmp_lv       /mnt/tmp_lv                    ext2   noatime         1 2

Nun starten wir das System neu und überprüfen ob wir den Verzeichnisinhalt von diesen zwei Verzeichnissen sehen können.

[stextbox id=“warning“ caption=“Wichtig“]Fahre NICHT weiter fort, bevor du diesen Schritt erfolgreich beendet hast![/stextbox]

Editiere nun /boot/grub/menu.lst, kopiere den ersten (standard) Eintrag nach zuoberst und ändere "root=/dev/sda2" in: "root=/dev/rootvg/root_lv".
Dies müsste dann etwa so aussehen:

title CentOS RAID
root (hd0,0)
kernel /vmlinuz ro root=/dev/rootvg/root_lv

Starte das System neu.

Migration

Nun migrieren wir die erste Disk.

Erstelle mit fdisk nun genau das selbe layout wie mit /dev/sdb.
Nun aktiveren wir das SWAP erstellen das array und warten bis es fertig ist:

mdadm --add /dev/md1 /dev/sda1
mdadm --add /dev/md2 /dev/sda2
 
watch -n 1 "cat /proc/mdstat"

Nun müssen wir nur noch grub auf die beiden Disks kopieren:

grub
Probing devices to guess BIOS drives. This may take a long time.
grub> root (hd0,0)
 Filesystem type is ext2fs, partition type 0xfd
grub> setup (hd0)
 Checking if "/boot/grub/stage1" exists... yes
 Checking if "/boot/grub/stage2" exists... yes
 Checking if "/boot/grub/e2fs_stage1_5" exists... yes
 Running "embed /boot/grub/e2fs_stage1_5 (hd0)"...  16 sectors are embedded.
succeeded
 Running "install /boot/grub/stage1 (hd0) (hd0)1+16 p (hd0,0)/boot/grub/stage2 /boot
grub/menu.lst"... succeeded
Done.
grub> root (hd1,0)
 Filesystem type is ext2fs, partition type 0xfd
grub> setup (hd1)
grub> quit

Starte nun das System noch ein letztes mal neu, prüfe ob es gut hochkommt und dann mit df -h die Partitionen.

Mail mit attachments senden

Einfache mails kann man von der Linux Shell ganz einfach mittels:

echo "message body" | mail -s "subject" user@example.org

senden.

Schwieriger wirds bei attachments, da diese jeweils MIME-codiert werden müssen um beim Empfänger richtig angezeigt zu werden. – Zwar könnte man die files mittels mimeencode vor dem senden codieren, einfacher gehts jedoch mit dem Kommandozeilen tool "mutt", welches ggf. noch installiert werden muss:

mutt -s "subject" user.name@example.org -a /pfad/zum/file < /dev/null

Anstatt /dev/null kann man natürlich auch ne textdatei angeben, die dann als message body eingefügt wird.

Einer Partition den Laufwerksbuchstaben B: zuweisen

Windows XP gesteht Partitionen nur Laufwerksbuchstaben zwischen C und Z zu. Wenn man eine Partition auf B legen möchten, muss man etwas tricksen.

Um den Buchstaben zu ändern, öffnet man eine Kommandozeile (Start > Ausführen > cmd > OK) und tippt mountvol ein. Das Tool zeigt nun alle Geräte und den entsprechenden Mountpunkt (Laufwerksbuchstaben) an.

Nun kopiert man die Volume-ID des zu bearbeitenden Laufwerks (zum Beispiel {5ce033e0-a1a3-11db-b93c-806d6172696f}) und gibt anschliessend

mountvol Z: /D

ein (wobei Z für den zu ändernden Laufwerksbuchstaben steht). Damit unmountet man die Partition.

Letztendlich muss man das Volume wieder als B: einhängen. Dazu gibt man mountvol B: ?Volume{VOLUME-ID} ein. Wobei VOLUME-ID für die oben notierte ID des Gerätes steht:

mountvol B: ?Volume{5ce033e0-a1a3-11db-b93c-806d6172696f}

Nun sollte die Partition im Explorer oder Arbeitsplatz an der neuen Stelle mit der neuen Kennung stehen. Um diese Schritte rückgängig zu machen kann man die Datenträgerverwaltung verwenden oder wieder das Kommandozeilentool bemühen.

h1. Quellen
http://www.computerleben.net/artikel/Einer_Partition_B:_zuweisen-251.html

Benutzte User/Gruppen finden

Eine Standard Linux Installation kommt in der Regel mit 10-20 "Standard User Accounts", etwa "games" oder "news". – Häufig braucht man diese jedoch gar nicht und wenn man sein System absichert ist das sogar hinderlich.

Mit folgender Shell-Zeile kann man deswegen alle Benutzer auflisten lassen denen irgendwo auf dem System Files gehören; alle die NICHT aufgelistet sind können gefahrlos gelöscht werden:

cut -f 1 -d : /etc/passwd | while read i; do find / -user "$i" | grep -q . && echo "$i"; done 2> /dev/null

Und das selbe geht natürlich auch für die Benutzergruppen:

cut -f 1 -d : /etc/group | while read i; do find / -group "$i" | grep -q . && echo "$i"; done 2> /dev/null

vmware web-konsole stürzt nach CentOS-Upgrade ab

[stextbox id=“warning“ caption=“Achtung“]Ab CentOS 5.6 ist das Problem mit der glibc zwar wieder behoben; doch dann stürzt die vmware-konsole ab (vmware-hostd mit einem „Segemnation fault“), wenn der hack aktiv ist!

Um das Problem dann wieder zu lösen muss man lediglich in /usr/sbin/vmware-hostd die zweitletzte Zeile

export LD_LIBRARY_PATH=/usr/lib/vmware/lib/libc.so.6:$LD_LIBRARY_PATH

auskommentieren oder löschen.

Diese Beschreibung bleibt deshalb nur noch als Referenz hier und für solche welche den Hack früher schon mal gemacht hatten. – Falls der Hack noch nicht ausgeführt wurde, sollte man ab jetzt gleich auf CentOS 5.6 upgraden.[/stextbox]

Nach dem upgrade von CentOS 5.3 auf 5.4 oder eine höhere Version stürzt die vmware web-konsole mit einem "HTTP error code" ab.

Grund ist ein bug in vmware, der mit der aktuellen glibc nicht zurecht kommt.

Glücklicherweise lässt sich dies aber sehr einfach lösen, indem man die alte glibc herunter lädt und diese mit vmware verlinkt.

Folgendes script löst das Problem automatisch:

#!/bin/bash
###########################################
# This may help using the vmware-server2  #
# on a CentOS 5.4 x86_64 Host.            #
# There is a problem with the the libc    #
# More informations:                      #
# <a href="http://bugs.centos.org/view.php?id=3884" target="blank">http://bugs.centos.org/view.php?id=3884</a> #
#-----------------------------------------#
# Version 0.1                             #
# This script will get the 'old' libc     #
# from the CentOS 5.3 repositories and    #
# configures vmware-server2 to use this   #
# The original libc (for the 5.4-system)  #
# will not be replaced or touched.        #
#-----------------------------------------#
# License: Do with the code whatever you  #
# want. This came without any warrenty.   #
###########################################
 
LIBC_DIR="/usr/lib/vmware/lib/libc.so.6"
TEMP_DIR="/tmp/vmw_glibc"
VMWARE_CONFIGFILE="/usr/sbin/vmware-hostd"
VMWARE_CONFIGFILE_BAK=$VMWARE_CONFIGFILE.bak
 
# Checking for root
if <span class="keys"> $EUID -ne 0 </span>; then
    echo "This script must be run as root"
    exit 1
fi
 
# We test for the commands  we need:
echo "Looking for some commands I need..."
which wget
if [ $? != 0 ]; then
    echo "I can't find wget but need it to download the files. Please install."
fi
which rpm2cpio
if [ $? != 0 ]; then
    echo "I can't find rpm2cpio but need it to extract Files from a .rpm-file. Please install."
fi
 
# Creating a directory for the 'old' glibc
mkdir -p $LIBC_DIR
if [ $? != 0 ]; then
    echo "Can't create directory $LIBC_DIR"
    exit 2
fi
 
# Removing and creating a temporary directory for the rpm,
# downloading it, extracting the old glibc and copy
# the them to our new directory
rm -rf $TEMP_DIR
mkdir -p $TEMP_DIR
if [ $? != 0 ]; then
    echo "Can't create directory $TEMP_DIR"
    exit 2
fi
cd $TEMP_DIR
wget <a href="http://vault.centos.org/5.3/os/x86_64/CentOS/glibc-2.5-34.x86_64.rpm" target="blank">http://vault.centos.org/5.3/os/x86_64/CentOS/glibc-2.5-34.x86_64.rpm</a>
if [ $? != 0 ]; then
    echo "Something was wrong while downloading"
    exit 2
fi
rpm2cpio glibc-2.5-34.x86_64.rpm | cpio -ivd
mv lib64/libc-2.5.so $LIBC_DIR/libc.so.6
if [ $? != 0 ]; then
    echo "Can't move the libc into directory $LIBC_DIR"
    echo "Removing temporary files..."
    echo -rf $TEMP_DIR
    exit 2
fi
echo "The file libc-2.5.so from the centOS 5.3 rep. was saved in: $LIBC_DIR as libc.so.6"
 
echo "Removing temporary files..."
rm -rf $TEMP_DIR
 
# Now we editing the start-config of the vmware-server
echo "I must change $VMWARE_CONFIGFILE now, you will find a backup in $VMWARE_CONFIGFILE_BAK"
mv $VMWARE_CONFIGFILE $VMWARE_CONFIGFILE_BAK
cat $VMWARE_CONFIGFILE_BAK | grep -v 'eval exec "$DEBUG_CMD" "$binary" "$@"' > $VMWARE_CONFIGFILE
echo export LD_LIBRARY_PATH=$LIBC_DIR/libc.so.6:'$LD_LIBRARY_PATH' >> $VMWARE_CONFIGFILE
echo '' >> $VMWARE_CONFIGFILE
echo 'eval exec "$DEBUG_CMD" "$binary" "$@"' >> $VMWARE_CONFIGFILE
 
# Ensuring the script is executable
chmod 555 $VMWARE_CONFIGFILE
 
echo "Everything is done, please restart your vmware-server2"

Troubleshooting

Nach dem ausführen des scriptes sollte überprüft werden ob das file: /usr/sbin/vmware-hostd ausführbar ist.

Weiter öffnet man am besten mal: /usr/sbin/vmware-hostd und prüft die unterste export Zeile; dabei muss man darauf achten, dass LD_LIBRARY_PATH auf das Verzeichnis zeigt wo die "libc.so.6" liegt und nicht das File selbst!

So ist es falsch:

export LD_LIBRARY_PATH=/usr/lib/vmware/lib/libc.so.6/libc.so.6:$LD_LIBRARY_PATH

So sieht die korrekte export-Zeile aus:

export LD_LIBRARY_PATH=/usr/lib/vmware/lib/libc.so.6:$LD_LIBRARY_PATH

(Dies wird manchmal vom script durcheinander gebracht)

Nach einem vmware-neustart sollte sich dann die Konsole wieder öffnen lassen.

[stextbox id=“note“ caption=“Hinweis“]Seit der Firefox-Version 3.6 lässt sich die vmware Web-Konsole nicht mehr korrekt öffnen; dies ist jedoch nicht mit diesem bug relevant, sondern ein Bug im Firefox-Plugin.[/stextbox]

Related Links

OpenVPN benutzt zufällige Ports beim verbinden

Bei OpenVPN kann es vorkommen, dass jedes mal wenn sich ein Client reconnected versucht er sich auf einen neuen Port; aufsteigend ab 2048 zu Verbinden, d.h.: 2048,2049,2050,2051,usw., was natürlich die Firewall blockt. Die Meldungen im log sehen dann so aus:

openvpn[1388]: MULTI: multi_create_instance called
openvpn[1388]: XX.XX.XX.XX:<B>2056</B> Re-using SSL/TLS context
openvpn[1388]: XX.XX.XX.XX:2056 LZO compression initialized
openvpn[1388]: XX.XX.XX.XX:2056 Control Channel MTU parms [ L:1542 D:138 EF:38 EB:0 ET:0 EL:0 ]
openvpn[1388]: XX.XX.XX.XX:2056 Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:135 ET:0 EL:0 AF:3/1 ]
openvpn[1388]: XX.XX.XX.XX:2056 Local Options hash (VER=V4): '530fdded'
openvpn[1388]: XX.XX.XX.XX:2056 Expected Remote Options hash (VER=V4): '41690919'
openvpn[1388]: XX.XX.XX.XX:2056 TLS: Initial packet from XX.XX.XX.XX:<B>2056</B>, sid=355db726 61057e4d
openvpn[1388]: XX.XX.XX.XX:2056 write UDPv4 []: Operation not permitted (code=1)
openvpn[1388]: XX.XX.XX.XX:2056 write UDPv4 []: Operation not permitted (code=1)
openvpn[1388]: XX.XX.XX.XX:2056 write UDPv4 []: Operation not permitted (code=1)
openvpn[1388]: XX.XX.XX.XX:2056 write UDPv4 []: Operation not permitted (code=1)
openvpn[1388]: XX.XX.XX.XX:2056 write UDPv4 []: Operation not permitted (code=1)
openvpn[1388]: XX.XX.XX.XX:2056 write UDPv4 []: Operation not permitted (code=1)
openvpn[1388]: XX.XX.XX.XX:2056 TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
openvpn[1388]: XX.XX.XX.XX:2056 TLS Error: TLS handshake failed

Entsprechend auf den client:

daemon.notice openvpn(custom_config)[995]: SIGUSR1[soft,tls-error] received, process restarting
daemon.notice openvpn(custom_config)[995]: Restart pause, 2 second(s)
daemon.notice openvpn(custom_config)[995]: Re-using SSL/TLS context
daemon.notice openvpn(custom_config)[995]: LZO compression initialized
daemon.notice openvpn(custom_config)[995]: Control Channel MTU parms [ L:1542 D:138 EF:38 EB:0 ET:0 EL:0 ]
daemon.notice openvpn(custom_config)[995]: Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:135 ET:0 EL:0 AF:3/1 ]
daemon.notice openvpn(custom_config)[995]: Local Options hash (VER=V4): '41690919'
daemon.notice openvpn(custom_config)[995]: Expected Remote Options hash (VER=V4): '530fdded'
daemon.notice openvpn(custom_config)[995]: UDPv4 link local: [undef]
daemon.notice openvpn(custom_config)[995]: UDPv4 link remote: 178.83.21.126:1194
daemon.err openvpn(custom_config)[995]: TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
daemon.err openvpn(custom_config)[995]: TLS Error: TLS handshake failed
daemon.notice openvpn(custom_config)[995]: TCP/UDP: Closing socket

Schuld daran ist der nobind-Parameter, der manchmal in OpenVPN Dokumentationen bei Verbindungen mit dynamischer IP-Adresse empfohlen wird. – Denn ist dieser aktiviert bindet sich OpenVPN zwar nicht mehr an die IP-Adresse, aber eben auch nicht mehr an einen Port, was sehr mühsam ist.
Das herausnehmen des nobind-parameters löst dieses Problem dann.

postfix-mysql: queue file write error / Temporary lookup failure

Nachdem ich mein Postfix für die Verwendung mit mysql Tabellen konfiguriert hatte, bekam ich auf einmal beinahe täglich mails, die den Text: "451 4.3.0 Error: queue file write error" und/oder: "Temporary lookup failure" enthielten:

Transcript of session follows.
 
 Out: 220 mail.domain.tld ESMTP Postfix
 In:  EHLO [X.X.X.X]
 Out: 250-mail.domain.tld
 Out: 250-PIPELINING
 Out: 250-SIZE 10240000
 Out: 250-VRFY
 Out: 250-ETRN
 Out: 250-AUTH PLAIN LOGIN
 Out: 250-AUTH=PLAIN LOGIN
 Out: 250-ENHANCEDSTATUSCODES
 Out: 250-8BITMIME
 Out: 250 DSN
 In:  AUTH PLAIN XXXXXXXXXXXXXXXXXXXXXXX
 Out: 235 2.0.0 Authentication successful
 In:  MAIL FROM:<sender@example.org> SIZE=1037
 Out: 250 2.1.0 Ok
 In:  RCPT TO:<empfaenger@example.org>
 Out: 250 2.1.5 Ok
 In:  DATA
 Out: 354 End data with <CR><LF>.<CR><LF>
 Out: 451 4.3.0 Error: queue file write error
 
Session aborted, reason: lost connection

Zwar schien alles zu funktionieren und die mails kamen auch immer noch rein, ich wollte jedoch der Meldung nachgehen.

Im maillog wurde ich dann fündig, denn folgende Fehlermeldung tauchte ziemlich oft auf:

warning: mysql query failed: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=

Dies kam davon, weil ich die postfix Datenbank noch auf dem alten Server angelegt hatte und auf dem der Zeichensatz: latin1_swedish_ci standardmässig eingestellt war, beim neuen Server war jedoch UTF8 standard.

Das Problem kann man dann lösen, wenn man die Postfix Datenbank wie folgt konvertiert:

Login auf mysql:

mysql -uroot -p

dann für jede Tabelle:

ALTER TABLE tbl_name CHARACTER SET utf8 COLLATE utf8_general_ci;

und für jedes Textfeld:

ALTER TABLE tbl_name MODIFY email varchar(255) CHARACTER SET utf8;

Quelle