天空 Blond - AWS
type: channel
link: https://skyblond.info/tag/AWS/
items: 【歪门邪道】在内网环境下使用SSL证书
items: 【歪门邪道】使用AWS记录加密货币的价格

【歪门邪道】在内网环境下使用SSL证书
type: item
date: 2022-01-11T21:22:00+08:00
description: 最近开始尝试一些集群的玩意儿了，主要问题有二：如何通过主机名解析到IP；对于默认提供SSL的服务，证书怎么办？本文将阐述我的解决方法。最近开始搭建Ceph集群了，过程中遇到了两点问题。其中一点就是如果通过主机名来访问其他结点，那么旧必须要修改hosts文件，如果一次搭建还好，可摸索的过程中谁还不翻个车，我重装了6次系统才搞好Ceph集群。其中有不少弯路是因为装完系统之后没有改hosts而排查了半天。我：这怎么就连不上呢主机：有人没配hosts，但我不说是谁另一个问题就是现在大多数服务在启动后都会产生一个自签证书，对于简单的测试还好，可如果要长期运行，自签证书不光用起来麻烦，而且还是很大一个安全隐患——毕竟不能每次都看那个自签CA的公钥有没有变动，但是不检查的话被中间人攻击了也无从得知。如果决定使用自签证书的话，那么每一个服务的CA都不一样，就得在所有访问的设备上安装这个自签CA，并且如果这个自签CA的私钥泄露了，那么对于所有设备都是一个更大的安全隐患。经过一番谷歌搜索和一系列尝试，我自认为找到了一个相对不错的解决办法。以下详述：主机名解析到IP关于这个问题，最简单的解决办法就是利用域名直接解析成内网ip，这样方便又简单，有效避免了频繁改hosts的问题。但是，怎么设置域名呢？经过一番搜索，StackOverflow上无外乎两种声音：利用已有域名自己编造一个域名下面我分别说说这两种方法的利弊。利用已有域名利用已有域名最大的问题就是如何保证内网IP不泄露到公网——假如一个内网主机是192.168.1.1，你把它设置到了某个域名上，那么别人访问这个域名就会访问到对方内网上的主机，如果碰巧的话，可能就是他家的路由器。很明显，这会造成不必要的混乱。最好的办法就是设立一个单独的二级域名，例如internal.skyblond.info，然后在内网上搭建一个DNS服务器用来解析，这样的话公网上不会知道你的node1.internal.skyblond.info，而本地网络中又可以正常解析。而且这种方法的好处就是可以申请通配符SSL证书。至于坏处嘛，就是你得在本地网络上弄个DNS服务器。这个设施对于长期运行且颇具规模的网络来说必不可少，但是对于测试环境，有点杀鸡焉用牛刀的意思了。自己编造一个域名如果你没有域名，或者你的域名太长了，那么最好的办法就是随便编一个域名。一般来说不建议随便编造域名，但是如果一定要编造的话，那么最合理的应该是home.arpa。这个域名最开始被IETF提出，一开始是.home，但是后来改成了home.arpa，因为卖域名的不想把整个.home顶级域名拱手相让。虽然合理，但毕竟是二级域名，用起来的话就变成了三级域名了，何况都已经编造了，干嘛不编一个顶级域名呢？一般来说并不建议随意编造域名，即便是目前没有使用的顶级域名，在未来一旦分配到某个用途上，那对应的本地网络上的运维可能就要骂街了——鬼知道会不会有人用了你现在用的域名，万一发生冲突，谁知道会引发什么奇怪的bug。不过话是这么说，当你一定需要编造域名的话，最好符合行业标准。我们来看看AWS和GCP是怎么做的：Amazon EC2 instance hostname types：IP address-based namingWhen you launch an EC2 instance with IP address-based naming (IPBN), the guest OS hostname is configured to use the private IPv4 addressFormat for an instance in us-east-1: private-ipv4-address.ec2.internalExample: ip-10-24-34-0.ec2.internalFormat for an instance in any other AWS Region: private-ipv4-address.region.compute.internalExample: ip-10-24-34-0.us-west-2.compute.internalResource-based namingResource-based naming (RBN) is used automatically when you launch EC2 instances in IPv6-only subnets. RBN is not selected by default when you launch an instance in dual-stack (IPv4+IPv6) subnets, but it is an option that you can sele…

