Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Couper une connexion TCP qui ne m'appartient pas

13 réponses
Avatar
nospam
Bonjour,

J'essaye de faire un programme qui coupe la connexion tcp entre ma
machine et n'importe quelle autre, en me basant sur l'idée du "double
RST" du créateur de "TCP cutter" (http://www.lowth.com/cutter)
Le problème de base etant que n'etant pas "au milieu" de la session,
il faut s'envoyer un RST à soi même en usurpant l'identité de la
machine distante.

Mon problème est le suivant :

2 machines : Un EXPEDITEUR (qui veut mettre fin à la connection TCP
qu'il a avec la CIBLE) et la CIBLE
EXPEDITEUR : 192.168.1.3
CIBLE : xx.xx.xx.xx.

et voila le pb :
15:11:59.369482 192.168.1.3.33254 > xx.xx.xx.xx.imaps: F [tcp sum ok]
0:0(0) win 0 (DF) (ttl 253, id 0, len 40)
15:11:59.372507 xx.xx.xx.xx.imaps > 192.168.1.3.33254: . [tcp sum ok]
1589:1589(0) ack 461 win 6432 <nop,nop,timestamp 163410425 1403391>
(DF) (ttl 62, id 40208, len 52)
15:11:59.373290 192.168.1.3.33254 > xx.xx.xx.xx.imaps: R [tcp sum ok]
2365895080:2365895080(0) win 0 (DF) (ttl 253, id 0, len 40)
15:11:59.373699 xx.xx.xx.xx.imaps > 192.168.1.3.33254: R [tcp sum ok]
3960647341:3960647341(0) win 0 (DF) (ttl 253, id 0, len 40)
15:12:06.073374 192.168.1.3.33254 > xx.xx.xx.xx.imaps: P [tcp sum ok]
461:490(29) ack 1589 win 8870 <nop,nop,timestamp 1406204 163410425>
(DF) (ttl 64, id 39495, len 81)
15:12:06.076633 xx.xx.xx.xx.imaps > 192.168.1.3.33254: R [tcp sum ok]
3960647341:3960647341(0) win 0 (DF) (ttl 253, id 0, len 40)

decryptage ;)

1) envoi FIN pour trouver numéro de sequence :
15:11:59.369482 192.168.1.3.33254 > xx.xx.xx.xx.imaps: F [tcp sum ok]
0:0(0) win 0 (DF) (ttl 253, id 0, len 40)

2) reponse de la cible : ACK avec bon numéro de sequence :
15:11:59.372507 xx.xx.xx.xx.imaps > 192.168.1.3.33254: . [tcp sum ok]
1589:1589(0) ack 461 win 6432 <nop,nop,timestamp 163410425 1403391>
(DF) (ttl 62, id 40208, len 52)

3) envoi Reset à la cible (avec le bon numéro de sequence)
conséquence, la cible ferme le socket de son coté:
15:11:59.373290 192.168.1.3.33254 > xx.xx.xx.xx.imaps: R [tcp sum ok]
2365895080:2365895080(0) win 0 (DF) (ttl 253, id 0, len 40)

4) envoi FAUX reset à l'expéditeur (c'est l'expéditeur qui a forgé ce
packet et se l'est envoyé, grace aux Raw Sockets) ... (devrait fermer
le socket du coté de l'expéditeur, mais ca ne marche pas) :
15:11:59.373699 xx.xx.xx.xx.imaps > 192.168.1.3.33254: R [tcp sum ok]
3960647341:3960647341(0) win 0 (DF) (ttl 253, id 0, len 40)

5) tentative du logiciel d'ecrire dans le socket (alors que le paquet
precedent aurait du lui faire comprendre que le socket etait mort):
15:12:06.073374 192.168.1.3.33254 > xx.xx.xx.xx.imaps: P [tcp sum ok]
461:490(29) ack 1589 win 8870 <nop,nop,timestamp 1406204 163410425>
(DF) (ttl 64, id 39495, len 81)

6) Cible répond que socket fermé et ferme donc le socket du coté
expéditeur:
15:12:06.076633 xx.xx.xx.xx.imaps > 192.168.1.3.33254: R [tcp sum ok]
3960647341:3960647341(0) win 0 (DF) (ttl 253, id 0, len 40)

