Security Week 37: Дружно выключаем Bluetooth, дыра в Tor на миллион, ботнеты на серверах Elasticsearch |
Метки: author Kaspersky_Lab информационная безопасность блог компании «лаборатория касперского» klsw bluetooth blueborne elasticsearch pos malware zerodium tor project |
Security Week 37: Дружно выключаем Bluetooth, дыра в Tor на миллион, ботнеты на серверах Elasticsearch |
Метки: author Kaspersky_Lab информационная безопасность блог компании «лаборатория касперского» klsw bluetooth blueborne elasticsearch pos malware zerodium tor project |
Как правильно вставлять SVG |
Метки: author htmlacademy разработка веб-сайтов html блог компании html academy svg html5 для начинающих верстка сайтов html- верстка графика |
Как правильно вставлять SVG |
Метки: author htmlacademy разработка веб-сайтов html блог компании html academy svg html5 для начинающих верстка сайтов html- верстка графика |
Приглашаем на mini ai cups |
Вот уже пять лет мы проводим russian ai cup, крупнейший в СНГ ежегодный чемпионат по искусственному интеллекту (а если проще — по написанию ботов для игр). И вот уже семь лет участники этого чемпионата просят либо оставлять песочницу работать весь год, либо запустить площадку, где можно было бы весь год играться в подобные же конкурсы, только чуть меньше размером.
Мы подумали и решили опробовать второй вариант — открыли новую площадку с мини-конкурсами, связанными с искусственным интеллектом и написанием ботов для игр. Встречайте новый для нас класс чемпионатов — http://aicups.ru/.
И сразу же предлагаем принять участие в первом, тестовом чемпионате.
И не бейте нас, пожалуйста, за дизайн площадки. Мы очень упарывались в качество самого соревнования, поэтому в дизайн мы просто не успели. Сделаем вид, что мы так видим ;)
Поскольку это первый чемпионат на новой площадке, мы особо не упарывались в сложность задачи и взяли довольно простую тематику — развоз пассажиров по этажам с помощью лифта. Чтобы разнообразить задачу, в неё добавлено несколько факторов, влияющих на алгоритм развоза пассажиров:
Кроме того, задачу мультиплеерная. То есть, у нас есть две группы лифтов и каждый игрок управляет своей группой. Сами же пассажиры делятся на “своих” и “чужих” — чужого сложнее забрать с этажа. Но если смог, получил 2x очков ;)
Подробнее обо всем этом можно прочитать ниже, в разделе “Правила”
Чемпионат открывается сегодня, 15-сентября, и продлится до 9-го октября.
Пока что наш план таков:
15-го сентября открывается площадка с песочницей, и у участников появляется возможность загружать свои стратегии и играть не-рейтинговые игры “на интерес” с другими своими стратегиями, с другими игроками или с бейзлайном — в песочнице живут два фейковых пользователя (“good baseline” — забирает всегда только своих пассажиров и “evil baseline” — забирает только чужих).
В сутки можно загрузить не более 6 новых решений, и сыграть не более 30 не-рейтинговых игр.
18 сентября в песочнице начинают работать рейтинговые игры (их система создает сама). Время от времени псевдослучайно выбирается два участника (для подбора мы используем TrueSkill, спасибо Microsoft за этот прекрасный алгоритм!). От каждого из них мы берем стратегию, которую он до этого выбрал для участия в рейтинге. Две эти стратегии играют друг с другом, победившая передвигается в лидерборде вверх, проигравшая вниз. Таким образом строится рейтинг песочницы.
9-го октября мы планируем провести финал. Некоторое количество топовых участников из песочницы будет отобрано в отдельный рейтинг, после чего мы запустим несколько волн игр “каждый с каждым” и таким образом выясним, чья же стратегия самая крутая, раздадим призы, учтем пожелания и пойдем готовиться к следующему подобному чемпионату!
Как уже давно принято в наших чемпионатах, мы награждаем TOP6. Расклад призов такой же, как и в прошедшем недавно highloadcup:
Кроме того, маечки! Не будем нарушать и эту добрую традицию — TOP20 получат от нас майки с символикой чемпионата. Возможно маек будет больше — в highloadcup мы тоже начали с 20-ти штук, в результате дарим 116 :)
Итак, подробнее о задаче.
Место появления пассажиров
Лестница
Кол-во пассажиров в группе
Кол-во пассажиров на этаже
Кол-во пассажиров в лифте
Тики
Описание здания:
Лифты:
Пассажиры:
Подсчет очков:
Побеждает игрок, набравший большее кол-во очков.
API и Baseline мы выложили в официальном репозитории с документацией, здесь. В этом же репозитории принимаются новые issue, мы обязательно будем их просматривать.
Сейчас у нас есть API для следующих языков:
Возможно, этот список будет пополняться. Прямо сейчас пытаемся подключить C#.
Участвовать могут все, без ограничений! Заходите, пробуйте! Поучаствовать можно здесь, а обсудить чемпионат можно в VK и в Telegram. Удачи в чемпионате!
Метки: author sat2707 разработка игр блог компании mail.ru group russian ai cup ai algorithms ненормальное программирование |
Приглашаем на mini ai cups |
Вот уже пять лет мы проводим russian ai cup, крупнейший в СНГ ежегодный чемпионат по искусственному интеллекту (а если проще — по написанию ботов для игр). И вот уже семь лет участники этого чемпионата просят либо оставлять песочницу работать весь год, либо запустить площадку, где можно было бы весь год играться в подобные же конкурсы, только чуть меньше размером.
Мы подумали и решили опробовать второй вариант — открыли новую площадку с мини-конкурсами, связанными с искусственным интеллектом и написанием ботов для игр. Встречайте новый для нас класс чемпионатов — http://aicups.ru/.
И сразу же предлагаем принять участие в первом, тестовом чемпионате.
И не бейте нас, пожалуйста, за дизайн площадки. Мы очень упарывались в качество самого соревнования, поэтому в дизайн мы просто не успели. Сделаем вид, что мы так видим ;)
Поскольку это первый чемпионат на новой площадке, мы особо не упарывались в сложность задачи и взяли довольно простую тематику — развоз пассажиров по этажам с помощью лифта. Чтобы разнообразить задачу, в неё добавлено несколько факторов, влияющих на алгоритм развоза пассажиров:
Кроме того, задачу мультиплеерная. То есть, у нас есть две группы лифтов и каждый игрок управляет своей группой. Сами же пассажиры делятся на “своих” и “чужих” — чужого сложнее забрать с этажа. Но если смог, получил 2x очков ;)
Подробнее обо всем этом можно прочитать ниже, в разделе “Правила”
Чемпионат открывается сегодня, 15-сентября, и продлится до 9-го октября.
Пока что наш план таков:
15-го сентября открывается площадка с песочницей, и у участников появляется возможность загружать свои стратегии и играть не-рейтинговые игры “на интерес” с другими своими стратегиями, с другими игроками или с бейзлайном — в песочнице живут два фейковых пользователя (“good baseline” — забирает всегда только своих пассажиров и “evil baseline” — забирает только чужих).
В сутки можно загрузить не более 6 новых решений, и сыграть не более 30 не-рейтинговых игр.
18 сентября в песочнице начинают работать рейтинговые игры (их система создает сама). Время от времени псевдослучайно выбирается два участника (для подбора мы используем TrueSkill, спасибо Microsoft за этот прекрасный алгоритм!). От каждого из них мы берем стратегию, которую он до этого выбрал для участия в рейтинге. Две эти стратегии играют друг с другом, победившая передвигается в лидерборде вверх, проигравшая вниз. Таким образом строится рейтинг песочницы.
9-го октября мы планируем провести финал. Некоторое количество топовых участников из песочницы будет отобрано в отдельный рейтинг, после чего мы запустим несколько волн игр “каждый с каждым” и таким образом выясним, чья же стратегия самая крутая, раздадим призы, учтем пожелания и пойдем готовиться к следующему подобному чемпионату!
Как уже давно принято в наших чемпионатах, мы награждаем TOP6. Расклад призов такой же, как и в прошедшем недавно highloadcup:
Кроме того, маечки! Не будем нарушать и эту добрую традицию — TOP20 получат от нас майки с символикой чемпионата. Возможно маек будет больше — в highloadcup мы тоже начали с 20-ти штук, в результате дарим 116 :)
Итак, подробнее о задаче.
Место появления пассажиров
Лестница
Кол-во пассажиров в группе
Кол-во пассажиров на этаже
Кол-во пассажиров в лифте
Тики
Описание здания:
Лифты:
Пассажиры:
Подсчет очков:
Побеждает игрок, набравший большее кол-во очков.
API и Baseline мы выложили в официальном репозитории с документацией, здесь. В этом же репозитории принимаются новые issue, мы обязательно будем их просматривать.
Сейчас у нас есть API для следующих языков:
Возможно, этот список будет пополняться. Прямо сейчас пытаемся подключить C#.
Участвовать могут все, без ограничений! Заходите, пробуйте! Поучаствовать можно здесь, а обсудить чемпионат можно в VK и в Telegram. Удачи в чемпионате!
Метки: author sat2707 разработка игр блог компании mail.ru group russian ai cup ai algorithms ненормальное программирование |
Краткое руководство для новичков, желающих стать комплексными (full stack) веб-разработчиками |
Метки: author SmirkinDA разработка веб-сайтов программирование блог компании parallels parallels web |
Краткое руководство для новичков, желающих стать комплексными (full stack) веб-разработчиками |
Метки: author SmirkinDA разработка веб-сайтов программирование блог компании parallels parallels web |
Новая серия вебинаров по SAP Cloud Platform: разработка, интеграция, мобильные приложения и многое другое за месяц |
Метки: author SAP разработка мобильных приложений блог компании sap sap sap cloud platform вебинары разработка интернет вещей машинное обучение |
Новая серия вебинаров по SAP Cloud Platform: разработка, интеграция, мобильные приложения и многое другое за месяц |
Метки: author SAP разработка мобильных приложений блог компании sap sap sap cloud platform вебинары разработка интернет вещей машинное обучение |
Большие маневры малого бизнеса: «Альфа-Бизнес Мобайл» и его возможности |
Метки: author megapost разработка мобильных приложений альфа |
Docker, или Туда и обратно |
С появлением docker у нас, как у сервиса мониторинга немного усложнилась жизнь. Как я писал ранее, одна из фишек нашего сервиса — автодетект сервисов, то есть агент сам находит запущенные на сервере сервисы, читает их конфиги и начинает сбор метрик.
Но в какой-то момент в production у наших клиентов начал появляться докер, и наш автодетект перестал работать. Процессу, который запускается через докер, проставляются различные namespace (mnt, net, user, pid), это достаточно сильно усложняет работу извне контейнера с файлами и сетью внутри контейнера.
Под катом я расскажу, как мы решали эту проблему, какие варианты пробовали, и что в итоге заработало.
Нашу задачу можно условно разделить на 2 части:
Первая гипотеза была очень простой: мы просто будем определять куда смотрит fs контейнера на диске хоста, менять пути и ходить туда. К сожалению это работает только в случае AUFS, но он в production практически не встречается.
Дальше мы наивно пробовали делать setns на MNT namespace прямо из кода агента, но это тоже не получилось. Дело в том, что setns на mnt (и user тоже) неймспейс может делать только однотредовое приложение:
A process may not be reassociated with a new mount namespace if it is multithreaded
Наш агент написан на golang и к моменту, когда мы хотим вызывать setns, гошный runtime уже наплодил нам несколько тредов. Чтобы агент мог запускать какие-то специальные процессы типа nsenter, нужно предварительно притащить их на машину клиенту, чего нам сильно не хотелось.
Был вариант запускать что-то через docker exec -ti
, но, во-первых, эта команда доступна только с версии 1.3, во-вторых, существует не только докер, но еще и другие сервисы контейнеризации, а в-третьих, внутри контейнера может не быть даже cat.
Потом нашелся интересный хак для go, который позволяет сделать setns в сишном конструкторе до запуска go runtime. В итоге мы пришли к тому, что агент запускает сам себя с определенными аргументами и может прочитать файл в нужном ns, раскрыть glob по файловой системе контейнера и тому подобное. Но так как setns должен выполняться в C коде, пришлось писать на C и обработку аргументов запуска. Причем в момент вызова
__attribute__((constructor))
argv/argc еще не проинициализированы, так что пришлось читать аргументы запуска себя из /proc/self/cmdline
.
При запуске агента в этом режиме он вываливает результат своей работы в stdout/stderr, а агент-родитель это читает. Отдельно пришлось сделать ограничение на размер читаемого файла: чтобы не нагружать диск мы даже не пытаемся читать файлы более 200KB (часто встречаются увесистые конфиги nginx с мапингом geoip), так как это может заметно прогрузить диск на клиентском сервере.
Такой подход хорошо работает только когда нужно один раз прочитать файл, но не годится, если нужно например tail'ить лог. С другой стороны логи на слоеные fs контейнеров обычно не пишут. Их обычно либо заворачивают в докеровские stdout/stderr и прогоняют через dockerd, либо пишут на примонтированные разделы на хостовую fs.
Вариант с dockerd мы пока никак не обрабатываем, но стоит отметить, что среди наших клиентов он встречается редко. Видимо из-за того, что на большом потоке логов, dockerd начинает нехило нагружать процессор.
Для случая с примонтированными директориями для логов, мы через информацию из docker inspect
пытаемся найти нужный файл на fs хоста, а плагин, который хочет парсить такой лог, получает путь до файла уже вне контейнера.
Первая идея относительно того, как работать по сети с сервисом в контейнере была тоже наивной: мы будем брать из docker inspect
IP контейнера и будем работать с ним. Потом выяснилось, что доступа с хоста в сеть контейнера может и не быть вовсе (macvlan). К тому же есть lxc итд.
Мы решили двигаться в сторону setns. Cетевой namespace в отличии от mnt и user можно переопределить для одного конкретного треда приложения. В golang с этим с первого взгляда все достаточно просто:
Но все оказалось сложнее. На самом деле при блокировке треда runtime нам не гарантирует, что исполнение данной горутины останется в этом треде. Есть хорошее описание как раз такого случае в посте "Linux Namespaces And Go Don't Mix".
Изначально мы собирались запускать плагин, мониторящий сервис в контейнере как раз в залоченном треде с setns, но это сломалось на первом же http клиенте.
Так как влиять на планировщик go у нас нет возможности, мы стали искать способ оставить в треде только код, не приводящий к порождению новых тредов.
Мы заметили, что если сразу после setns делать tcp коннект, то он проходит в 100% случаев, и если потом выйти из namespace и отпустить лок на тред, открытое соединение продолжает работать (я затрудняюсь объяснить, почему это работает).
Дальше задача свелась к тому, чтобы всем библиотеками для работы с различными сервисами, которые мы мониторим, подсунуть наш Dialer
(функцию, отвечающую за TCP connect):
client := redis.NewClient(&redis.Options{
Dialer: func() (net.Conn, error) {
return utils.DialTimeoutNs("tcp", params.Address, params.NetNs, redisTimeout)
},
ReadTimeout: redisTimeout,
WriteTimeout: redisTimeout,
Password: params.Password,
})
mysql.RegisterDial("netns", func(addr string) (net.Conn, error) {
return utils.DialTimeoutNs("tcp", addr, params.NetNs, connectTimeout)
})
db, err = sql.Open("mysql",
fmt.Sprintf("netns(%s)/?timeout=%s&readTimeout=%s&writeTimeout=%s",
params.Address, connectTimeout, readTimeout, writeTimeout))
database/sql
:func init() {
sql.Register("postgres+netns", &drv{})
}
type drv struct{}
type nsDialer struct {
netNs string
}
func (d nsDialer) Dial(ntw, addr string) (net.Conn, error) {
return utils.DialTimeoutNs(ntw, addr, d.netNs, connectTimeout)
}
func (d nsDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) {
return utils.DialTimeoutNs(ntw, addr, d.netNs, timeout)
}
func (d *drv) Open(name string) (driver.Conn, error) {
parts := strings.SplitN(name, "|", 2)
netNs := ""
if len(parts) == 2 {
netNs = parts[0]
name = parts[1]
}
return pq.DialOpen(nsDialer{netNs}, name)
}
потом вызываем свой драйвер:
dsn := fmt.Sprintf("%s|postgres://%s:%s@%s/%s",
p.NetNs, p.User, p.Password, p.Address, dbName)
db, err := sql.Open("postgres+netns", dsn)
Оглядываясь назад, мы не пожалели, что выбрали вариант с setns, так этот же код недавно прекрасно сработал у клиента с lxc.
Единственный незакрытый на данный момент сервис — это jvm в контейнере, но это совсем другая история.
Метки: author NikolaySivko системное программирование go блог компании okmeter.io мониторинг golang setns docker |
Docker, или Туда и обратно |
С появлением docker у нас, как у сервиса мониторинга немного усложнилась жизнь. Как я писал ранее, одна из фишек нашего сервиса — автодетект сервисов, то есть агент сам находит запущенные на сервере сервисы, читает их конфиги и начинает сбор метрик.
Но в какой-то момент в production у наших клиентов начал появляться докер, и наш автодетект перестал работать. Процессу, который запускается через докер, проставляются различные namespace (mnt, net, user, pid), это достаточно сильно усложняет работу извне контейнера с файлами и сетью внутри контейнера.
Под катом я расскажу, как мы решали эту проблему, какие варианты пробовали, и что в итоге заработало.
Нашу задачу можно условно разделить на 2 части:
Первая гипотеза была очень простой: мы просто будем определять куда смотрит fs контейнера на диске хоста, менять пути и ходить туда. К сожалению это работает только в случае AUFS, но он в production практически не встречается.
Дальше мы наивно пробовали делать setns на MNT namespace прямо из кода агента, но это тоже не получилось. Дело в том, что setns на mnt (и user тоже) неймспейс может делать только однотредовое приложение:
A process may not be reassociated with a new mount namespace if it is multithreaded
Наш агент написан на golang и к моменту, когда мы хотим вызывать setns, гошный runtime уже наплодил нам несколько тредов. Чтобы агент мог запускать какие-то специальные процессы типа nsenter, нужно предварительно притащить их на машину клиенту, чего нам сильно не хотелось.
Был вариант запускать что-то через docker exec -ti
, но, во-первых, эта команда доступна только с версии 1.3, во-вторых, существует не только докер, но еще и другие сервисы контейнеризации, а в-третьих, внутри контейнера может не быть даже cat.
Потом нашелся интересный хак для go, который позволяет сделать setns в сишном конструкторе до запуска go runtime. В итоге мы пришли к тому, что агент запускает сам себя с определенными аргументами и может прочитать файл в нужном ns, раскрыть glob по файловой системе контейнера и тому подобное. Но так как setns должен выполняться в C коде, пришлось писать на C и обработку аргументов запуска. Причем в момент вызова
__attribute__((constructor))
argv/argc еще не проинициализированы, так что пришлось читать аргументы запуска себя из /proc/self/cmdline
.
При запуске агента в этом режиме он вываливает результат своей работы в stdout/stderr, а агент-родитель это читает. Отдельно пришлось сделать ограничение на размер читаемого файла: чтобы не нагружать диск мы даже не пытаемся читать файлы более 200KB (часто встречаются увесистые конфиги nginx с мапингом geoip), так как это может заметно прогрузить диск на клиентском сервере.
Такой подход хорошо работает только когда нужно один раз прочитать файл, но не годится, если нужно например tail'ить лог. С другой стороны логи на слоеные fs контейнеров обычно не пишут. Их обычно либо заворачивают в докеровские stdout/stderr и прогоняют через dockerd, либо пишут на примонтированные разделы на хостовую fs.
Вариант с dockerd мы пока никак не обрабатываем, но стоит отметить, что среди наших клиентов он встречается редко. Видимо из-за того, что на большом потоке логов, dockerd начинает нехило нагружать процессор.
Для случая с примонтированными директориями для логов, мы через информацию из docker inspect
пытаемся найти нужный файл на fs хоста, а плагин, который хочет парсить такой лог, получает путь до файла уже вне контейнера.
Первая идея относительно того, как работать по сети с сервисом в контейнере была тоже наивной: мы будем брать из docker inspect
IP контейнера и будем работать с ним. Потом выяснилось, что доступа с хоста в сеть контейнера может и не быть вовсе (macvlan). К тому же есть lxc итд.
Мы решили двигаться в сторону setns. Cетевой namespace в отличии от mnt и user можно переопределить для одного конкретного треда приложения. В golang с этим с первого взгляда все достаточно просто:
Но все оказалось сложнее. На самом деле при блокировке треда runtime нам не гарантирует, что исполнение данной горутины останется в этом треде. Есть хорошее описание как раз такого случае в посте "Linux Namespaces And Go Don't Mix".
Изначально мы собирались запускать плагин, мониторящий сервис в контейнере как раз в залоченном треде с setns, но это сломалось на первом же http клиенте.
Так как влиять на планировщик go у нас нет возможности, мы стали искать способ оставить в треде только код, не приводящий к порождению новых тредов.
Мы заметили, что если сразу после setns делать tcp коннект, то он проходит в 100% случаев, и если потом выйти из namespace и отпустить лок на тред, открытое соединение продолжает работать (я затрудняюсь объяснить, почему это работает).
Дальше задача свелась к тому, чтобы всем библиотеками для работы с различными сервисами, которые мы мониторим, подсунуть наш Dialer
(функцию, отвечающую за TCP connect):
client := redis.NewClient(&redis.Options{
Dialer: func() (net.Conn, error) {
return utils.DialTimeoutNs("tcp", params.Address, params.NetNs, redisTimeout)
},
ReadTimeout: redisTimeout,
WriteTimeout: redisTimeout,
Password: params.Password,
})
mysql.RegisterDial("netns", func(addr string) (net.Conn, error) {
return utils.DialTimeoutNs("tcp", addr, params.NetNs, connectTimeout)
})
db, err = sql.Open("mysql",
fmt.Sprintf("netns(%s)/?timeout=%s&readTimeout=%s&writeTimeout=%s",
params.Address, connectTimeout, readTimeout, writeTimeout))
database/sql
:func init() {
sql.Register("postgres+netns", &drv{})
}
type drv struct{}
type nsDialer struct {
netNs string
}
func (d nsDialer) Dial(ntw, addr string) (net.Conn, error) {
return utils.DialTimeoutNs(ntw, addr, d.netNs, connectTimeout)
}
func (d nsDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) {
return utils.DialTimeoutNs(ntw, addr, d.netNs, timeout)
}
func (d *drv) Open(name string) (driver.Conn, error) {
parts := strings.SplitN(name, "|", 2)
netNs := ""
if len(parts) == 2 {
netNs = parts[0]
name = parts[1]
}
return pq.DialOpen(nsDialer{netNs}, name)
}
потом вызываем свой драйвер:
dsn := fmt.Sprintf("%s|postgres://%s:%s@%s/%s",
p.NetNs, p.User, p.Password, p.Address, dbName)
db, err := sql.Open("postgres+netns", dsn)
Оглядываясь назад, мы не пожалели, что выбрали вариант с setns, так этот же код недавно прекрасно сработал у клиента с lxc.
Единственный незакрытый на данный момент сервис — это jvm в контейнере, но это совсем другая история.
Метки: author NikolaySivko системное программирование go блог компании okmeter.io мониторинг golang setns docker |
[Из песочницы] Немного о безопасности терминалов в МФЦ |
Метки: author gdt тестирование it-систем разработка под windows информационная безопасность терминалы мфц безопасность |
[Из песочницы] Немного о безопасности терминалов в МФЦ |
Метки: author gdt тестирование it-систем разработка под windows информационная безопасность терминалы мфц безопасность |
Hackspace Capital: от World of Tanks к технологическим инновациям |
Метки: author megapost финансы в it wot |
Hackspace Capital: от World of Tanks к технологическим инновациям |
Метки: author megapost финансы в it wot |
Пятничное: пузырь ICO |
Сегодня можно увидеть устремившийся в бесконечность почти вертикальный график роста объема капитала, услышать яростную критику от скептиков и возвышенную похвалу от оптимистов. Признаться, я отношу себя к оптимистам, хотя до последнего времени ненавидел пузыри, относился к ним как к форме помешательства или одержимости. Но, обратившись к здравому смыслу, я изменил свое мнение на противоположное. Далее я расскажу как перестал бояться пузырей и полюбил вот это все.
Читать дальше ->
Метки: author rumkin финансы в it ico инвестиции новые технологии блокчейн пятница |
Пятничное: пузырь ICO |
Сегодня можно увидеть устремившийся в бесконечность почти вертикальный график роста объема капитала, услышать яростную критику от скептиков и возвышенную похвалу от оптимистов. Признаться, я отношу себя к оптимистам, хотя до последнего времени ненавидел пузыри, относился к ним как к форме помешательства или одержимости. Но, обратившись к здравому смыслу, я изменил свое мнение на противоположное. Далее я расскажу как перестал бояться пузырей и полюбил вот это все.
Читать дальше ->
Метки: author rumkin финансы в it ico инвестиции новые технологии блокчейн пятница |