commit c49bbc503cd565c766fdd91ffd094f2fbe2d6170 Author: mischa Date: Sun Apr 30 17:15:42 2023 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9393d5a --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +change.pl +#records/* +#records-archive/* +#tokens/* +#zonefiles/* +#zonefiles-archive/* diff --git a/clean.pl b/clean.pl new file mode 100755 index 0000000..6fab844 --- /dev/null +++ b/clean.pl @@ -0,0 +1,38 @@ +#!/usr/bin/env perl +# +use 5.024; +use strict; +use warnings; +use autodie; +use Fcntl qw(:flock); +use File::Basename; +use File::stat; +use POSIX qw(strftime); + +my $ttl = "300"; +my $workdir = dirname($0); + +opendir my $dh, "${workdir}/tokens"; +while (my $file = readdir $dh) { + chomp $file; + next if $file =~ /^\./; + + open my $fh, '<', "${workdir}/tokens/$file"; + my $client_ip = <$fh>; + chomp $client_ip; + close $fh; + + my $mtime = stat("${workdir}/tokens/${file}")->mtime(); + if ((time() - $mtime) > $ttl) { + _log("$client_ip $file removed"); + unlink("${workdir}/tokens/${file}"); + } +} + +sub _log { + my ($msg) = @_; + open my $fh, '>>', '/var/log/ptrd.log'; + flock $fh, LOCK_EX; + print $fh sprintf("%s %s: %s \n", strftime("%b %d %H:%M:%S", localtime), basename($0), $msg); + close $fh; +} diff --git a/fetch-tlds.sh b/fetch-tlds.sh new file mode 100755 index 0000000..86322d3 --- /dev/null +++ b/fetch-tlds.sh @@ -0,0 +1,2 @@ +#!/bin/sh +ftp -MV https://data.iana.org/TLD/tlds-alpha-by-domain.txt diff --git a/parse.pl b/parse.pl new file mode 100755 index 0000000..36b4792 --- /dev/null +++ b/parse.pl @@ -0,0 +1,105 @@ +#!/usr/bin/env perl +# +use 5.024; +use strict; +use warnings; +use autodie; +use Fcntl qw(:flock); +use File::Basename; +use File::Copy; +use POSIX qw(strftime); +use Net::IP; + +my $ipv4_range = new Net::IP("46.23.80.0/20"); +my $ipv6_range = new Net::IP("2a03:6000::/29"); +my $nsd = "/var/nsd/zones/reverse"; +my $v6_zone = "2a03.6000"; +my $workdir = dirname($0); +my $serial; +my $serial_prev; +my $zonefile; + +opendir my $dh, "${workdir}/records"; +while (my $file = readdir $dh) { + chomp $file; + next if $file =~ /^\./; + + open my $fh_ptr, '<', "${workdir}/records/$file"; + my $replace = <$fh_ptr>; + chomp $replace; + my ($match, $rest) = split(' ', $replace, 2); + close $fh_ptr; + + my $ip = new Net::IP($file); + if ($ip->overlaps($ipv4_range)) { + ($zonefile = $file) =~ s/^((\d{1,3}\.){3})\d+$/${1}0/; + } elsif ($ip->overlaps($ipv6_range)) { + $zonefile = $v6_zone; + } + + if (qx(rlog ${nsd}/${zonefile} | grep 'locked by') =~ m/locked by/) { + _log("$file zone file locked, trying again later..."); + next; + } else { + open my $fh_in, '<', "${nsd}/$zonefile"; + open my $fh_out, '>', "${workdir}/zonefiles/$zonefile"; + while (my $row = <$fh_in>) { + chomp $row; + if ($row =~ m/^\s*(\d+)\s*; serial$/) { + $serial = $serial_prev = $1; + my $timestamp = strftime ("%Y%m%d", localtime()) . "01"; + if ($serial < $timestamp) { + $serial = $timestamp; + } else { + $serial++; + } + $row =~ s/${serial_prev}/${serial}/; + } + + if ($row =~ m/^${match}\s+IN\s+PTR\s+\S+( ;.*)?$/) { + if ($1) { + my $comment = $1; + $row =~ s/^${match}\s+.*$/${replace}${comment}/; + } else { + $row =~ s/^${match}\s+.*$/${replace}/; + } + } + print $fh_out "$row\n"; + } + close $fh_in; + close $fh_out; + + (my $diff = qx(diff ${nsd}/${zonefile} ${workdir}/zonefiles/${zonefile} | wc -l)) =~ s/^\s*(.*?)\s*$/$1/; + if ($diff == 8) { + _log("$file diff within limits ($diff), $serial_prev -> $serial"); + copy("${nsd}/${zonefile}", "${workdir}/zonefiles-archive/${zonefile}-${serial}"); + qx(co -q -l ${nsd}/${zonefile}); + copy("${workdir}/zonefiles/${zonefile}", "${nsd}/${zonefile}"); + qx(ci -q -u -m"updated for ${file}" ${nsd}/${zonefile}); + move("${workdir}/records/${file}", "${workdir}/records-archive/${file}-${serial}"); + + qx(rcctl reload nsd); + qx(rdist -f /etc/Distfile) if (-r '/etc/Distfile'); + + open my $fh_email, '|-', '/usr/sbin/sendmail -t'; + print $fh_email "To: ptrd\@openbsd.amsterdam\n"; + print $fh_email "From: ptrd\@openbsd.amsterdam\n"; + print $fh_email "Subject: OpenBSD Amsterdam PTR $zonefile\n"; + print $fh_email "Content-Type: text/plain; charset=utf-8\n\n"; + print $fh_email "$serial_prev -> $serial\n$file\n$replace\n"; + close $fh_email; + } else { + _log("$file diff is outside limits ($diff), cleaning up"); + unlink("${workdir}/records/${file}", "${workdir}/zonefiles/${zonefile}"); + } + } +} + +sub _log { + my ($msg) = @_; + open my $fh, '>>', '/var/log/ptrd.log'; + flock $fh, LOCK_EX; + print $fh sprintf("%s %s: %s \n", strftime("%b %d %H:%M:%S", localtime), basename($0), $msg); + close $fh; +} + diff --git a/ptrd.pl b/ptrd.pl new file mode 100755 index 0000000..b6e64ac --- /dev/null +++ b/ptrd.pl @@ -0,0 +1,223 @@ +#!/usr/bin/perl +# +use 5.024; +use strict; +use warnings; +use autodie; +use Digest::SHA qw(sha1_hex); +use Fcntl qw(:flock); +use File::Basename; +use Getopt::Long; +use POSIX qw(strftime WNOHANG); +use Pod::Usage; +use HTTP::Daemon; +use HTTP::Response; +use HTTP::Status; +use Net::IP; + +GetOptions( + "listen=s" => \(my $LISTEN = "ptr4.openbsd.amsterdam"), + "port=i" => \(my $PORT = "80"), + "help" => \(my $HELP), + "man" => \(my $MAN), +) or pod2usage(2); +pod2usage(1) if $HELP; +pod2usage(-verbose => 2) if $MAN; + +=head1 NAME + +=head1 SYNOPSIS + +ptrd.pl [options] + +=head1 OPTIONS + +=over 4 + +=item B<-l> | --listen + +Address or hostname to listen on, default ptr4.openbsd.amsterdam. + +=item B<-p> | --port + +Port to listen on, default 80 + +=back + +=head1 DESCRIPTION + +B is a Perl HTTP Daemon designed to listen for incoming PTR records of OpenBSD Amsterdam VMs. + +A token needs to be requested before the PTR record can be set. + +=cut + +my %O = ( + 'listen-host' => $LISTEN, + 'listen-port' => $PORT, + 'listen-clients' => 10, + 'listen-max-req-per-child' => 10000, +); + +my $d = HTTP::Daemon->new( + LocalAddr => $O{'listen-host'}, + LocalPort => $O{'listen-port'}, + Reuse => 1, +) or die "Can't start http listener at $O{'listen-host'}:$O{'listen-port'}"; +_log("Started HTTP listener at $LISTEN from " . dirname($0)); + +my %chld; +my $workdir = dirname($0); +my $error = 0; + +$SIG{INT} = \&signal_handler; +$SIG{TERM} = \&signal_handler; + +open my $fh_tlds, '<', "${workdir}/tlds-alpha-by-domain.txt"; +chomp(my @tlds = <$fh_tlds>); +close $fh_tlds; + +if ($O{'listen-clients'}) { + $SIG{CHLD} = sub { + # checkout finished children + while ((my $kid = waitpid(-1, WNOHANG)) > 0) { + delete $chld{$kid}; + } + }; +} + +while (1) { + if ($O{'listen-clients'}) { + # prefork all at once + for (scalar(keys %chld) .. $O{'listen-clients'} - 1 ) { + my $pid = fork; + + if (!defined $pid) { # error + die "Can't fork for http child $_: $!"; + } + if ($pid) { # parent + $chld{$pid} = 1; + } else { # child + $_ = 'DEFAULT' for @SIG{qw/ INT TERM CHLD /}; + http_child($d); + exit; + } + } + sleep 1; + } else { + http_child($d); + } +} + +sub http_child { + my $d = shift; + my $i; + + while (++$i < $O{'listen-max-req-per-child'}) { + my $c = $d->accept or last; + my $r = $c->get_request(1) or last; + $c->autoflush(1); + + my $ipv4_range = new Net::IP("46.23.80.0/20"); + my $ipv6_range = new Net::IP("2a03:6000::/29"); + + my $client_ip = $c->peerhost; + my $ip = new Net::IP($client_ip); + my ($first, $token, $hostname) = split(/\//, $r->uri->as_string); + my $tld = (defined($hostname) ? substr($hostname, rindex($hostname, '.')+1) : ''); + $hostname = (!defined($hostname) ? $token : lc($hostname)); + + if ($ip->overlaps($ipv4_range) or $ip->overlaps($ipv6_range)) { + + if ($token eq 'token') { + my $token = sha1_hex(int(rand(32))); + open my $fh_token, '>', "${workdir}/tokens/${token}"; + print $fh_token "$client_ip\n"; + close $fh_token; + + _log("$client_ip $token"); + _http_response($c, {content_type => 'text/plain'}, "$token"); + + } elsif (-e "${workdir}/tokens/$token" and grep(/^${tld}$/i, @tlds) and ($hostname =~ /(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?', "${workdir}/records/${client_ip}"; + if ($ip->overlaps($ipv4_range)) { + my $ptr = substr($client_ip, rindex($client_ip, '.')+1); + print $fh sprintf("%s\t\tIN\tPTR\t%s.\n", $ptr, $hostname); + + } elsif ($ip->overlaps($ipv6_range)) { + my $dig = qx(dig +short \@46.23.80.23 -x ${client_ip}); + if (!$dig) { + $error = 1; + } else { + my $ptr = substr($ip->reverse_ip(), 0, 47); + print $fh sprintf("%s\tIN\tPTR\t%s.\n", $ptr, $hostname); + } + } + close $fh; + + if ($error == 1) { + _log("$client_ip $token $hostname - PTR doesn't exist"); + _http_response($c, {content_type => 'text/plain'}, "Error PTR [$client_ip] doesn't exist, please contact the administrator."); + $error = 0; + } else { + _log("$client_ip $token $hostname"); + _http_response($c, {content_type => 'text/plain'}, "Received PTR [$client_ip -> $hostname] will be processed asap."); + } + + } elsif (!-e "${workdir}/tokens/$token" and defined($token)and $token ne 'token') { + _log("$client_ip RC_REQUEST_TIMEOUT $hostname"); + _http_error($c, RC_REQUEST_TIMEOUT); + + } else { + _log("$client_ip RC_BAD_REQUEST $hostname"); + _http_error($c, RC_BAD_REQUEST); + } + + } else { + #print sprintf("%s %s: %s RC_FORBIDDEN\n", $date, $0, $client_ip); + _log("$client_ip RC_FORBIDDEN"); + _http_error($c, RC_FORBIDDEN); + } + + $c->close(); + undef $c; + } +} + +sub _http_error { + my ($c, $code, $msg) = @_; + $c->send_error($code, $msg); +} + +sub _http_response { + my $c = shift; + my $header = shift; + my $content = shift; + $c->send_response( + HTTP::Response->new( + RC_OK, + undef, + [ + 'Content-Type' => $header->{content_type}, + 'Cache-Control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0', + 'Pragma' => 'no-cache', + 'Expires' => 'Wed, 29 Feb 1984 13:37:00 GMT', + ], + "$content\r\n", + ) + ); +} + +sub _log { + my ($msg) = @_; + open my $fh, '>>', '/var/log/ptrd.log'; + flock $fh, LOCK_EX; + print $fh sprintf("%s %s: %s \n", strftime("%b %d %H:%M:%S", localtime), basename($0), $msg); + close $fh; +} + +sub signal_handler { + _log("Caught a signal $!"); + die "Caught a signal $!"; +} diff --git a/rc.d/ptrd4 b/rc.d/ptrd4 new file mode 100755 index 0000000..f5ee9f2 --- /dev/null +++ b/rc.d/ptrd4 @@ -0,0 +1,13 @@ +#!/bin/ksh + +daemon="/home/runbsd/api/ptrd.pl" + +. /etc/rc.d/rc.subr + +pexp="$(eval echo ${daemon}${daemon_flags:+ ${daemon_flags}})" +rc_bg="YES" +rc_reload="NO" + +pexp="/usr/bin/perl ${daemon}${daemon_flags:+ ${daemon_flags}}" + +rc_cmd $1 diff --git a/rc.d/ptrd6 b/rc.d/ptrd6 new file mode 100755 index 0000000..5c3a7a4 --- /dev/null +++ b/rc.d/ptrd6 @@ -0,0 +1,13 @@ +#!/bin/ksh + +daemon="/home/runbsd/api2/ptrd.pl" + +. /etc/rc.d/rc.subr + +pexp="$(eval echo ${daemon}${daemon_flags:+ ${daemon_flags}})" +rc_bg="YES" +rc_reload="NO" + +pexp="/usr/bin/perl ${daemon}${daemon_flags:+ ${daemon_flags}}" + +rc_cmd $1 diff --git a/tlds-alpha-by-domain.txt b/tlds-alpha-by-domain.txt new file mode 100644 index 0000000..46b0d0d --- /dev/null +++ b/tlds-alpha-by-domain.txt @@ -0,0 +1,1480 @@ +# Version 2023042900, Last Updated Sat Apr 29 07:07:01 2023 UTC +AAA +AARP +ABARTH +ABB +ABBOTT +ABBVIE +ABC +ABLE +ABOGADO +ABUDHABI +AC +ACADEMY +ACCENTURE +ACCOUNTANT +ACCOUNTANTS +ACO +ACTOR +AD +ADS +ADULT +AE +AEG +AERO +AETNA +AF +AFL +AFRICA +AG +AGAKHAN +AGENCY +AI +AIG +AIRBUS +AIRFORCE +AIRTEL +AKDN +AL +ALFAROMEO +ALIBABA +ALIPAY +ALLFINANZ +ALLSTATE +ALLY +ALSACE +ALSTOM +AM +AMAZON +AMERICANEXPRESS +AMERICANFAMILY +AMEX +AMFAM +AMICA +AMSTERDAM +ANALYTICS +ANDROID +ANQUAN +ANZ +AO +AOL +APARTMENTS +APP +APPLE +AQ +AQUARELLE +AR +ARAB +ARAMCO +ARCHI +ARMY +ARPA +ART +ARTE +AS +ASDA +ASIA +ASSOCIATES +AT +ATHLETA +ATTORNEY +AU +AUCTION +AUDI +AUDIBLE +AUDIO +AUSPOST +AUTHOR +AUTO +AUTOS +AVIANCA +AW +AWS +AX +AXA +AZ +AZURE +BA +BABY +BAIDU +BANAMEX +BANANAREPUBLIC +BAND +BANK +BAR +BARCELONA +BARCLAYCARD +BARCLAYS +BAREFOOT +BARGAINS +BASEBALL +BASKETBALL +BAUHAUS +BAYERN +BB +BBC +BBT +BBVA +BCG +BCN +BD +BE +BEATS +BEAUTY +BEER +BENTLEY +BERLIN +BEST +BESTBUY +BET +BF +BG +BH +BHARTI +BI +BIBLE +BID +BIKE +BING +BINGO +BIO +BIZ +BJ +BLACK +BLACKFRIDAY +BLOCKBUSTER +BLOG +BLOOMBERG +BLUE +BM +BMS +BMW +BN +BNPPARIBAS +BO +BOATS +BOEHRINGER +BOFA +BOM +BOND +BOO +BOOK +BOOKING +BOSCH +BOSTIK +BOSTON +BOT +BOUTIQUE +BOX +BR +BRADESCO +BRIDGESTONE +BROADWAY +BROKER +BROTHER +BRUSSELS +BS +BT +BUILD +BUILDERS +BUSINESS +BUY +BUZZ +BV +BW +BY +BZ +BZH +CA +CAB +CAFE +CAL +CALL +CALVINKLEIN +CAM +CAMERA +CAMP +CANON +CAPETOWN +CAPITAL +CAPITALONE +CAR +CARAVAN +CARDS +CARE +CAREER +CAREERS +CARS +CASA +CASE +CASH +CASINO +CAT +CATERING +CATHOLIC +CBA +CBN +CBRE +CBS +CC +CD +CENTER +CEO +CERN +CF +CFA +CFD +CG +CH +CHANEL +CHANNEL +CHARITY +CHASE +CHAT +CHEAP +CHINTAI +CHRISTMAS +CHROME +CHURCH +CI +CIPRIANI +CIRCLE +CISCO +CITADEL +CITI +CITIC +CITY +CITYEATS +CK +CL +CLAIMS +CLEANING +CLICK +CLINIC +CLINIQUE +CLOTHING +CLOUD +CLUB +CLUBMED +CM +CN +CO +COACH +CODES +COFFEE +COLLEGE +COLOGNE +COM +COMCAST +COMMBANK +COMMUNITY +COMPANY +COMPARE +COMPUTER +COMSEC +CONDOS +CONSTRUCTION +CONSULTING +CONTACT +CONTRACTORS +COOKING +COOKINGCHANNEL +COOL +COOP +CORSICA +COUNTRY +COUPON +COUPONS +COURSES +CPA +CR +CREDIT +CREDITCARD +CREDITUNION +CRICKET +CROWN +CRS +CRUISE +CRUISES +CU +CUISINELLA +CV +CW +CX +CY +CYMRU +CYOU +CZ +DABUR +DAD +DANCE +DATA +DATE +DATING +DATSUN +DAY +DCLK +DDS +DE +DEAL +DEALER +DEALS +DEGREE +DELIVERY +DELL +DELOITTE +DELTA +DEMOCRAT +DENTAL +DENTIST +DESI +DESIGN +DEV +DHL +DIAMONDS +DIET +DIGITAL +DIRECT +DIRECTORY +DISCOUNT +DISCOVER +DISH +DIY +DJ +DK +DM +DNP +DO +DOCS +DOCTOR +DOG +DOMAINS +DOT +DOWNLOAD +DRIVE +DTV +DUBAI +DUNLOP +DUPONT +DURBAN +DVAG +DVR +DZ +EARTH +EAT +EC +ECO +EDEKA +EDU +EDUCATION +EE +EG +EMAIL +EMERCK +ENERGY +ENGINEER +ENGINEERING +ENTERPRISES +EPSON +EQUIPMENT +ER +ERICSSON +ERNI +ES +ESQ +ESTATE +ET +ETISALAT +EU +EUROVISION +EUS +EVENTS +EXCHANGE +EXPERT +EXPOSED +EXPRESS +EXTRASPACE +FAGE +FAIL +FAIRWINDS +FAITH +FAMILY +FAN +FANS +FARM +FARMERS +FASHION +FAST +FEDEX +FEEDBACK +FERRARI +FERRERO +FI +FIAT +FIDELITY +FIDO +FILM +FINAL +FINANCE +FINANCIAL +FIRE +FIRESTONE +FIRMDALE +FISH +FISHING +FIT +FITNESS +FJ +FK +FLICKR +FLIGHTS +FLIR +FLORIST +FLOWERS +FLY +FM +FO +FOO +FOOD +FOODNETWORK +FOOTBALL +FORD +FOREX +FORSALE +FORUM +FOUNDATION +FOX +FR +FREE +FRESENIUS +FRL +FROGANS +FRONTDOOR +FRONTIER +FTR +FUJITSU +FUN +FUND +FURNITURE +FUTBOL +FYI +GA +GAL +GALLERY +GALLO +GALLUP +GAME +GAMES +GAP +GARDEN +GAY +GB +GBIZ +GD +GDN +GE +GEA +GENT +GENTING +GEORGE +GF +GG +GGEE +GH +GI +GIFT +GIFTS +GIVES +GIVING +GL +GLASS +GLE +GLOBAL +GLOBO +GM +GMAIL +GMBH +GMO +GMX +GN +GODADDY +GOLD +GOLDPOINT +GOLF +GOO +GOODYEAR +GOOG +GOOGLE +GOP +GOT +GOV +GP +GQ +GR +GRAINGER +GRAPHICS +GRATIS +GREEN +GRIPE +GROCERY +GROUP +GS +GT +GU +GUARDIAN +GUCCI +GUGE +GUIDE +GUITARS +GURU +GW +GY +HAIR +HAMBURG +HANGOUT +HAUS +HBO +HDFC +HDFCBANK +HEALTH +HEALTHCARE +HELP +HELSINKI +HERE +HERMES +HGTV +HIPHOP +HISAMITSU +HITACHI +HIV +HK +HKT +HM +HN +HOCKEY +HOLDINGS +HOLIDAY +HOMEDEPOT +HOMEGOODS +HOMES +HOMESENSE +HONDA +HORSE +HOSPITAL +HOST +HOSTING +HOT +HOTELES +HOTELS +HOTMAIL +HOUSE +HOW +HR +HSBC +HT +HU +HUGHES +HYATT +HYUNDAI +IBM +ICBC +ICE +ICU +ID +IE +IEEE +IFM +IKANO +IL +IM +IMAMAT +IMDB +IMMO +IMMOBILIEN +IN +INC +INDUSTRIES +INFINITI +INFO +ING +INK +INSTITUTE +INSURANCE +INSURE +INT +INTERNATIONAL +INTUIT +INVESTMENTS +IO +IPIRANGA +IQ +IR +IRISH +IS +ISMAILI +IST +ISTANBUL +IT +ITAU +ITV +JAGUAR +JAVA +JCB +JE +JEEP +JETZT +JEWELRY +JIO +JLL +JM +JMP +JNJ +JO +JOBS +JOBURG +JOT +JOY +JP +JPMORGAN +JPRS +JUEGOS +JUNIPER +KAUFEN +KDDI +KE +KERRYHOTELS +KERRYLOGISTICS +KERRYPROPERTIES +KFH +KG +KH +KI +KIA +KIDS +KIM +KINDER +KINDLE +KITCHEN +KIWI +KM +KN +KOELN +KOMATSU +KOSHER +KP +KPMG +KPN +KR +KRD +KRED +KUOKGROUP +KW +KY +KYOTO +KZ +LA +LACAIXA +LAMBORGHINI +LAMER +LANCASTER +LANCIA +LAND +LANDROVER +LANXESS +LASALLE +LAT +LATINO +LATROBE +LAW +LAWYER +LB +LC +LDS +LEASE +LECLERC +LEFRAK +LEGAL +LEGO +LEXUS +LGBT +LI +LIDL +LIFE +LIFEINSURANCE +LIFESTYLE +LIGHTING +LIKE +LILLY +LIMITED +LIMO +LINCOLN +LINK +LIPSY +LIVE +LIVING +LK +LLC +LLP +LOAN +LOANS +LOCKER +LOCUS +LOL +LONDON +LOTTE +LOTTO +LOVE +LPL +LPLFINANCIAL +LR +LS +LT +LTD +LTDA +LU +LUNDBECK +LUXE +LUXURY +LV +LY +MA +MADRID +MAIF +MAISON +MAKEUP +MAN +MANAGEMENT +MANGO +MAP +MARKET +MARKETING +MARKETS +MARRIOTT +MARSHALLS +MASERATI +MATTEL +MBA +MC +MCKINSEY +MD +ME +MED +MEDIA +MEET +MELBOURNE +MEME +MEMORIAL +MEN +MENU +MERCKMSD +MG +MH +MIAMI +MICROSOFT +MIL +MINI +MINT +MIT +MITSUBISHI +MK +ML +MLB +MLS +MM +MMA +MN +MO +MOBI +MOBILE +MODA +MOE +MOI +MOM +MONASH +MONEY +MONSTER +MORMON +MORTGAGE +MOSCOW +MOTO +MOTORCYCLES +MOV +MOVIE +MP +MQ +MR +MS +MSD +MT +MTN +MTR +MU +MUSEUM +MUSIC +MUTUAL +MV +MW +MX +MY +MZ +NA +NAB +NAGOYA +NAME +NATURA +NAVY +NBA +NC +NE +NEC +NET +NETBANK +NETFLIX +NETWORK +NEUSTAR +NEW +NEWS +NEXT +NEXTDIRECT +NEXUS +NF +NFL +NG +NGO +NHK +NI +NICO +NIKE +NIKON +NINJA +NISSAN +NISSAY +NL +NO +NOKIA +NORTHWESTERNMUTUAL +NORTON +NOW +NOWRUZ +NOWTV +NP +NR +NRA +NRW +NTT +NU +NYC +NZ +OBI +OBSERVER +OFFICE +OKINAWA +OLAYAN +OLAYANGROUP +OLDNAVY +OLLO +OM +OMEGA +ONE +ONG +ONL +ONLINE +OOO +OPEN +ORACLE +ORANGE +ORG +ORGANIC +ORIGINS +OSAKA +OTSUKA +OTT +OVH +PA +PAGE +PANASONIC +PARIS +PARS +PARTNERS +PARTS +PARTY +PASSAGENS +PAY +PCCW +PE +PET +PF +PFIZER +PG +PH +PHARMACY +PHD +PHILIPS +PHONE +PHOTO +PHOTOGRAPHY +PHOTOS +PHYSIO +PICS +PICTET +PICTURES +PID +PIN +PING +PINK +PIONEER +PIZZA +PK +PL +PLACE +PLAY +PLAYSTATION +PLUMBING +PLUS +PM +PN +PNC +POHL +POKER +POLITIE +PORN +POST +PR +PRAMERICA +PRAXI +PRESS +PRIME +PRO +PROD +PRODUCTIONS +PROF +PROGRESSIVE +PROMO +PROPERTIES +PROPERTY +PROTECTION +PRU +PRUDENTIAL +PS +PT +PUB +PW +PWC +PY +QA +QPON +QUEBEC +QUEST +RACING +RADIO +RE +READ +REALESTATE +REALTOR +REALTY +RECIPES +RED +REDSTONE +REDUMBRELLA +REHAB +REISE +REISEN +REIT +RELIANCE +REN +RENT +RENTALS +REPAIR +REPORT +REPUBLICAN +REST +RESTAURANT +REVIEW +REVIEWS +REXROTH +RICH +RICHARDLI +RICOH +RIL +RIO +RIP +RO +ROCHER +ROCKS +RODEO +ROGERS +ROOM +RS +RSVP +RU +RUGBY +RUHR +RUN +RW +RWE +RYUKYU +SA +SAARLAND +SAFE +SAFETY +SAKURA +SALE +SALON +SAMSCLUB +SAMSUNG +SANDVIK +SANDVIKCOROMANT +SANOFI +SAP +SARL +SAS +SAVE +SAXO +SB +SBI +SBS +SC +SCA +SCB +SCHAEFFLER +SCHMIDT +SCHOLARSHIPS +SCHOOL +SCHULE +SCHWARZ +SCIENCE +SCOT +SD +SE +SEARCH +SEAT +SECURE +SECURITY +SEEK +SELECT +SENER +SERVICES +SEVEN +SEW +SEX +SEXY +SFR +SG +SH +SHANGRILA +SHARP +SHAW +SHELL +SHIA +SHIKSHA +SHOES +SHOP +SHOPPING +SHOUJI +SHOW +SHOWTIME +SI +SILK +SINA +SINGLES +SITE +SJ +SK +SKI +SKIN +SKY +SKYPE +SL +SLING +SM +SMART +SMILE +SN +SNCF +SO +SOCCER +SOCIAL +SOFTBANK +SOFTWARE +SOHU +SOLAR +SOLUTIONS +SONG +SONY +SOY +SPA +SPACE +SPORT +SPOT +SR +SRL +SS +ST +STADA +STAPLES +STAR +STATEBANK +STATEFARM +STC +STCGROUP +STOCKHOLM +STORAGE +STORE +STREAM +STUDIO +STUDY +STYLE +SU +SUCKS +SUPPLIES +SUPPLY +SUPPORT +SURF +SURGERY +SUZUKI +SV +SWATCH +SWISS +SX +SY +SYDNEY +SYSTEMS +SZ +TAB +TAIPEI +TALK +TAOBAO +TARGET +TATAMOTORS +TATAR +TATTOO +TAX +TAXI +TC +TCI +TD +TDK +TEAM +TECH +TECHNOLOGY +TEL +TEMASEK +TENNIS +TEVA +TF +TG +TH +THD +THEATER +THEATRE +TIAA +TICKETS +TIENDA +TIFFANY +TIPS +TIRES +TIROL +TJ +TJMAXX +TJX +TK +TKMAXX +TL +TM +TMALL +TN +TO +TODAY +TOKYO +TOOLS +TOP +TORAY +TOSHIBA +TOTAL +TOURS +TOWN +TOYOTA +TOYS +TR +TRADE +TRADING +TRAINING +TRAVEL +TRAVELCHANNEL +TRAVELERS +TRAVELERSINSURANCE +TRUST +TRV +TT +TUBE +TUI +TUNES +TUSHU +TV +TVS +TW +TZ +UA +UBANK +UBS +UG +UK +UNICOM +UNIVERSITY +UNO +UOL +UPS +US +UY +UZ +VA +VACATIONS +VANA +VANGUARD +VC +VE +VEGAS +VENTURES +VERISIGN +VERSICHERUNG +VET +VG +VI +VIAJES +VIDEO +VIG +VIKING +VILLAS +VIN +VIP +VIRGIN +VISA +VISION +VIVA +VIVO +VLAANDEREN +VN +VODKA +VOLKSWAGEN +VOLVO +VOTE +VOTING +VOTO +VOYAGE +VU +VUELOS +WALES +WALMART +WALTER +WANG +WANGGOU +WATCH +WATCHES +WEATHER +WEATHERCHANNEL +WEBCAM +WEBER +WEBSITE +WED +WEDDING +WEIBO +WEIR +WF +WHOSWHO +WIEN +WIKI +WILLIAMHILL +WIN +WINDOWS +WINE +WINNERS +WME +WOLTERSKLUWER +WOODSIDE +WORK +WORKS +WORLD +WOW +WS +WTC +WTF +XBOX +XEROX +XFINITY +XIHUAN +XIN +XN--11B4C3D +XN--1CK2E1B +XN--1QQW23A +XN--2SCRJ9C +XN--30RR7Y +XN--3BST00M +XN--3DS443G +XN--3E0B707E +XN--3HCRJ9C +XN--3PXU8K +XN--42C2D9A +XN--45BR5CYL +XN--45BRJ9C +XN--45Q11C +XN--4DBRK0CE +XN--4GBRIM +XN--54B7FTA0CC +XN--55QW42G +XN--55QX5D +XN--5SU34J936BGSG +XN--5TZM5G +XN--6FRZ82G +XN--6QQ986B3XL +XN--80ADXHKS +XN--80AO21A +XN--80AQECDR1A +XN--80ASEHDB +XN--80ASWG +XN--8Y0A063A +XN--90A3AC +XN--90AE +XN--90AIS +XN--9DBQ2A +XN--9ET52U +XN--9KRT00A +XN--B4W605FERD +XN--BCK1B9A5DRE4C +XN--C1AVG +XN--C2BR7G +XN--CCK2B3B +XN--CCKWCXETD +XN--CG4BKI +XN--CLCHC0EA0B2G2A9GCD +XN--CZR694B +XN--CZRS0T +XN--CZRU2D +XN--D1ACJ3B +XN--D1ALF +XN--E1A4C +XN--ECKVDTC9D +XN--EFVY88H +XN--FCT429K +XN--FHBEI +XN--FIQ228C5HS +XN--FIQ64B +XN--FIQS8S +XN--FIQZ9S +XN--FJQ720A +XN--FLW351E +XN--FPCRJ9C3D +XN--FZC2C9E2C +XN--FZYS8D69UVGM +XN--G2XX48C +XN--GCKR3F0F +XN--GECRJ9C +XN--GK3AT1E +XN--H2BREG3EVE +XN--H2BRJ9C +XN--H2BRJ9C8C +XN--HXT814E +XN--I1B6B1A6A2E +XN--IMR513N +XN--IO0A7I +XN--J1AEF +XN--J1AMH +XN--J6W193G +XN--JLQ480N2RG +XN--JVR189M +XN--KCRX77D1X4A +XN--KPRW13D +XN--KPRY57D +XN--KPUT3I +XN--L1ACC +XN--LGBBAT1AD8J +XN--MGB9AWBF +XN--MGBA3A3EJT +XN--MGBA3A4F16A +XN--MGBA7C0BBN0A +XN--MGBAAKC7DVF +XN--MGBAAM7A8H +XN--MGBAB2BD +XN--MGBAH1A3HJKRD +XN--MGBAI9AZGQP6J +XN--MGBAYH7GPA +XN--MGBBH1A +XN--MGBBH1A71E +XN--MGBC0A9AZCG +XN--MGBCA7DZDO +XN--MGBCPQ6GPA1A +XN--MGBERP4A5D4AR +XN--MGBGU82A +XN--MGBI4ECEXP +XN--MGBPL2FH +XN--MGBT3DHD +XN--MGBTX2B +XN--MGBX4CD0AB +XN--MIX891F +XN--MK1BU44C +XN--MXTQ1M +XN--NGBC5AZD +XN--NGBE9E0A +XN--NGBRX +XN--NODE +XN--NQV7F +XN--NQV7FS00EMA +XN--NYQY26A +XN--O3CW4H +XN--OGBPF8FL +XN--OTU796D +XN--P1ACF +XN--P1AI +XN--PGBS0DH +XN--PSSY2U +XN--Q7CE6A +XN--Q9JYB4C +XN--QCKA1PMC +XN--QXA6A +XN--QXAM +XN--RHQV96G +XN--ROVU88B +XN--RVC1E0AM3E +XN--S9BRJ9C +XN--SES554G +XN--T60B56A +XN--TCKWE +XN--TIQ49XQYJ +XN--UNUP4Y +XN--VERMGENSBERATER-CTB +XN--VERMGENSBERATUNG-PWB +XN--VHQUV +XN--VUQ861B +XN--W4R85EL8FHU5DNRA +XN--W4RS40L +XN--WGBH1C +XN--WGBL6A +XN--XHQ521B +XN--XKC2AL3HYE2A +XN--XKC2DL3A5EE0H +XN--Y9A3AQ +XN--YFRO4I67O +XN--YGBI2AMMX +XN--ZFR164B +XXX +XYZ +YACHTS +YAHOO +YAMAXUN +YANDEX +YE +YODOBASHI +YOGA +YOKOHAMA +YOU +YOUTUBE +YT +YUN +ZA +ZAPPOS +ZARA +ZERO +ZIP +ZM +ZONE +ZUERICH +ZW