packet 4 = packet 6 non ? alors pourquoi le quatre ne ferme pas le
socket auprès du logiciel, alors que le 6 oui ?


détail ascii :
15:16:03.029155 192.168.1.3.33264 > xx.xx.xx.xx.imaps: F [tcp sum ok]
0:0(0) win 0 (DF) (ttl 253, id 0, len 40)
0x0000 4510 0028 0000 4000 fd06 3f8f c0a8 0103
E..(..@...?.....
0x0010 xxxx xxxx 81f0 03e1 0000 0000 0000 0000
QP+E............
0x0020 5001 0000 ebd1 0000 P.......
15:16:03.032450 xx.xx.xx.xx.imaps > 192.168.1.3.33264: . [tcp sum ok]
1547:1547(0) ack 432 win 6432 <nop,nop,timestamp 163434791 1428906>
(DF) (ttl 62, id 47958, len 52)
0x0000 4500 0034 bb56 4000 3e06 432d xxxx xxxx
E..4.V@.>.C-QP+E
0x0010 c0a8 0103 03e1 81f0 04bb 7c74 a601 53be
..........|t..S.
0x0020 8010 1920 75f7 0000 0101 080a 09bd d127
....u..........'
0x0030 0015 cdaa ....
15:16:03.032751 192.168.1.3.33264 > xx.xx.xx.xx.imaps: R [tcp sum ok]
2785104830:2785104830(0) win 0 (DF) (ttl 253, id 0, len 40)
0x0000 4510 0028 0000 4000 fd06 3f8f c0a8 0103
E..(..@...?.....
0x0010 xxxx xxxx 81f0 03e1 a601 53be 0000 0000
QP+E......S.....
0x0020 5004 0000 f20e 0000 P.......
15:16:03.032760 xx.xx.xx.xx.imaps > 192.168.1.3.33264: R [tcp sum ok]
79395956:79395956(0) win 0 (DF) (ttl 253, id 0, len 40)
0x0000 4510 0028 0000 4000 fd06 3f8f xxxx xxxx
E..(..@...?.QP+E
0x0010 c0a8 0103 03e1 81f0 04bb 7c74 0000 0000
..........|t....
0x0020 5004 0000 6a9f 0000 P...j...
15:16:06.658510 192.168.1.3.33264 > xx.xx.xx.xx.imaps: P [tcp sum ok]
432:461(29) ack 1547 win 8870 <nop,nop,timestamp 1430262 163434791>
(DF) (ttl 64, id 40850, len 81)
0x0000 4500 0051 9f92 4000 4006 5cd4 c0a8 0103
E..Q..@.@.\.....
0x0010 xxxx xxxx 81f0 03e1 a601 53be 04bb 7c74
QP+E......S...|t
0x0020 8018 22a6 9384 0000 0101 080a 0015 d2f6
..".............
0x0030 09bd d127 1703 0100 1890 5710 c450 b838
...'......W..P.8
0x0040 697e b447 cbaa 576b 5725 6f31 267d 2e9e
i~.G..WkW%o1&}..
0x0050 73 s
15:16:06.661649 xx.xx.xx.xx.imaps > 192.168.1.3.33264: R [tcp sum ok]
79395956:79395956(0) win 0 (DF) (ttl 253, id 0, len 40)
0x0000 4500 0028 0000 4000 fd06 3f8f xxxx xxxx
E..(..@...?.QP+E
0x0010 c0a8 0103 03e1 81f0 04bb 7c74 0000 0000
..........|t....
0x0020 5004 0000 6a9f 0000 0000 0000 0000 P...j.........

la seule différence que je vois c'est le nombre de 0 à la fin ... mais
bon ca a pas géné la cible, elle s'est bien fermée, pourquoi ca
generait l'expediteur ?

Est ce que j'interprète mal qq chose ? une erreur de base ? qq'un a
une idée ?

Merci
Florent

10 réponses

1 2
Avatar
T0t0
"Florent Carli" wrote in message
news:
J'essaye de faire un programme qui coupe la connexion tcp entre ma
machine et n'importe quelle autre, en me basant sur l'idée du "double
RST" du créateur de "TCP cutter" (http://www.lowth.com/cutter)
Le problème de base etant que n'etant pas "au milieu" de la session,
il faut s'envoyer un RST à soi même en usurpant l'identité de la
machine distante.


Whaou, c'est intéressant comme problème.

2 machines : Un EXPEDITEUR (qui veut mettre fin à la connection TCP
qu'il a avec la CIBLE) et la CIBLE
EXPEDITEUR : 192.168.1.3
CIBLE : xx.xx.xx.xx.


Au passage, c'est ta machine l'expéditeur ? ou une machine
quelconque ?

[snip]
6) Cible répond que socket fermé et ferme donc le socket du coté
expéditeur:
15:12:06.076633 xx.xx.xx.xx.imaps > 192.168.1.3.33254: R [tcp sum ok]
3960647341:3960647341(0) win 0 (DF) (ttl 253, id 0, len 40)

packet 4 = packet 6 non ? alors pourquoi le quatre ne ferme pas le
socket auprès du logiciel, alors que le 6 oui ?


Tu sniffes à quel niveau ?
Ca semble bizarre effectivement...

As-tu accès aux sockets des machines en cause ? pour pouvoir y placer
des codes d'erreur en fonction de ce qui est reçu ?


--
Posted via Mailgate.ORG Server - http://www.Mailgate.ORG

Avatar
nospam
Whaou, c'est intéressant comme problème.


ravi de voir que ca interesse qq'un :)

2 machines : Un EXPEDITEUR (qui veut mettre fin à la connection TCP
qu'il a avec la CIBLE) et la CIBLE
EXPEDITEUR : 192.168.1.3
CIBLE : xx.xx.xx.xx.


Au passage, c'est ta machine l'expéditeur ? ou une machine
quelconque ?


Oui l'expediteur, c ma machine : elle a plein de sessions ouvertes
(imaginons par ex que j'ai un emule qui tourne...) et donc le prog
serait la pour killer une session a la demande.
Ma machine est donc A (l'expediteur des packets sensés killer la
session) et le vilain downloader serait B.

Tu sniffes à quel niveau ?
Ca semble bizarre effectivement...


Bah je sniff avec un tcpdump donc au nivo de la libpcap.

As-tu accès aux sockets des machines en cause ? pour pouvoir y placer
des codes d'erreur en fonction de ce qui est reçu ?


Pour des tests, je peux avoir acces à A et B oui, mais les sockets
appartiennent a l'application qui les a lancé, donc je ne peux pas
faire bcp plus que lancer mes packets au milieu en esperant tromper
ces meme applis.

Une idée ? la j'avoue que je suis bien coincé.


Avatar
T0t0
"Florent Carli" wrote in message
news:
Oui l'expediteur, c ma machine : elle a plein de sessions ouvertes
(imaginons par ex que j'ai un emule qui tourne...) et donc le prog
serait la pour killer une session a la demande.
Ma machine est donc A (l'expediteur des packets sensés killer la
session) et le vilain downloader serait B.


Ok, je suis alle sur la page indiquee, si j ai bien compris, tu veux
faire pareil sans utiliser iptables ?

Bah je sniff avec un tcpdump donc au nivo de la libpcap.


Ok.

Pour des tests, je peux avoir acces à A et B oui, mais les sockets
appartiennent a l'application qui les a lancé, donc je ne peux pas
faire bcp plus que lancer mes packets au milieu en esperant tromper
ces meme applis.


L'ideal serait de lancer un client/serveur a ta sauce qui permettrait
de generer un code d erreur lorsque la trame en cause est recue.
Par contre, je ne sais pas comment exactement reagit la socket quand
elle recoit une info erronee. Je sais pas si ca remonte jusqu a l appli
ou si ca se limite au systeme d exploitation qui gere la socket...

Une idée ? la j'avoue que je suis bien coincé.


Tcpdump ne met pas tous les champs des en-tetes. Il faudrait voir avec
ethereal ou un truc du genre si les champs sont bien identiques.
En fait, si je reviens a ton premier post:

la seule différence que je vois c'est le nombre de 0 à la fin ...
mais bon ca a pas géné la cible, elle s'est bien fermée, pourquoi ca
generait l'expediteur ?


En fait, tu dois creer tes trames avec raw ethernet access. Ca a
quelle tete ? tu dois entrer tous les champs des en-tetes ? avec un
certain codage ? et au niveau des donnees ?
As tu essaye de rajouter tous ces 0 en fin de trame pour voir si ca
faisait la difference ?
Ca pourrait ressembler a une sorte de bourrage ajoute pour faire en
sorte que la trame soit au bon format.
"Les octets de bourrage terminent l'en-tête TCP:
- de sorte que le nombre d'octet de celle-ci soit toujours multiple
de 4 (32 bits)
- de sorte que l'offset de données marqué dans l'en-tête corresponde
bien au début des données applicatives"

Par ailleurs, les deux trames ne semblent pas exactement identique:
0x0000 4510 0028 0000 4000 fd06 3f8f xxxx xxxx (Sur la premiere)
0x0000 4500 0028 0000 4000 fd06 3f8f xxxx xxxx (Sur la seconde)

Il faut regarder a quelle partie de la trame cela correspond...

Une derniere chose.
Si j ai bien compris, c est juste quand tu essaies d envoyer une trame
en local (d un socket distant spoofe vers un socket local) que tu as
l erreur. Alors que quand tu envoies une trame vers une autre machine,
ca semble marcher (premier FIN par exemple)
Ce qui voudrait dire que le passage par la carte reseau pourrait
changer quelque chose...
Il faut peut etre voir du cote de la doc de raw ethernet access pour
voir ce qui se passe quand ca reste en local.

Voila, pas d autre idee pour l instant...

A la limite, si tu m envoies le code, je pourrai tester de mon cote
si tu veux.
(mon adresse n est plus valide, je peux t en filer une valide si tu
veux)




--
Posted via Mailgate.ORG Server - http://www.Mailgate.ORG

Avatar
nospam
Ok, je suis alle sur la page indiquee, si j ai bien compris, tu veux
faire pareil sans utiliser iptables ?


TCP Cutter n'utilise pas iptables. La diff que moi j'apporte c'est
qu'il n'est pas nécessaire d'être au milieu de la session (tcp cutter
est fait pour les firewalls).

L'ideal serait de lancer un client/serveur a ta sauce qui permettrait
de generer un code d erreur lorsque la trame en cause est recue.
Par contre, je ne sais pas comment exactement reagit la socket quand
elle recoit une info erronee. Je sais pas si ca remonte jusqu a l appli
ou si ca se limite au systeme d exploitation qui gere la socket...


Tu as tout dit, a ma connaissance l'appli ne voit pas les packets,
juste une api socket :) (peut etre que ca depend des applis, mais moi
je veux qq chose de général à toutes les applis

En fait, tu dois creer tes trames avec raw ethernet access. Ca a
quelle tete ? tu dois entrer tous les champs des en-tetes ? avec un
certain codage ? et au niveau des donnees ?


Bien vu :) mais g repompé le code de tcp cutter pour ca :)

As tu essaye de rajouter tous ces 0 en fin de trame pour voir si ca
faisait la difference ?
Ca pourrait ressembler a une sorte de bourrage ajoute pour faire en
sorte que la trame soit au bon format.
"Les octets de bourrage terminent l'en-tête TCP:
- de sorte que le nombre d'octet de celle-ci soit toujours multiple
de 4 (32 bits)
- de sorte que l'offset de données marqué dans l'en-tête corresponde
bien au début des données applicatives"


Lee bourrage est au nivo ethernet (me dit ethereal), et ca ne fait
aucune difference, puisque meme sans ce bourrage mon 1er RST kille
bien la connection dans l'autre sens. Le problème vient bel et bien du
fait que je m'autosend un packet...

Par ailleurs, les deux trames ne semblent pas exactement identique:
0x0000 4510 0028 0000 4000 fd06 3f8f xxxx xxxx (Sur la premiere)
0x0000 4500 0028 0000 4000 fd06 3f8f xxxx xxxx (Sur la seconde)



Le tos, pas de pb a ce nivo la, j'en ai essayé plusieurs

Tcpdump ne met pas tous les champs des en-tetes. Il faudrait voir avec
ethereal ou un truc du genre si les champs sont bien identiques.


Bien vu, le pb que ethereal m'a montré est que j'avais pas fait
l'inversion des addresses mac au nivo deux (donc j'avais une mac
destination = machine distante). J'ai changé ca, mais c dur de se
binder a un socket en spoofant sa propre mac par une autre, alors pour
l'instant j'ai une trame ethernet qui dit qu'elle part de chez moi
pour aller chez moi aussi (ce qui est la pure vérité)
Mais ca ne change rien malheureusement, mon appli ignore toujours ce
packet.

Une derniere chose.
Si j ai bien compris, c est juste quand tu essaies d envoyer une trame
en local (d un socket distant spoofe vers un socket local) que tu as
l erreur. Alors que quand tu envoies une trame vers une autre machine,
ca semble marcher (premier FIN par exemple)
Ce qui voudrait dire que le passage par la carte reseau pourrait
changer quelque chose...
Il faut peut etre voir du cote de la doc de raw ethernet access pour
voir ce qui se passe quand ca reste en local.


C ce que je fais pour l'instant, j'essaye de reprendre le code de
tcpcutter un peu plus a fond, c compliqué ;)

A la limite, si tu m envoies le code, je pourrai tester de mon cote
si tu veux.
(mon adresse n est plus valide, je peux t en filer une valide si tu
veux)


Si ce problème t'interesse, tu es bien sur un collaborateur
bienvenu...
(et pi c interessant les raw sockets ethernet en C non ? ;) )

