ืืขืื. ืืขื ืืืื ืขืก ืืื ืึท ื ืขืฅ ืคืื 5 ืง ืงืืืืึทื ืฅ. ืืขืฆืื ืก ืขืก ืืื ืืขืืืขื ืึท ื ืื ืืืืขืจ ืึธื ืืขื ืขื ืืึธืืขื ื - ืืื ืืขื ืฆืขื ืืขืจ ืคืื ืื ื ืขืฅ ืืืจ ืืึธืื ืึท ืืจืึธืงืึทืืข ืจืงืก 8 ืืื ืขืก ืกืืึทืจืืขื ืฉืืงื ืึท ืคึผืืึทืฅ ืคืื ืืืืืึทืงืึทื ื-ืื ืืงืึทืกื ืคึผืึทืงืืฅ, ืืื ื ืื ื ืขืฅ ืืื ืฆืขืืืืื ืืื ืืืืึทื ื - ืืึธืก ืืื ืืืืืืืืื ื ืืฉื ืึท ืคึผืจืึธืืืขื, ืึธืืขืจ ืขืก ืืขื ืขื ืกืคึผืขืฆืืขืืข ืืืืึทื ื ืคึฟืึทืจ ืืืืึทืก ืึทืืจืขืกืขืก, ืขืืง. ืืื ืืื ืืขื ืขื ืืืืกืืขืฉืืจืขืงื ืืื ืึทืืข ืจืืืืื ืืขื ืคืื ืืขืจ ื ืขืฅ. ืืขืฆื ืฉืืขื ืืื ืคืืจ ื ืื ืงืืืขื ืืืืข ืฉืืจืึธื ืฆื ืื ืืืจืขืก ืคืื ื ืงืืืขื ื ืืืืก ืืขืจื ื ื ืืฉื ืืืก ืืจืขื ืืฅ ืกืืืืขื ื ืืื ืืขืจ ืฉืืจืึธื ืคืืื ืฆื ื ืจืืืื ืืื ืง ืฆื ืขืคืขืก (ืืืขืจ ืืืข) ืืืจืฃ - ืืขืจ ืงืื ืื ืืื ืคืืจืฉืืืคื - ืื ืงืืืืึทื ืฅ ืืขื ืขื ืืืื - ืืจืืืขืจืืง...
ืืขืจ ืฆืื ืืื ืฆื ืืืขื ืื ืึท ืืฉืืง ืืื ืึท ืฉืืจืื. ืืื ืืึธื ืืขืืจืึทืื ืืื ืืขืจ ืจืืืืื ื ืคืื q-in-q ืืื ืึท ืคืื-ืคืืขืืืฉื ืงืืืขื ื ืืืืึทื, ืึธืืขืจ ืึทืืข ืกืึธืจืฅ ืคืื ืืึทืื ืืืึทืจื ืืื P3310, ืืืขื dot1q ืืื ืขื ืืืืึทืื, ืกืืึทืคึผืก ืืึธืื DHCP ืืืจื, ืืื ืืืื ืืึธื ื ืื ืืืืกื ืืื ืฆื ืกืขืืขืงืืืื qinq ืืื ืคืืืข ืคึผืืืคืึธืื ืคืื ืืขื ืืื. ืืืึธืก ืืื ืืคึผ-ืึทื ื ืึทืืืขืจื ืืื ืืื ืืื ืขืก ืึทืจืืขื? ืืืืขืจ ืืขืงืืฆืขืจ: ืืืืืืืื ืึทืืจืขืก + ืืึทืจืฉืจืื ืืืืฃ ืื ืฆืืืื ื. ืคึฟืึทืจ ืืื ืืืขืจ ืึทืจืืขื, ืืืจ ืืึทืจืคึฟื ืฆื: ืฉื ืืึทืื ืื ืฉืึทืคึผืขืจ, ืคืึทืจืฉืคึผืจืืืื ืึทืืจืขืกืขืก ืฆื ืงืืืืึทื ืฅ, ืืืืื ืจืืฅ ืฆื ืงืืืืึทื ืฅ ืืืจื ืืืืขืจ ืื ืืขืจืคืืืกืื. ืืื ืฆื ืืึธื ืืึธืก ืึทืืฅ? Shaper - lisg, dhcp - db2dhcp ืืืืฃ ืฆืืืื ืคืจืืึท ืกืขืจืืืขืจืก, dhcprelay ืืืืคื ืืืืฃ ืึทืงืกืขืก ืกืขืจืืืขืจืก, ucarp ืืืื ืืืืคื ืืืืฃ ืึทืงืกืขืก ืกืขืจืืืขืจืก - ืคึฟืึทืจ ืืึทืงืึทืคึผ. ืืืขืจ ืืื ืฆื ืืืืื ืจืืฅ? ืืืจ ืงืขื ืขื ืืืืื ืึทืืฅ ืืื ืฉืืืึทืื ืืื ืึท ืืจืืืก ืฉืจืืคื - ืึธืืขืจ ืืึธืก ืืื ื ืืฉื ืืืช. ืึทืืื ืืืจ ืืืขืื ืืึทืื ืึท ืืื-ืืขืฉืจืืื ืงืจืึทืืฉ.
ื ืึธื ืึท ืืจืื ืืืง ืืืื ืืืืฃ ืืขืจ ืืื ืืขืจื ืขืฅ, ืืื ืืขืคึฟืื ืขื ืึท ืืืื ืืขืจืืขื ืืืื-ืืืจืื ืืืืืืึธืืขืง ืคึฟืึทืจ C ++, ืืืึธืก ืึทืืึทืื ืืืจ ืฆื ืฉืืื ืฆืืฉืืขืงื ืคืึทืจืงืขืจ. ืืขืจ ืึทืืืขืจืืืึทื ืคึฟืึทืจ ืื ืคึผืจืึธืืจืึทื ืืืึธืก ืืืกืืฃ ืจืืฅ ืืื ืืื ืืืื - ืืืจ ืืขืจื ืฆื ืึทืจืคึผ ืจืืงืืืขืก ืืืืฃ ืื ืฆืืืื ื, ืืืื ืืืจ ืืึธืื ืึทื ืึทืืจืขืก ืืืืฃ ืื ืืึธ ืฆืืืื ื ืืืืฃ ืื ืกืขืจืืืขืจ ืืืึธืก ืืื ืืขืืขืื, ืืืจ ืืืืื ืึท ืืึทืจืฉืจืื ืืืจื ืืขื ืฆืืืื ื ืืื ืืืืื ืึท ืกืืึทืืืง ืึทืจืคึผ. ืจืขืงืึธืจื ืฆื ืืขื ืืคึผ - ืืื ืึทืืืขืืืื, ืึท ืืืกื ืงืึธืคึผืืข-ืคึผืึทืกืืขืก, ืึท ืืืกื ืึทืืืฉืืงืืืื ืืื ืืืจ ื ืืืึธ ืืขืืื
ืงืืืืื ืคืื ืื 'ืจืึธืืืขืจ'
#include <stdio.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <tins/tins.h>
#include <map>
#include <iostream>
#include <functional>
#include <sstream>
using std::cout;
using std::endl;
using std::map;
using std::bind;
using std::string;
using std::stringstream;
using namespace Tins;
class arp_monitor {
public:
void run(Sniffer &sniffer);
void reroute();
void makegws();
string iface;
map <string, string> gws;
private:
bool callback(const PDU &pdu);
map <string, string> route_map;
map <string, string> mac_map;
map <IPv4Address, HWAddress<6>> addresses;
};
void arp_monitor::makegws() {
struct ifaddrs *ifAddrStruct = NULL;
struct ifaddrs *ifa = NULL;
void *tmpAddrPtr = NULL;
gws.clear();
getifaddrs(&ifAddrStruct);
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr) {
continue;
}
string ifName = ifa->ifa_name;
if (ifName == "lo") {
char addressBuffer[INET_ADDRSTRLEN];
if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
// is a valid IP4 Address
tmpAddrPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
} else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6
// is a valid IP6 Address
tmpAddrPtr = &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr;
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
} else {
continue;
}
gws[addressBuffer] = addressBuffer;
cout << "GW " << addressBuffer << " is added" << endl;
}
}
if (ifAddrStruct != NULL) freeifaddrs(ifAddrStruct);
}
void arp_monitor::run(Sniffer &sniffer) {
cout << "RUNNED" << endl;
sniffer.sniff_loop(
bind(
&arp_monitor::callback,
this,
std::placeholders::_1
)
);
}
void arp_monitor::reroute() {
cout << "REROUTING" << endl;
map<string, string>::iterator it;
for ( it = route_map.begin(); it != route_map.end(); it++ ) {
if (this->gws.count(it->second) && !this->gws.count(it->second)) {
string cmd = "ip route replace ";
cmd += it->first;
cmd += " dev " + this->iface;
cmd += " src " + it->second;
cmd += " proto static";
cout << cmd << std::endl;
cout << "REROUTE " << it->first << " SRC " << it->second << endl;
system(cmd.c_str());
cmd = "arp -s ";
cmd += it->first;
cmd += " ";
cmd += mac_map[it->first];
cout << cmd << endl;
system(cmd.c_str());
}
}
for ( it = gws.begin(); it != gws.end(); it++ ) {
string cmd = "arping -U -s ";
cmd += it->first;
cmd += " -I ";
cmd += this->iface;
cmd += " -b -c 1 ";
cmd += it->first;
system(cmd.c_str());
}
cout << "REROUTED" << endl;
}
bool arp_monitor::callback(const PDU &pdu) {
// Retrieve the ARP layer
const ARP &arp = pdu.rfind_pdu<ARP>();
if (arp.opcode() == ARP::REQUEST) {
string target = arp.target_ip_addr().to_string();
string sender = arp.sender_ip_addr().to_string();
this->route_map[sender] = target;
this->mac_map[sender] = arp.sender_hw_addr().to_string();
cout << "save sender " << sender << ":" << this->mac_map[sender] << " want taregt " << target << endl;
if (this->gws.count(target) && !this->gws.count(sender)) {
string cmd = "ip route replace ";
cmd += sender;
cmd += " dev " + this->iface;
cmd += " src " + target;
cmd += " proto static";
// cout << cmd << std::endl;
/* cout << "ARP REQUEST FROM " << arp.sender_ip_addr()
<< " for address " << arp.target_ip_addr()
<< " sender hw address " << arp.sender_hw_addr() << std::endl
<< " run cmd: " << cmd << endl;*/
system(cmd.c_str());
cmd = "arp -s ";
cmd += arp.sender_ip_addr().to_string();
cmd += " ";
cmd += arp.sender_hw_addr().to_string();
cout << cmd << endl;
system(cmd.c_str());
}
}
return true;
}
arp_monitor monitor;
void reroute(int signum) {
monitor.makegws();
monitor.reroute();
}
int main(int argc, char *argv[]) {
string test;
cout << sizeof(string) << endl;
if (argc != 2) {
cout << "Usage: " << *argv << " <interface>" << endl;
return 1;
}
signal(SIGHUP, reroute);
monitor.iface = argv[1];
// Sniffer configuration
SnifferConfiguration config;
config.set_promisc_mode(true);
config.set_filter("arp");
monitor.makegws();
try {
// Sniff on the provided interface in promiscuous mode
Sniffer sniffer(argv[1], config);
// Only capture arp packets
monitor.run(sniffer);
}
catch (std::exception &ex) {
std::cerr << "Error: " << ex.what() << std::endl;
}
}
ืืืืืื ืก ืื ืกืืึทืืืจืื ื ืฉืจืืคื
#!/bin/bash
git clone https://github.com/mfontanini/libtins.git
cd libtins
mkdir build
cd build
cmake ../
make
make install
ldconfig
ืืึทืคึฟืขื ืฆื ืืืืขื ืื ืืืื ืขืจื
g++ main.cpp -o arp-rt -O3 -std=c++11 -lpthread -ltins
ืืื ืฆื ืึธื ืืืืื ืขืก?
start-stop-daemon --start --exec /opt/ipoe/arp-routes/arp-rt -b -m -p /opt/ipoe/arp-routes/daemons/eth0.800.pid -- eth0.800
ืืึธ - ืขืก ืืืขื ืจืืืืื ืื ืืืฉื ืืืืืจื ืืืืฃ ืื HUP ืกืืื ืึทื. ืคืืจืืืืก ืืื ืืืจ ื ืืฉื ื ืืฆื ื ืขืืืื ืง? ืขืก ืืื ื ืึธืจ ืคืืืืงืืึทื ืืื ืืื ืืงืก ืืื ืึท ืฉืจืืคื ืืืืฃ ืึท ืฉืจืืคื - ืึทืืื ืึทืืฅ ืืื ืืื. ื ื, ืจืืฅ ืืขื ืขื ืจืืฅ, ืืืึธืก ืก ืืืืึทืืขืจ? ืืืืึทืืขืจ, ืืืจ ืืึทืจืคึฟื ืฆื ืฉืืงื ืื ืจืืฅ ืืืึธืก ืืขื ืขื ืืืืฃ ืืขื ืกืขืจืืืขืจ ืฆื ืื ืืจืขื ืขืฅ - ืืึธ, ืจืขืื ืฆื ืืขืจ ืืขืืืืงืขืจ ืึทืืืืืืืื ืืึทืื ืืืึทืจื, ืืืจ ืืขื ืืืขื ืืขื ืืืขื ืคืื ืืื ืืกืืขืจ ืงืขืื ืฉืืขื - ืืืจ ืึทืกืืื ื ืืขื ืึทืจืืขื ืฆื BGP.
bgp configืืึทืืขืืึธืก ื ืึธืืขื *******
ืคึผืึทืจืึธื *******
ืงืืึธืฅ ืืขืงืข /var/log/bgp.log
!
# AS ื ืืืขืจ, ืืืขื ืื ืืื ื ืขืืืืึธืจืงืก ืืขื ืขื ืคืืงืืืฉ
ืจืึทืืืขืจ bgp 12345
bgp router-id 1.2.3.4
ืจืืืืกืืจืืืืื ืงืึธื ื ืขืงืืขื
ืจืืืืกืืจืืืืื ืกืืึทืืืง
ืืืจ 1.2.3.1 ืืืืึทื-ืืื 12345
ืืืจ 1.2.3.1 ืืืืึทืืขืจ-ืืึธืคึผืงืขื-ืืื
ืืืจ 1.2.3.1 ืืึทืจืฉืจืื-ืืึทืคึผืข ืงืืื ืืื
ืืืจ 1.2.3.1 ืืึทืจืฉืจืื-ืืึทืคึผืข ืึทืจืืืกืคืืจื
!
ืึทืงืกืขืก-ืจืฉืืื ืึทืจืืืกืคืืจื ืืขืจืืืืืขื ืืฉ 1.2.3.0/24
!
ืืึทืจืฉืจืื-ืืึทืคึผืข ืึทืจืืืกืคืืจื ืืขืจืืืืืขื ืืฉ 10
ืืืืึทืื ืืคึผ ืึทืืจืขืก ืึทืจืืืกืคืืจื
!
ืืึทืจืฉืจืื-ืืึทืคึผืข ืึทืจืืืกืคืืจื ืืืืงืขื ืขื 20
ืืึธืืืจ ืคืึธืจืืขืฆื. ืึผืื ืืขืจ ืกืขืจืืืขืจ ืืึธื ืจืืกืคึผืึทื ื ืฆื ืึทืจืคึผ ืจืืงืืืขืก, ืืืจ ืืืื ืืขืื ืื ืึทืจืคึผ ืคืจืืงืกื.
echo 1 > /proc/sys/net/ipv4/conf/eth0.800/proxy_arp
ืืืืืจ ืืืืืืขืจ ืืืื - ืืืงืึทืจืคึผ. ืืืจ ืฉืจืืึทืื ืื ืงืึทืืขืจ ืกืงืจืืคึผืก ืคึฟืึทืจ ืืขื ื ืก ืืื.
ืืืึทืฉืคึผืื ืคืื ืคืืืกื ืืืง ืืืื ืืืืืึทื
start-stop-daemon --start --exec /usr/sbin/ucarp -b -m -p /opt/ipoe/ucarp-gen2/daemons/$iface.$vhid.$virtualaddr.pid -- --interface=eth0.800 --srcip=1.2.3.4 --vhid=1 --pass=carpasword --addr=10.10.10.1 --upscript=/opt/ipoe/ucarp-gen2/up.sh --downscript=/opt/ipoe/ucarp-gen2/down.sh -z -k 10 -P --xparam="10.10.10.0/24"
ืึทืจืืืฃ.ืฉ
#!/bin/bash
iface=$1
addr=$2
gw=$3
vlan=`echo $1 | sed "s/eth0.//"`
ip ad ad $addr/32 dev lo
ip ro add blackhole $gw
echo 1 > /proc/sys/net/ipv4/conf/$iface/proxy_arp
killall -9 dhcrelay
/etc/init.d/dhcrelay zap
/etc/init.d/dhcrelay start
killall -HUP arp-rt
ืึทืจืึธืคึผ.ืฉ
#!/bin/bash
iface=$1
addr=$2
gw=$3
ip ad d $addr/32 dev lo
ip ro de blackhole $gw
echo 0 > /proc/sys/net/ipv4/conf/$iface/proxy_arp
killall -9 dhcrelay
/etc/init.d/dhcrelay zap
/etc/init.d/dhcrelay start
ืคึฟืึทืจ dhcprelay ืฆื ืึทืจืืขืื ืืืืฃ ืึท ืฆืืืื ื, ืขืก ืืึทืจืฃ ืึทื ืึทืืจืขืก. ืืขืจืืืขืจ, ืืืืฃ ืื ืื ืืขืจืคืืืกืื ืืืึธืก ืืืจ ื ืืฆื ืืืจ ืืืขืื ืืืืื ืืื ืงืก ืึทืืจืขืกืขืก - ืคึฟืึทืจ ืืืึทืฉืคึผืื 10.255.255.1/32, 10.255.255.2/32, ืขืืง. ืืื ืืืขื ื ืืฉื ืืึธืื ืืืจ ืืื ืฆื ืงืึทื ืคืืืืขืจ ืื ืจืขืืข - ืึทืืฅ ืืื ืคึผืฉืื.
ืึทืืื ืืืึธืก ืืึธื ืืืจ ืืึธืื? ืืึทืงืงืืคึผ ืคืื ืืืืืืืืื, ืึทืืืึธ-ืงืึทื ืคืืืืขืจืืืฉืึทื ืคืื ืจืืฅ, dhcp. ืืึธืก ืืื ืืขืจ ืืื ืืืื ืฉืืขืื - ืืืกื ืืืื ืจืึทืคึผืก ืึทืืฅ ืึทืจืื ืืื ืืื ืืืจ ืืึธืื ืฉืืื ืึท ืฉืึทืคืขืจ. ืคืืจืืืืก ืืื ืึทืืฅ ืึทืืื ืืึทื ื ืืื ืงืึทื ืคืืืืื ื? ืืื ืขืก ื ืืฉื ืืจืื ืืขืจ ืฆื ื ืขืืขื ืึทืงืกืขื-ืคึผืคึผืคึผื ืืื ื ืืฆื pppoe ืืขืกืึทืืึทืงื? ื ืืื, ืืึธืก ืืื ื ืืฉื ืกืืืคึผืืขืจ - ืืขื ืืฉื ืงืขื ืขื ืงืืื ืคึผืึทืกืืง ืึท ืคึผืึทืืฉืงืึธืจื ืืื ืึท ืจืึทืืืขืจ, ื ืื ืฆื ืืขืจืืึธื ืขื ืคึผืคึผืคึผืึธืข. accel-ppp ืืื ืึท ืงืื ืืึทื - ืึธืืขืจ ืขืก ืืื ื ืืฉื ืึทืจืืขืื ืคึฟืึทืจ ืืื ืื - ืขืก ืืขื ืขื ืึท ืคึผืืึทืฅ ืคืื ืขืจืจืึธืจืก ืืื ืื ืงืึธื - ืขืก ืงืจืึทืืืึทืื, ืขืก ืฉื ืืืื ืงืจืื, ืืื ืื ืืจืืืขืจืืง ืืึทื ืืื ืึทื ืืืื ืขืก ืืจืืืืึทื ื ืึทืจืืืฃ - ืืขืืึธืื ืืขื ืืฉื ืืึทืจืคึฟื ืฆื ืจืืืึธืื ืึทืืฅ - ืื ืคืึธื ืขืก ืืขื ืขื ืจืืื - ืขืก ืืื ื ืืฉื ืึทืจืืขืื. ืืืึธืก ืืื ืื ืืืึทืืข ืคืื โโโโื ืืฆื ืืงืึทืจืคึผ ืืื ืืื ืงืขืคึผืึทืืืืืขื? ืืึธ, ืืื ืึทืืฅ - ืขืก ืืขื ืขื 100 ืืืืืืืืื, ืงืขืขืึทืืืืืขื ืืื ืืืื ืืขืืช ืืื ืื ืงืึทื ืคืืืืขืจืืืฉืึทื - ืึทืืฅ ืึทืจืืขื ื ืืฉื. 1 ืืืืืืืื ืืื ื ืืฉื ืึทืจืืขืื ืืื ืืงืึทืจืคึผ. ืื ืืืข ืืืืขืจืืืื ืืืื ืืื ืื ืื ืืื ืงืข ืืืขืื ืคืืจืฉืจืืืื ืืืจืขืกื ืคืืจ ืืื ืืื ืืื ื ืืฆื ืืืืฃ ืื ืฉืขืจ - ืฆื ืงืื ืืจืืืืจื ืืขื ืืืืขื ื ืืืื ืืืจ ืืืืคืืขืฉืืขืื dhcp-snooping + source-guard + arp ืืืจืืงืืง ืืืืฃ ืืืข ืกืืืืืฉืื/ืึธืืฅ/ืืืกืขืก. ืืืื ืืขืจ ืงืืืขื ื ืืื ื ืืฉื ืืืคึผืง ืึธืืขืจ ืกืืึทืืืง - ืึทืงืกืขืก-ืจืฉืืื ืืืืฃ ืื ืคึผืึธืจื.
ืคืืจืืืืก ืืื ืืึธืก ืึทืืข ืืขืืื? ืฆื ืฆืขืฉืืขืจื ืึทื ืืืึธื ืืื ืคืึทืจืงืขืจ. ืืืฆื ืืขืืขืจ ืืึทืฉืืืืขื ืืื ืืืึทื ืืืืื ืืืืึทื ืืื ืืืืืึทืงืึทื ื-ืื ืืงืึทืกื ืืื ื ืื ืืขืจ ืกืงืขืจื, ืืื ื ืขืก ื ืึธืจ ืืึทืจืฃ ืฆื ืืืื ืฆื ืืืื ืคึผืึธืจื ืืื ื ืื ืฆื ืึทืืข ... ื ื, ืื ืืืึทื ืืคืขืงืฅ ืืขื ืขื ืึท ืกืืึทื ืืขืจืืืืื ืืืกืจืืื ืงืึทื ืคืืืืขืจืืืฉืึทื, ืืขืจ ืขืคืขืงืืืืืงืืึทื ืืื ืึทืืึทืงืืืืื ื ืึทืืจืขืก ืคึผืืึทืฅ.
ืืื ืฆื ืงืึทื ืคืืืืขืจ ืืืกื ืืื ืึท ืืึทืืื ืืขืจ ืืขืืข. ืืื ืงืก ืฆื ืืืืืืึธืืขืง ืืขื ืขื ืึทืืึทืืฉื. ืืึธืืขืจ ืื ืืืืื ืืืขื ืืขืืคื ืขืืขืฆืขืจ ืฆื ืืขืจืืจืืืื ืืืืขืจ ืฆืืื. ืืืขืจืกืืข 6 ืืื ื ืึธื ื ืืฉื ืืืคึผืืึทืืขื ืึทื ืืืืฃ ืืื ืืืขืจ ื ืขืฅ - ืึธืืขืจ ืขืก ืืืขื ืืืื ืึท ืคึผืจืึธืืืขื - ืขืก ืืขื ืขื ืคึผืืึทื ื ืฆื ืจืืจืืื ืืืกื ืคึฟืึทืจ ืืืขืจืกืืข 6, ืืื ืขืก ืืืขื ืืืื ื ืืืืืง ืฆื ืคืึทืจืจืืืื ืื ืคึผืจืึธืืจืึทื ืืืึธืก ืืืกืืฃ ืจืืฅ.
ืืงืืจ: www.habr.com