【歪门邪道】使用AWS记录加密货币的价格
type: item
date: 2021-12-08T10:25:20+08:00
description: 本文将记述如何使用AWS的相关服务完成定时抓取各种加密货币的实时价格，并将它们存入数据库中供以后查询。最近很关注NEO这个区块链，一方面因为他是起源于国内，另一方面则是因为它比比特币环保，比以太坊便于开发，整个社区环境还算不错。前几天尝试了一下他们新主网上的DEX，叫Flamingo，感觉还不错。虽然我不是资深炒币人士，但是偶尔还是有使用加密货币的需求（主要是作为汽油费使用），所以对于历史价格有一个相对直观的把握，有助于我判断到底什么时候买币会更划算一些。而目前现有的各大交易所，大多数都将于2021年12月31日清退中国大陆用户，即便是不清退的，对于历史数据也比较有限，不能提供很好的查询服务。因此我决定自己写一个。实现这个需求的大体思路就是利用Java请求一些公开的API来获取各种加密货币的价格，然后整理出我想要的数据之后存到AWS上，同时尽可能降低成本。所以写一个服务长期运行是不现实了，AWS的EC2贵的要死，为这个专门买一个Lightsail也不划算，所以我决定使用Fargate来达到容器化部署，通过EventBridge实现定时调用，然后将数据存储到DynamoDB中。这样一来整个过程只有Fargate那块是按实际占用时间收费，其他的都是按量付费，例如DynamoDB只是按请求数和存储量收费，具体的每月成本可以看文末的分析。下面先说说程序怎么写。程序程序是比较核心的组件，当Fargate容器拉起来之后，AWS的任务就完成了。我们需要在程序中计算关注的币种的价格。比较无聊的部分就不说了，无非就是调API拿数据，这里我用的是实时价格，因为它可以一次性返回某一时刻，币安上所有交易对的价格数据，这样的话一次HTTP调用，剩下的就用程序找就完了。为了实现最大的灵活性，我并没有采取直接查交易对的方法，因为有些币种，例如GAS，就只有和BTC的交易对，如果要查询GAS的USDT或BUSD价格，那就废了。所以得想办法搜索出一种可能的路径，于是就有了如下的算法： private List<String> resolvePath(LinkedList<String> path, String toSymbol, Map<String, String> priceMap) { String currentSymbol = path.getLast(); if (priceMap.containsKey(currentSymbol + toSymbol)) { path.add(toSymbol); return path; } int currentPathLength = path.size(); var option = priceMap.keySet().stream() // related pair .filter(it -> it.startsWith(currentSymbol)) // get the symbol .map(it -> it.substring(currentSymbol.length())) // not a loop .filter(it -> !path.contains(it)) .map(it -> { var tempPath = new LinkedList<>(path.subList(0, currentPathLength)); tempPath.add(it); return resolvePath(tempPath, toSymbol, priceMap); }) .filter(Objects::nonNull) .min(Comparator.comparingInt(List::size)); if (option.isEmpty()) { // not found return null; } return option.get(); }这个是一个简单的深度优先搜索，具有三个入参：path：当前搜索出的路径toSymbol：目标币种的符号priceMap：全部交易对的价格数据初始时path就是源币种的符号，我们以A币为例（虚拟的，万一以后真有这个币了，跟它没关系，下面的END也一样），初始就是一个[A]。首先我们过一遍所有交易对，如果有A/END，那万事大吉，搜索结束。如果没有，那就找出有哪些相关的交易对，例如A/BTC，A/ETH之类的，然后提取出他们的名字，然后要检查这个币种是否已经搜索过了。搜索过就不要在尝试了，不然就成环了。对于剩下的不会成环的，挨个加到路径里看看行不行就是了。例如选定BTC进行尝试，那么递归调用的入参就变成了[A, BTC]，那么把A换成BTC，再重复这个过程就可以了，最终的结果是：要么找到了交易对；要么搜索遍了所有币种，都没找到一个路径。前者直接返回…