Avatar
T0t0
"Florent Carli" wrote in message
news:
Si ce problème t'interesse, tu es bien sur un collaborateur
bienvenu...


Arf, j'ai pas le temps de m'y plonger ce soir, mais je te fais une
réponse ce WE.

(et pi c interessant les raw sockets ethernet en C non ? ;) )


Oui, bien que mon niveau en C m'interdise de pouvoir m'y mettre
vraiment, mais je m'y remets depuis quelques semaines. Je vais voir
ce que je peux faire...





--
Posted via Mailgate.ORG Server - http://www.Mailgate.ORG

Avatar
Cyril
Salut,

J'ai un peu suivi ce file, et j'y apporte mon grain de sel... ;)

TCP Cutter n'utilise pas iptables. La diff que moi j'apporte c'est
qu'il n'est pas nécessaire d'être au milieu de la session (tcp cutter
est fait pour les firewalls).
Cutter peut lire ip_conntrack. Utilisé pour les suivit de connection de

netfilter (je me souviens bien).
Si j'ai bien compris tu veux tuer la session TCP avec l'équivalent de :
"cutter 200.1.2.3 22 10.10.0.45 32451"
ou à la limite :
cutter 200.1.2.3 80
(puisqu l'autre adresse c'est forcement la tienne, et le port tu l'as dans
netstat).

Lee bourrage est au nivo ethernet (me dit ethereal), et ca ne fait
aucune difference, puisque meme sans ce bourrage mon 1er RST kille
bien la connection dans l'autre sens. Le problème vient bel et bien du
fait que je m'autosend un packet...
D'après ce que je comprend, le fait que tu t'envoies une trame, ça

pose problème... Hummm... intéressant... Dans adresse destinnation au niveau
ethernet tu as ta carte réseau, et source ? Et au niveau IP, en adresse
source tu mets la bonne adresse ?

Un test intéressant à faire est que tu te génères un ping vers ton adresse
IP, et en adresse source une autre adresse sur ton réseau... Sniffer et voir
si l'autre machine reçoit la réponse du ping.... Juste pour voir si ta trame
générée est prise en compte...

Tcpdump ne met pas tous les champs des en-tetes. Il faudrait voir avec
ethereal ou un truc du genre si les champs sont bien identiques.
Faudrait faire un tcpdump -w file qu'on pourrait lire avec ethereal par


exemple.

Bien vu, le pb que ethereal m'a montré est que j'avais pas fait
l'inversion des addresses mac au nivo deux (donc j'avais une mac
destination = machine distante). J'ai changé ca, mais c dur de se
binder a un socket en spoofant sa propre mac par une autre, alors pour
l'instant j'ai une trame ethernet qui dit qu'elle part de chez moi
pour aller chez moi aussi (ce qui est la pure vérité)
Mais ca ne change rien malheureusement, mon appli ignore toujours ce
packet.
Tiens j'ai ma réponse à ma question précédente... Etrange comme

problème...

C ce que je fais pour l'instant, j'essaye de reprendre le code de
tcpcutter un peu plus a fond, c compliqué ;)
Je fais le test ce soir avec cutter en local...


(et pi c interessant les raw sockets ethernet en C non ? ;) )
Ouais


Cyril


Avatar
nospam
Cutter peut lire ip_conntrack. Utilisé pour les suivit de connection de
netfilter (je me souviens bien).
Si j'ai bien compris tu veux tuer la session TCP avec l'équivalent de :
"cutter 200.1.2.3 22 10.10.0.45 32451"
ou à la limite :
cutter 200.1.2.3 80
(puisqu l'autre adresse c'est forcement la tienne, et le port tu l'as dans
netstat).


En effet Cutter lit dans ip_conntrack, mais n'utilise pas les
fonctionnalités d'iptables. C'est d'ailleurs pour ca que je refais un
truc en me basant sur /proc/net/tcp, que tout le monde a, pas
seulement les firewalls.

Je continue d'essayer, et je n'arrive pas a spoofer mon adresse mac
avec des raw sockets (je doute que ce soit le problème, mais on peut
toujours essayer). En effet, l'appel système "bind" ignore le champ
"adresse" que je lui passe. (man packet : For bind only sll_protocol
and sll_ifindex are used.)
La question a 100F pour tous les développeurs présents dans la salle
est la suivante : Comment on spoofe son adresse mac avec des raw
sockets sous linux ?
(C'est peut etre plus le bon newsgroup...)

Avatar
nospam
D'après ce que je comprend, le fait que tu t'envoies une trame, ça
pose problème... Hummm... intéressant... Dans adresse destinnation au niveau
ethernet tu as ta carte réseau, et source ? Et au niveau IP, en adresse
source tu mets la bonne adresse ?


Tout est inversé maintenant à toutes les couches réseaux (2, 3 et 4).
Donc le packet que j'emets sur le LAN est le même que celui que je
recevrais de mon interlocuteur si lui-même me l'envoyait.


Un test intéressant à faire est que tu te génères un ping vers ton adresse
IP, et en adresse source une autre adresse sur ton réseau... Sniffer et voir
si l'autre machine reçoit la réponse du ping.... Juste pour voir si ta trame
générée est prise en compte...



Bah plus simplement, s'envoyer un ping a soi-meme, ca marche non ?
alors pourquoi pas un RST ?

Avatar
Cyril
D'après ce que je comprend, le fait que tu t'envoies une trame,
ça


pose problème... Hummm... intéressant... Dans adresse destinnation au
niveau


ethernet tu as ta carte réseau, et source ? Et au niveau IP, en adresse
source tu mets la bonne adresse ?


Tout est inversé maintenant à toutes les couches réseaux (2, 3 et 4).
Donc le packet que j'emets sur le LAN est le même que celui que je
recevrais de mon interlocuteur si lui-même me l'envoyait.
Bien....


Un test intéressant à faire est que tu te génères un ping vers ton
adresse


IP, et en adresse source une autre adresse sur ton réseau... Sniffer et
voir


si l'autre machine reçoit la réponse du ping.... Juste pour voir si ta
trame


générée est prise en compte...



Bah plus simplement, s'envoyer un ping a soi-meme, ca marche non ?
alors pourquoi pas un RST ?
Tu peux faire une trace avec tcpdump -w file et avec un descriptif

de la maquette montée (graphique si possible, sinon par écrit) et tu me
l'envoie... On sinon tu le mets à dispo on ze net.

Cyril


Avatar
T0t0
"Florent Carli" wrote in message
news:
Bah plus simplement, s'envoyer un ping a soi-meme, ca marche non ?
alors pourquoi pas un RST ?


De même que deux sockets peuvent facilement dialoguer en local, il n'y
a pas de problème au niveau réseau pour cela.
Par contre, le problème que tu décris est plus sioux que cela et
demande une petite recherche car tu fais dialoguer deux RAW_SOCKET qui
ont été crées par toi, il faut donc que les infos que tu y places
soient correctes. Dans le cas de ping ou de deux sockets UDP ou TCP,
l'os gère les sockets et ce qu'il met dedans. Dans ton cas, c'est toi
qui remplis ce qui est envoyé et il faut vérifier que c'est correct.

Désolé, mais je n'ai pas eu le temps de m'y pencher ce WE.

Si jamais toi et Cyril continuez à galérer sur ce problème,
j'essaierai de le reproduire en local. Mais je trouve pas le temps !!!




--
Posted via Mailgate.ORG Server - http://www.Mailgate.ORG

1 2